/* * 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; }