blob: de262bd34d90438a3299ea4236427c09e9b61dd8 [file] [log] [blame]
/********************************************************************************
* Marvell GPL License Option
*
* 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 "config.h"
#include "tee_client_util.h"
#include "tz_client_api.h"
#include "log.h"
#ifndef __KERNEL__
#include <string.h>
#else
#include <linux/string.h>
#endif
uint32_t TEEC_CallParamToComm(int tzc,
union tee_param *commParam,
TEEC_Parameter *param, uint32_t paramType)
{
uint32_t t = paramType & 0x7; /* covented paramType for communication */
uint32_t attr;
switch (paramType) {
case TEEC_VALUE_INPUT:
case TEEC_VALUE_OUTPUT:
case TEEC_VALUE_INOUT:
commParam->value.a = param->value.a;
commParam->value.b = param->value.b;
break;
case TEEC_MEMREF_TEMP_INPUT:
case TEEC_MEMREF_TEMP_OUTPUT:
case TEEC_MEMREF_TEMP_INOUT:
commParam->memref.buffer = (uint32_t)((unsigned long)
tzc_get_mem_info(tzc, param->tmpref.buffer, &attr));
commParam->memref.size = param->tmpref.size;
break;
case TEEC_MEMREF_WHOLE:
t = TEE_PARAM_TYPE_MEMREF_INOUT;
commParam->memref.buffer = (uint32_t)((unsigned long)
param->memref.parent->phyAddr);
commParam->memref.size = param->memref.parent->size;
break;
case TEEC_MEMREF_PARTIAL_INPUT:
case TEEC_MEMREF_PARTIAL_OUTPUT:
case TEEC_MEMREF_PARTIAL_INOUT:
commParam->memref.buffer = (uint32_t)((unsigned long)
(param->memref.parent->phyAddr +
param->memref.offset));
commParam->memref.size = param->memref.size;
break;
}
return t;
}
uint32_t TEEC_CallCommToParam(TEEC_Parameter *param,
union tee_param *commParam,
uint32_t paramType)
{
uint32_t t = paramType & 0x7; /* covented paramType for communication */
switch (paramType) {
case TEEC_VALUE_INPUT:
case TEEC_VALUE_OUTPUT:
case TEEC_VALUE_INOUT:
param->value.a = commParam->value.a;
param->value.b = commParam->value.b;
break;
case TEEC_MEMREF_TEMP_OUTPUT:
case TEEC_MEMREF_TEMP_INOUT:
param->tmpref.size = commParam->memref.size;
break;
case TEEC_MEMREF_WHOLE:
case TEEC_MEMREF_PARTIAL_OUTPUT:
case TEEC_MEMREF_PARTIAL_INOUT:
param->memref.size = commParam->memref.size;
break;
}
return t;
}
uint32_t TEEC_CallbackCommToParam(TEEC_Parameter *param,
union tee_param *commParam,
uint32_t paramType)
{
uint32_t t = paramType & 0x7; /* covented paramType for communication */
switch (paramType) {
case TEE_PARAM_TYPE_VALUE_INPUT:
case TEE_PARAM_TYPE_VALUE_OUTPUT:
case TEE_PARAM_TYPE_VALUE_INOUT:
param->value.a = commParam->value.a;
param->value.b = commParam->value.b;
break;
case TEE_PARAM_TYPE_MEMREF_INPUT:
case TEE_PARAM_TYPE_MEMREF_OUTPUT:
case TEE_PARAM_TYPE_MEMREF_INOUT:
param->tmpref.buffer = (void *)((unsigned long)
commParam->memref.buffer);
param->tmpref.size = commParam->memref.size;
break;
}
return t;
}
uint32_t TEEC_CallbackParamToComm(union tee_param *commParam,
TEEC_Parameter *param, uint32_t paramType)
{
uint32_t t = paramType & 0x7; /* covented paramType for communication */
switch (paramType) {
case TEE_PARAM_TYPE_VALUE_INPUT:
case TEE_PARAM_TYPE_VALUE_OUTPUT:
case TEE_PARAM_TYPE_VALUE_INOUT:
commParam->value.a = param->value.a;
commParam->value.b = param->value.b;
break;
case TEE_PARAM_TYPE_MEMREF_INPUT:
case TEE_PARAM_TYPE_MEMREF_OUTPUT:
case TEE_PARAM_TYPE_MEMREF_INOUT:
commParam->memref.buffer = (uint32_t)((unsigned long)param->tmpref.buffer);
commParam->memref.size = param->tmpref.size;
break;
}
return t;
}
/*
* it will fill cmd->param_types and cmd->params[4]
*/
TEEC_Result TEEC_CallOperactionToCommand(int tzc,
struct tee_comm_param *cmd,
uint32_t cmdId, TEEC_Operation *operation)
{
int i, t[4];
if (!cmd) {
error("illigle arguments\n");
return TEEC_ERROR_BAD_PARAMETERS;
}
memset(cmd, 0, TEE_COMM_PARAM_BASIC_SIZE);
cmd->cmd_id = cmdId;
if (!operation) {
cmd->param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
goto out;
}
/* travel all the 4 parameters */
for (i = 0; i < 4; i++) {
int paramType = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
t[i] = TEEC_CallParamToComm(tzc,
&cmd->params[i],
&operation->params[i], paramType);
}
cmd->param_types = TEE_PARAM_TYPES(t[0], t[1], t[2], t[3]);
out:
trace("invoke command 0x%08x\n", cmd->cmd_id);
return TEEC_SUCCESS;
}
/*
* it will copy data from cmd->params[4] to operation->params[4]
*/
TEEC_Result TEEC_CallCommandToOperaction(TEEC_Operation *operation,
struct tee_comm_param *cmd)
{
int i;
if (!operation)
return TEEC_SUCCESS;
if (!cmd) {
error("illigle arguments\n");
return TEEC_ERROR_BAD_PARAMETERS;
}
/* travel all the 4 param */
for (i = 0; i < 4; i++) {
int paramType = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
TEEC_CallCommToParam(&operation->params[i],
&cmd->params[i],
paramType);
}
return TEEC_SUCCESS;
}
/*
* it will copy data from cmd->params[4] to operation->params[4]
*/
TEEC_Result TEEC_CallbackCommandToOperaction(TEEC_Operation *operation,
struct tee_comm_param *cmd)
{
int i, t[4];
if (!operation || !cmd) {
error("illigle arguments\n");
return TEEC_ERROR_BAD_PARAMETERS;
}
memset(operation, 0, sizeof(*operation));
/* travel all the 4 param */
for (i = 0; i < 4; i++) {
int paramType = TEE_PARAM_TYPE_GET(cmd->param_types, i);
t[i] = TEEC_CallbackCommToParam(&operation->params[i],
&cmd->params[i],
paramType);
}
operation->paramTypes = TEEC_PARAM_TYPES(t[0], t[1], t[2], t[3]);
return TEEC_SUCCESS;
}
/*
* it will fill cmd->param_types and cmd->params[4]
*/
TEEC_Result TEEC_CallbackOperactionToCommand(struct tee_comm_param *cmd,
TEEC_Operation *operation)
{
int i;
if (!cmd) {
error("illigle arguments\n");
return TEEC_ERROR_BAD_PARAMETERS;
}
/* travel all the 4 parameters */
for (i = 0; i < 4; i++) {
int paramType = TEE_PARAM_TYPE_GET(cmd->param_types, i);
TEEC_CallbackParamToComm(&cmd->params[i],
&operation->params[i], paramType);
}
trace("invoke command 0x%08x\n", cmd->cmd_id);
return TEEC_SUCCESS;
}
#define TEEC_PROPERTY_VALUE_MAX 64
typedef struct TEEC_PropNode {
char *name;
char *value;
struct TEEC_PropNode *next;
} TEEC_PropNode;
struct TEEC_Property {
TEEC_PropNode *head;
};
/*
* create the property handle, initialize the head to NULL,
*/
TEEC_Result TEEC_CreateProperty(TEEC_Property **property)
{
if (NULL == property)
return TEEC_ERROR_BAD_PARAMETERS;
*property = (TEEC_Property *) tzc_malloc(sizeof(TEEC_Property));
if (NULL == *property) {
error("malloc memory for Prop_Handle failed\n");
return TEEC_ERROR_OUT_OF_MEMORY;
}
(*property)->head = NULL;
return TEEC_SUCCESS;
}
static TEEC_PropNode **teec_find_property(TEEC_Property *property,
const char *name)
{
TEEC_PropNode **current = &property->head;
while (NULL != *current) {
if (!strcmp((*current)->name, name))
return current;
current = &(*current)->next;
}
return current;
}
TEEC_Result TEEC_AddPropertyString(TEEC_Property *property,
const char *name, const char *value)
{
TEEC_PropNode **current;
if ((NULL == property) || (NULL == name))
return TEEC_ERROR_BAD_PARAMETERS;
if (NULL == value)
value = ""; /* give a default value if NULL */
current = teec_find_property(property, name);
if (*current)
return TEEC_ERROR_EXCESS_DATA; /* ITEM duplicated */
*current = (TEEC_PropNode *) tzc_malloc(sizeof(TEEC_PropNode));
if (!*current)
return TEEC_ERROR_OUT_OF_MEMORY;
(*current)->name = tzc_strdup(name);
if (NULL == (*current)->name) {
tzc_free(*current);
*current = NULL;
return TEEC_ERROR_OUT_OF_MEMORY;
}
(*current)->value = tzc_strdup(value);
if (NULL == (*current)->value) {
tzc_free((*current)->name);
tzc_free(*current);
*current = NULL;
return TEEC_ERROR_OUT_OF_MEMORY;
}
(*current)->next = NULL;
return TEEC_SUCCESS;
}
TEEC_Result TEEC_AddPropertyUint32(TEEC_Property *property,
const char *name, uint32_t value)
{
char str[TEEC_PROPERTY_VALUE_MAX];
if ((NULL == property) || (NULL == name))
return TEEC_ERROR_BAD_PARAMETERS;
sprintf(str, "%u", value);
return TEEC_AddPropertyString(property, name, str);
}
TEEC_Result TEEC_GetPropertyString(TEEC_Property *property,
char const *name, char *value, uint32_t valueLen)
{
TEEC_PropNode **current;
if ((NULL == property) || (NULL == name) || (NULL == value))
return TEEC_ERROR_BAD_PARAMETERS;
current = teec_find_property(property, name);
if (NULL == *current)
return TEEC_ERROR_ITEM_NOT_FOUND;
if (strlen((*current)->value) + 1 < valueLen ) {
strcpy(value, (*current)->value);
return TEEC_SUCCESS;
}
return TEEC_ERROR_SHORT_BUFFER;
}
TEEC_Result TEEC_GetPropertyUint32(TEEC_Property *property, const char *name,
uint32_t *value)
{
char str[TEEC_PROPERTY_VALUE_MAX];
TEEC_Result res = TEEC_SUCCESS;
if ((NULL == property) || (NULL == name) || (NULL == value))
return TEEC_ERROR_BAD_PARAMETERS;
res = TEEC_GetPropertyString(property, name, str, TEEC_PROPERTY_VALUE_MAX);
if (res == TEEC_SUCCESS)
*value = tzc_strtoul(str, 0, 0);
return res;
}
TEEC_Result TEEC_DeleteProperty(TEEC_Property *property, const char *name)
{
TEEC_PropNode **ptr, *next;
if ((NULL == property) || (NULL == name))
return TEEC_ERROR_BAD_PARAMETERS;
ptr = &property->head;
while (NULL != *ptr) {
if (!strcmp((*ptr)->name, name)) {
next = (*ptr)->next;
tzc_free((*ptr)->name);
tzc_free((*ptr)->value);
tzc_free(*ptr);
*ptr = next;
return TEEC_SUCCESS;
}
}
return TEEC_ERROR_ITEM_NOT_FOUND;
}
TEEC_Result TEEC_DestroyProperty(TEEC_Property *property)
{
TEEC_PropNode *current, *next;
if (NULL == property)
return TEEC_ERROR_BAD_PARAMETERS;
current = property->head;
while (NULL != current) {
next = current->next;
tzc_free(current->name);
tzc_free(current->value);
tzc_free(current);
current = next;
}
tzc_free(property);
return TEEC_SUCCESS;
}