static int _copy_ta_image(struct tee_session *sess, struct tee_cmd_io *cmd_io, struct tee_cmd *cmd) { int res = -EINVAL; dev_dbg(_DEV_TEE, "%s: > data=%p uuid=%p\n", __func__, cmd_io->data, cmd_io->uuid); if (((cmd_io->data != NULL) && (cmd_io->data_size == 0)) || ((cmd_io->data == NULL) && (cmd_io->data_size != 0))) goto out_failed; if ((cmd_io->data != NULL) && (cmd_io->data_size > 0)) { dev_dbg(_DEV_TEE, "%s: copy DATA image (s=%d)...\n", __func__, cmd_io->data_size); cmd->ta = tee_context_alloc_shm_tmp(sess->ctx, cmd_io->data_size, cmd_io->data, TEEC_MEM_INPUT); if (IS_ERR_OR_NULL(cmd->ta)) goto out_failed; } 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)) goto out_failed; } res = 0; goto out; out_failed: tee_shm_free(cmd->uuid); tee_shm_free(cmd->ta); out: dev_dbg(_DEV_TEE, "%s: < res=%d", __func__, res); return res; }
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; }