blob: fd8e7f5b31d7542b7d7644d5a826d5973cdcb977 [file] [log] [blame]
/*
* Copyright (c) [2009-2013] Marvell International Ltd. and its affiliates.
* All rights reserved.
* This software file (the "File") is owned and distributed by Marvell
* International Ltd. and/or its affiliates ("Marvell") under the following
* licensing terms.
* If you received this File from Marvell, you may opt to use, redistribute
* and/or modify this File in accordance with the terms and conditions of
* the General Public License Version 2, June 1991 (the "GPL License"), a
* copy of which is available along with the File in the license.txt file
* or by writing to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 or on the worldwide web at
* http://www.gnu.org/licenses/gpl.txt. THE FILE IS DISTRIBUTED AS-IS,
* WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
* DISCLAIMED. The GPL License provides additional details about this
* warranty disclaimer.
*/
#include "tee_cm_internal.h"
#include "tee_cm.h"
/* variables */
void *in_header = NULL;
void *in_buf = NULL; /* rb data buffer */
uint32_t in_buf_size = 0;
void *out_header = NULL;
void *out_buf = NULL; /* rc data buffer */
uint32_t out_buf_size = 0;
/* if wr idx wrap around and behind rd idx, this is min space to reserved */
#define BAR_SIZE (4)
/*** facility functions/macros ***/
extern int32_t *_cm_in_read_idx(void);
extern int32_t *_cm_in_write_idx(void);
extern int32_t *_cm_out_read_idx(void);
extern int32_t *_cm_out_write_idx(void);
#define IN_RD_IDX (*_cm_in_read_idx()) /* RB, read_index */
#define IN_WR_IDX (*_cm_in_write_idx()) /* RB, wirte_index */
#define OUT_RD_IDX (*_cm_out_read_idx()) /* RC, read_index */
#define OUT_WR_IDX (*_cm_out_write_idx()) /* RC, write_index */
extern void cm_call_smi(void *arg);
extern int32_t _cm_get_out_write_idx(void);
extern void _cm_update_out_write_idx(int32_t idx);
/* get out empty size */
uint32_t _out_empty_size(void)
{
uint32_t ret = 0;
int32_t delta = OUT_WR_IDX - OUT_RD_IDX;
if (delta >= 0) /* data size */
ret = out_buf_size - (delta) - BAR_SIZE;
else /* data size */
ret = out_buf_size - (delta + out_buf_size) - BAR_SIZE;
return ret;
}
/* get in data size */
uint32_t _in_data_size(void)
{
uint32_t ret = 0;
int32_t delta = IN_WR_IDX - IN_RD_IDX;
if (delta >= 0)
ret = delta;
else
ret = in_buf_size - delta - BAR_SIZE;
return ret;
}
/* out writing */
void _out_write(int8_t *buf, uint32_t len, int32_t *idx)
{
uint32_t end;
OSA_ASSERT(len < out_buf_size);
end = (uint32_t)(*idx) + len;
if (end > out_buf_size) {
uint32_t remained_sz;
uint32_t current_sz;
remained_sz = end - out_buf_size;
current_sz = out_buf_size - (uint32_t)(*idx);
memcpy(out_buf + *idx, buf, current_sz);
memcpy(out_buf, buf + current_sz, remained_sz);
*idx = remained_sz;
} else {
memcpy(out_buf + *idx, buf, len);
*idx = end;
}
}
/* in reading */
void _in_read(int8_t *buf, uint32_t len, int32_t *idx)
{
uint32_t end;
OSA_ASSERT(len < in_buf_size);
end = (uint32_t)(*idx) + len;
if (end > in_buf_size) {
uint32_t remained_sz;
uint32_t current_sz;
remained_sz = end - in_buf_size;
current_sz = in_buf_size - (uint32_t)(*idx);
memcpy(buf, in_buf + *idx, current_sz);
memcpy(buf + current_sz, in_buf, remained_sz);
*idx = remained_sz;
} else {
memcpy(buf, in_buf + *idx, len);
*idx = end;
}
}
bool tee_cm_send_data(uint8_t *buf)
{
bool ret = true;
uint32_t size;
/* int32_t idx = OUT_WR_IDX; */
int32_t idx;
tee_msg_head_t *tee_msg_head;
tee_msg_head = (tee_msg_head_t *)buf;
size = sizeof(tee_msg_head_t) + tee_msg_head->msg_sz;
#if 0 /* zyq 20130207, find the bugs with RB and RC */
/* check if there is enough space */
if (_out_empty_size() < size)
return false;
#endif
idx = _cm_get_out_write_idx();
/* write caller's data */
_out_write((int8_t *)buf, size, &idx);
/* set out write index */
_cm_update_out_write_idx(idx);
/* OUT_WR_IDX = idx; */
return ret;
}
uint32_t tee_cm_get_data_size(void)
{
uint32_t size_in_data = _in_data_size();
tee_msg_head_t tee_msg_head;
uint32_t size;
int32_t idx = IN_RD_IDX;
if (size_in_data < sizeof(tee_msg_head_t))
return 0;
_in_read((int8_t *)(&tee_msg_head), sizeof(tee_msg_head_t), &idx);
size = sizeof(tee_msg_head_t) + tee_msg_head.msg_sz;
return size;
}
void tee_cm_recv_data(uint8_t *buf)
{
tee_msg_head_t tee_msg_head;
int32_t idx = IN_RD_IDX;
_in_read((int8_t *)(&tee_msg_head), sizeof(tee_msg_head_t), &idx);
idx = IN_RD_IDX;
/* output data */
_in_read((int8_t *)buf, sizeof(tee_msg_head_t) + tee_msg_head.msg_sz,
&idx);
/* update rb read index */
IN_RD_IDX = idx;
}
void tee_cm_get_recv_buf(void **head)
{
tee_msg_head_t tee_msg_head;
int32_t idx = IN_RD_IDX;
_in_read((int8_t *)(&tee_msg_head), sizeof(tee_msg_head_t), &idx);
*head = tee_msg_head.tee_msg;
}
void tee_cm_smi(uint32_t flag)
{
tee_cm_smi_input_t tee_cm_smi_input;
tee_cm_smi_input.arg0 = flag;
tee_cm_smi_input.arg1 = 0;
tee_cm_smi_input.arg2 = 0;
cm_call_smi(&tee_cm_smi_input);
return;
}
void tee_cm_get_msgm_head(void *msg_head)
{
int32_t idx = IN_RD_IDX;
OSA_ASSERT(msg_head);
_in_read((int8_t *)msg_head, sizeof(tee_msg_head_t), &idx);
return;
}