static int tee_session_cancel_be(struct tee_session *sess, struct tee_cmd_io *cmd_io) { int ret = -EINVAL; struct tee *tee; struct tee_cmd cmd; BUG_ON(!sess || !sess->ctx || !sess->ctx->tee); tee = sess->ctx->tee; dev_dbg(_DEV(tee), "%s: > sessid=%08x, cmd=0x%08x\n", __func__, sess->sessid, cmd_io->cmd); ret = _init_tee_cmd(sess, cmd_io, &cmd); if (ret) goto out; ret = tee->ops->cancel(sess, &cmd); out: _release_tee_cmd(sess, &cmd); dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret); return ret; }
int tee_session_invoke_be(struct tee_session *sess, struct tee_cmd_io *cmd_io) { int ret = -EINVAL; struct tee *tee; struct tee_cmd cmd; BUG_ON(!sess || !sess->ctx || !sess->ctx->tee); tee = sess->ctx->tee; dev_dbg(_DEV(tee), "%s: > sessid=%08x, cmd=0x%08x\n", __func__, sess->sessid, cmd_io->cmd); ret = _init_tee_cmd(sess, cmd_io, &cmd); if (ret) goto out; ret = tee->ops->invoke(sess, &cmd); if (!ret) _update_client_tee_cmd(sess, cmd_io, &cmd); else { /* propagate the reason of the error */ cmd_io->origin = cmd.origin; cmd_io->err = cmd.err; } out: _release_tee_cmd(sess, &cmd); dev_dbg(_DEV(tee), "%s: < ret=%d", __func__, ret); return ret; }
static int _init_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io, struct tee_cmd *cmd) { int ret = -EINVAL; dev_dbg(_DEV_TEE, "%s: > set tee_cmd...\n", __func__); memset(cmd, 0, sizeof(struct tee_cmd)); cmd->cmd = cmd_io->cmd; cmd->origin = TEEC_ORIGIN_TEE; cmd->err = TEEC_ERROR_BAD_PARAMETERS; cmd_io->origin = cmd->origin; cmd_io->err = cmd->err; ret = _copy_op(sess, cmd_io, cmd); if (ret) goto out; ret = _copy_ta_image(sess, cmd_io, cmd); out: if (ret) _release_tee_cmd(sess, cmd); dev_dbg(_DEV_TEE, "%s: < ret=%d\n", __func__, ret); return ret; }
static int tee_session_open_be(struct tee_session *sess, struct tee_cmd_io *cmd_io) { int ret = -EINVAL; struct tee *tee; struct tee_cmd cmd; BUG_ON(!sess || !sess->ctx || !sess->ctx->tee); tee = sess->ctx->tee; dev_dbg(_DEV(tee), "%s: > open a new session", __func__); sess->sessid = 0; ret = _init_tee_cmd(sess, cmd_io, &cmd); if (ret) goto out; if (cmd.uuid) { dev_dbg(_DEV(tee), "%s: UUID=%s\n", __func__, _uuid_to_str((TEEC_UUID *) cmd.uuid->kaddr)); } ret = tee->ops->open(sess, &cmd); if (ret == 0) _update_client_tee_cmd(sess, cmd_io, &cmd); else { /* propagate the reason of the error */ cmd_io->origin = cmd.origin; cmd_io->err = cmd.err; } out: _release_tee_cmd(sess, &cmd); dev_dbg(_DEV(tee), "%s: < ret=%d, sessid=%08x", __func__, ret, sess->sessid); return ret; }
static int _init_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io, struct tee_cmd *cmd) { int ret = -EINVAL; int idx; TEEC_Operation op; struct tee_data *param = &cmd->param; struct tee *tee; struct tee_context *ctx; BUG_ON(!sess->ctx); BUG_ON(!sess->ctx->tee); ctx = sess->ctx; tee = sess->ctx->tee; dev_dbg(_DEV(tee), "%s: > sessid=%08x\n", __func__, sess->sessid); memset(cmd, 0, sizeof(struct tee_cmd)); cmd->cmd = cmd_io->cmd; cmd->origin = TEEC_ORIGIN_TEE; cmd->err = TEEC_ERROR_BAD_PARAMETERS; cmd_io->origin = cmd->origin; cmd_io->err = cmd->err; if (tee_context_copy_from_client(ctx, &op, cmd_io->op, sizeof(op))) goto out; cmd->param.type_original = op.paramTypes; for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) { uint32_t offset = 0; uint32_t size = 0; int type = TEEC_PARAM_TYPE_GET(op.paramTypes, idx); switch (type) { case TEEC_NONE: break; case TEEC_VALUE_INPUT: case TEEC_VALUE_OUTPUT: case TEEC_VALUE_INOUT: param->params[idx].value = op.params[idx].value; dev_dbg(_DEV_TEE, "%s: param[%d]:type=%d,a=%08x,b=%08x (VALUE)\n", __func__, idx, type, param->params[idx].value.a, param->params[idx].value.b); break; case TEEC_MEMREF_TEMP_INPUT: case TEEC_MEMREF_TEMP_OUTPUT: case TEEC_MEMREF_TEMP_INOUT: dev_dbg(_DEV_TEE, "> param[%d]:type=%d,buffer=%p,s=%zu (TMPREF)\n", idx, type, op.params[idx].tmpref.buffer, op.params[idx].tmpref.size); param->params[idx].shm = tee_context_create_tmpref_buffer(ctx, op.params[idx].tmpref.size, op.params[idx].tmpref.buffer, type); if (IS_ERR_OR_NULL(param->params[idx].shm)) goto out; dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx, (void *)param->params[idx].shm->paddr, param->params[idx].shm->size_alloc); break; case TEEC_MEMREF_PARTIAL_INPUT: case TEEC_MEMREF_PARTIAL_OUTPUT: case TEEC_MEMREF_PARTIAL_INOUT: case TEEC_MEMREF_WHOLE: if (tee_copy_from_user(ctx, ¶m->c_shm[idx], op.params[idx].memref.parent, sizeof(param->c_shm[idx]))) { goto out; } if (type == TEEC_MEMREF_WHOLE) { offset = 0; size = param->c_shm[idx].size; } else { /* for PARTIAL, check the size */ offset = op.params[idx].memref.offset; size = op.params[idx].memref.size; if (param->c_shm[idx].size < size + offset) { dev_err(_DEV(tee), "A PARTIAL parameter is bigger than the parent %zd < %d + %d\n", param->c_shm[idx].size, size, offset); goto out; } } dev_dbg(_DEV_TEE, "> param[%d]:type=%d,buffer=%p, offset=%d size=%d\n", idx, type, param->c_shm[idx].buffer, offset, size); type = to_memref_type(param->c_shm[idx].flags); if (type == 0) goto out; param->params[idx].shm = tee_shm_get(ctx, ¶m->c_shm[idx], size, offset); if (IS_ERR_OR_NULL(param->params[idx].shm)) { param->params[idx].shm = tee_context_create_tmpref_buffer(ctx, size, param->c_shm[idx].buffer + offset, type); if (IS_ERR_OR_NULL(param->params[idx].shm)) goto out; } dev_dbg(_DEV_TEE, "< %d %p:%zd\n", idx, (void *)param->params[idx].shm->paddr, param->params[idx].shm->size_req); break; default: BUG_ON(1); } param->type |= (type << (idx * 4)); } if (cmd_io->uuid != NULL) { dev_dbg(_DEV_TEE, "%s: copy UUID value...\n", __func__); cmd->uuid = tee_context_alloc_shm_tmp(sess->ctx, sizeof(*cmd_io->uuid), cmd_io->uuid, TEEC_MEM_INPUT); if (IS_ERR_OR_NULL(cmd->uuid)) { ret = -EINVAL; goto out; } } ret = 0; out: if (ret) _release_tee_cmd(sess, cmd); dev_dbg(_DEV_TEE, "%s: < ret=%d\n", __func__, ret); return ret; }