/* * tee_close_session - invoke TEE to close a GP TEE session */ static TEEC_Result tee_close_session(struct tee_session *ts, enum t_cmd_service_id sec_cmd, u32 ta_cmd, u32 param_type, TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT], u32 *origin) { TEEC_Result ret_tee; struct teesmc32_arg *arg32; uintptr_t parg32; arg32 = (typeof(arg32))alloc_tee_arg(&parg32, TEESMC32_GET_ARG_SIZE(0)); if (arg32 == NULL) { free_tee_arg(parg32); return TEEC_ERROR_OUT_OF_MEMORY; } dev_dbg(DEV, "> [%p]\n", (void *)ts->id); memset(arg32, 0, sizeof(*arg32)); arg32->cmd = TEESMC_CMD_CLOSE_SESSION; arg32->session = ts->id; mutex_lock(&e_mutex_teez); call_tee(parg32, arg32); mutex_unlock(&e_mutex_teez); ret_tee = arg32->ret; if (origin) *origin = arg32->ret_origin; free_tee_arg(parg32); dev_dbg(DEV, "< [%p]\n", (void *)ret_tee); return ret_tee; }
/* * tee_invoke_command - invoke TEE to invoke a GP TEE command */ static int tz_invoke(struct tee_session *sess, struct tee_cmd *cmd) { struct tee *tee; struct tee_tz *ptee; int ret = 0; struct teesmc32_arg *arg32; uintptr_t parg32; struct teesmc32_param *params32; BUG_ON(!sess->ctx->tee); BUG_ON(!sess->ctx->tee->priv); tee = sess->ctx->tee; ptee = tee->priv; dev_dbg(DEV, "> sessid %x cmd %x type %x\n", sess->sessid, cmd->cmd, cmd->param.type); if (!CAPABLE(tee)) { dev_dbg(tee->dev, "< not capable\n"); return -EBUSY; } arg32 = (typeof(arg32))alloc_tee_arg(ptee, &parg32, TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT)); if (!arg32) { free_tee_arg(ptee, parg32); return TEEC_ERROR_OUT_OF_MEMORY; } memset(arg32, 0, sizeof(*arg32)); arg32->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; params32 = TEESMC32_GET_PARAMS(arg32); arg32->cmd = TEESMC_CMD_INVOKE_COMMAND; arg32->session = sess->sessid; arg32->ta_func = cmd->cmd; set_params(ptee, params32, cmd->param.type, &cmd->param); call_tee(ptee, parg32, arg32); get_params(&cmd->param, params32); if (arg32->ret != TEEC_ERROR_COMMUNICATION) { cmd->err = arg32->ret; cmd->origin = arg32->ret_origin; } else ret = -EBUSY; free_tee_arg(ptee, parg32); dev_dbg(DEV, "< %x:%d\n", arg32->ret, ret); return ret; }
/* * tee_invoke_command - invoke TEE to invoke a GP TEE command */ static TEEC_Result tee_invoke_command(struct tee_session *ts, enum t_cmd_service_id sec_cmd, uint32_t ta_cmd, uint32_t param_type, TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT], uint32_t *origin) { TEEC_Result ret_tee; struct teesmc32_arg *arg32; uintptr_t parg32; struct teesmc32_param *params32; dev_dbg(DEV, "> [%p] [%d]\n", (void *)ts->id, ta_cmd); arg32 = (typeof(arg32))alloc_tee_arg(&parg32, TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT)); if (!arg32) { free_tee_arg(parg32); return TEEC_ERROR_OUT_OF_MEMORY; } memset(arg32, 0, sizeof(*arg32)); arg32->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; params32 = TEESMC32_GET_PARAMS(arg32); arg32->cmd = TEESMC_CMD_INVOKE_COMMAND; arg32->session = ts->id; arg32->ta_func = ta_cmd; set_params(params32, param_type, params); mutex_lock(&e_mutex_teez); call_tee(parg32, arg32); mutex_unlock(&e_mutex_teez); ret_tee = arg32->ret; get_params(params, params32); if (origin) *origin = arg32->ret_origin; free_tee_arg(parg32); dev_dbg(DEV, "< [%p]\n", (void *)ret_tee); return ret_tee; }
/* * tee_close_session - invoke TEE to close a GP TEE session */ static int tz_close(struct tee_session *sess) { struct tee *tee; struct tee_tz *ptee; int ret = 0; struct teesmc32_arg *arg32; uintptr_t parg32; BUG_ON(!sess->ctx->tee); BUG_ON(!sess->ctx->tee->priv); tee = sess->ctx->tee; ptee = tee->priv; dev_dbg(DEV, "close on sessid=%08x\n", sess->sessid); if (!CAPABLE(tee)) { dev_dbg(tee->dev, "< not capable\n"); return -EBUSY; } arg32 = alloc_tee_arg(ptee, &parg32, TEESMC32_GET_ARG_SIZE(0)); if (arg32 == NULL) { free_tee_arg(ptee, parg32); return TEEC_ERROR_OUT_OF_MEMORY; } dev_dbg(DEV, "> [%x]\n", sess->sessid); memset(arg32, 0, sizeof(*arg32)); arg32->cmd = TEESMC_CMD_CLOSE_SESSION; arg32->session = sess->sessid; call_tee(ptee, parg32, arg32); if (arg32->ret == TEEC_ERROR_COMMUNICATION) ret = -EBUSY; free_tee_arg(ptee, parg32); dev_dbg(DEV, "< %x:%d\n", arg32->ret, ret); return ret; }
/* * tee_cancel_command - invoke TEE to cancel a GP TEE command */ static int tz_cancel(struct tee_session *sess, struct tee_cmd *cmd) { struct tee *tee; struct tee_tz *ptee; int ret = 0; struct teesmc32_arg *arg32; uintptr_t parg32; BUG_ON(!sess->ctx->tee); BUG_ON(!sess->ctx->tee->priv); tee = sess->ctx->tee; ptee = tee->priv; dev_dbg(DEV, "cancel on sessid=%08x\n", sess->sessid); arg32 = alloc_tee_arg(ptee, &parg32, TEESMC32_GET_ARG_SIZE(0)); if (arg32 == NULL) { free_tee_arg(ptee, parg32); return TEEC_ERROR_OUT_OF_MEMORY; } memset(arg32, 0, sizeof(*arg32)); arg32->cmd = TEESMC_CMD_CANCEL; arg32->session = sess->sessid; call_tee(ptee, parg32, arg32); if (arg32->ret == TEEC_ERROR_COMMUNICATION) ret = -EBUSY; free_tee_arg(ptee, parg32); dev_dbg(DEV, "< %x:%d\n", arg32->ret, ret); return ret; }
/* * tee_open_session - invoke TEE to open a GP TEE session */ static int tz_open(struct tee_session *sess, struct tee_cmd *cmd) { struct tee *tee; struct tee_tz *ptee; int ret = 0; struct teesmc32_arg *arg32; struct teesmc32_param *params32; struct teesmc_meta_open_session *meta; uintptr_t parg32; uintptr_t pmeta; size_t num_meta = 1; uint8_t *ta; TEEC_UUID *uuid; BUG_ON(!sess->ctx->tee); BUG_ON(!sess->ctx->tee->priv); tee = sess->ctx->tee; ptee = tee->priv; if (cmd->uuid) uuid = cmd->uuid->kaddr; else uuid = NULL; dev_dbg(tee->dev, "> ta kaddr %p, uuid=%08x-%04x-%04x\n", (cmd->ta) ? cmd->ta->kaddr : NULL, ((uuid) ? uuid->timeLow : 0xDEAD), ((uuid) ? uuid->timeMid : 0xDEAD), ((uuid) ? uuid->timeHiAndVersion : 0xDEAD)); if (!CAPABLE(ptee->tee)) { dev_dbg(tee->dev, "< not capable\n"); return -EBUSY; } /* case ta binary is inside the open request */ ta = NULL; if (cmd->ta) ta = cmd->ta->kaddr; if (ta) num_meta++; arg32 = alloc_tee_arg(ptee, &parg32, TEESMC32_GET_ARG_SIZE( TEEC_CONFIG_PAYLOAD_REF_COUNT + num_meta)); meta = alloc_tee_arg(ptee, &pmeta, sizeof(*meta)); if ((arg32 == NULL) || (meta == NULL)) { free_tee_arg(ptee, parg32); free_tee_arg(ptee, pmeta); return TEEC_ERROR_OUT_OF_MEMORY; } memset(arg32, 0, sizeof(*arg32)); memset(meta, 0, sizeof(*meta)); arg32->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT + num_meta; params32 = TEESMC32_GET_PARAMS(arg32); arg32->cmd = TEESMC_CMD_OPEN_SESSION; params32[0].u.memref.buf_ptr = pmeta; params32[0].u.memref.size = sizeof(*meta); params32[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | TEESMC_ATTR_META | get_cache_attrs(ptee); if (ta) { params32[1].u.memref.buf_ptr = tee_shm_pool_v2p(DEV, ptee->shm_pool, cmd->ta->kaddr); params32[1].u.memref.size = cmd->ta->size_req; params32[1].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | TEESMC_ATTR_META | get_cache_attrs(ptee); } if (uuid != NULL) memcpy(meta->uuid, uuid, TEESMC_UUID_LEN); meta->clnt_login = 0; /* FIXME: is this reliable ? used ? */ params32 += num_meta; set_params(ptee, params32, cmd->param.type, &cmd->param); call_tee(ptee, parg32, arg32); get_params(&cmd->param, params32); if (arg32->ret != TEEC_ERROR_COMMUNICATION) { sess->sessid = arg32->session; cmd->err = arg32->ret; cmd->origin = arg32->ret_origin; } else ret = -EBUSY; free_tee_arg(ptee, parg32); free_tee_arg(ptee, pmeta); dev_dbg(DEV, "< %x:%d\n", arg32->ret, ret); return ret; }
/* * tee_open_session - invoke TEE to open a GP TEE session */ static TEEC_Result tee_open_session(struct tee_session *ts, enum t_cmd_service_id sec_cmd, uint32_t ta_cmd, uint32_t param_type, TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT], uint32_t *origin) { TEEC_Result ret_tee; struct teesmc32_arg *arg32; uintptr_t parg32; struct teesmc32_param *params32; struct teesmc_meta_open_session *meta; uintptr_t pmeta; size_t num_meta = 1; dev_dbg(DEV, "> uuid=%08x-%04x-%04x\n", ((ts->uuid) ? ts->uuid->timeLow : 0xDEAD), ((ts->uuid) ? ts->uuid->timeMid : 0xDEAD), ((ts->uuid) ? ts->uuid-> timeHiAndVersion : 0xDEAD)); if (tee_tz_ready == false) return TEEC_ERROR_BUSY; if (ts->ta) num_meta++; arg32 = (typeof(arg32))alloc_tee_arg(&parg32, TEESMC32_GET_ARG_SIZE( TEEC_CONFIG_PAYLOAD_REF_COUNT + num_meta)); meta = (typeof(meta))alloc_tee_arg(&pmeta, sizeof(*meta)); if ((arg32 == NULL) || (meta == NULL)) { free_tee_arg(parg32); free_tee_arg(pmeta); return TEEC_ERROR_OUT_OF_MEMORY; } memset(arg32, 0, sizeof(*arg32)); memset(meta, 0, sizeof(*meta)); arg32->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT + num_meta; params32 = TEESMC32_GET_PARAMS(arg32); arg32->cmd = TEESMC_CMD_OPEN_SESSION; params32[0].u.memref.buf_ptr = pmeta; params32[0].u.memref.size = sizeof(*meta); params32[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | TEESMC_ATTR_META | get_cache_attrs(); if (ts->ta != NULL) { params32[1].u.memref.buf_ptr = tee_shm_pool_v2p(DEV, TZop.Allocator, ts->ta); params32[1].u.memref.size = ts->tasize; params32[1].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT | TEESMC_ATTR_META | get_cache_attrs(); } if (ts->uuid != NULL) memcpy(meta->uuid, ts->uuid, TEESMC_UUID_LEN); meta->clnt_login = ts->login; set_params(params32 + num_meta, param_type, params); mutex_lock(&e_mutex_teez); call_tee(parg32, arg32); mutex_unlock(&e_mutex_teez); ts->id = arg32->session; ret_tee = arg32->ret; if (origin) *origin = arg32->ret_origin; get_params(params, params32 + num_meta); free_tee_arg(parg32); free_tee_arg(pmeta); dev_dbg(DEV, "< [%d]\n", ret_tee); return ret_tee; }