static void _update_client_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io, struct tee_cmd *cmd) { int idx; struct tee_context *ctx; BUG_ON(!cmd_io); BUG_ON(!cmd_io->op); BUG_ON(!cmd_io->op->params); BUG_ON(!cmd); BUG_ON(!sess->ctx); ctx = sess->ctx; dev_dbg(_DEV_TEE, "%s: returned err=0x%08x (origin=%d)\n", __func__, cmd->err, cmd->origin); cmd_io->origin = cmd->origin; cmd_io->err = cmd->err; if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE)) return; for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) { int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx); int offset = 0; size_t size; size_t size_new; TEEC_SharedMemory *parent; dev_dbg(_DEV_TEE, "%s: id %d type %d\n", __func__, idx, type); BUG_ON(!tee_session_is_supported_type(sess, type)); switch (type) { case TEEC_NONE: case TEEC_VALUE_INPUT: case TEEC_MEMREF_TEMP_INPUT: case TEEC_MEMREF_PARTIAL_INPUT: break; case TEEC_VALUE_OUTPUT: case TEEC_VALUE_INOUT: dev_dbg(_DEV_TEE, "%s: a=%08x, b=%08x\n", __func__, cmd->param.params[idx].value.a, cmd->param.params[idx].value.b); if (tee_copy_to_user (ctx, &cmd_io->op->params[idx].value, &cmd->param.params[idx].value, sizeof(cmd_io->op->params[idx].value))) dev_err(_DEV_TEE, "%s:%d: can't update %d result to user\n", __func__, __LINE__, idx); break; case TEEC_MEMREF_TEMP_OUTPUT: case TEEC_MEMREF_TEMP_INOUT: /* Returned updated size */ size_new = cmd->param.params[idx].shm->size_req; if (size_new != cmd_io->op->params[idx].tmpref.size) { dev_dbg(_DEV_TEE, "Size has been updated by the TA %zd != %zd\n", size_new, cmd_io->op->params[idx].tmpref.size); tee_put_user(ctx, size_new, &cmd_io->op->params[idx].tmpref.size); } dev_dbg(_DEV_TEE, "%s: tmpref %p\n", __func__, cmd->param.params[idx].shm->kaddr); /* ensure we do not exceed the shared buffer length */ if (size_new > cmd_io->op->params[idx].tmpref.size) dev_err(_DEV_TEE, " *** Wrong returned size from %d:%zd > %zd\n", idx, size_new, cmd_io->op->params[idx].tmpref.size); else if (tee_copy_to_user (ctx, cmd_io->op->params[idx].tmpref.buffer, cmd->param.params[idx].shm->kaddr, size_new)) dev_err(_DEV_TEE, "%s:%d: can't update %d result to user\n", __func__, __LINE__, idx); break; case TEEC_MEMREF_PARTIAL_OUTPUT: case TEEC_MEMREF_PARTIAL_INOUT: case TEEC_MEMREF_WHOLE: parent = &cmd->param.c_shm[idx]; if (type == TEEC_MEMREF_WHOLE) { offset = 0; size = parent->size; } else { offset = cmd_io->op->params[idx].memref.offset; size = cmd_io->op->params[idx].memref.size; } /* Returned updated size */ size_new = cmd->param.params[idx].shm->size_req; tee_put_user(ctx, size_new, &cmd_io->op->params[idx].memref.size); /* * If we allocated a tmpref buffer, * copy back data to the user buffer */ if (is_mapped_temp(cmd->param.params[idx].shm->flags)) { if (parent->buffer && offset + size_new <= parent->size) { if (tee_copy_to_user(ctx, parent->buffer + offset, cmd->param.params[idx].shm->kaddr, size_new)) dev_err(_DEV_TEE, "%s: can't update %d data to user\n", __func__, idx); } } break; default: BUG_ON(1); } } }
static void _update_client_tee_cmd(struct tee_session *sess, struct tee_cmd_io *cmd_io, struct tee_cmd *cmd) { int idx; struct tee_context *ctx; BUG_ON(!cmd_io); BUG_ON(!cmd_io->op); BUG_ON(!cmd_io->op->params); BUG_ON(!cmd); BUG_ON(!sess->ctx); ctx = sess->ctx; dev_dbg(_DEV_TEE, "%s: returned err=0x%08x (origin=%d)\n", __func__, cmd->err, cmd->origin); cmd_io->origin = cmd->origin; cmd_io->err = cmd->err; if (cmd->param.type_original == TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE)) return; for (idx = 0; idx < TEEC_CONFIG_PAYLOAD_REF_COUNT; ++idx) { int type = TEEC_PARAM_TYPE_GET(cmd->param.type_original, idx); dev_dbg(_DEV_TEE, "%s: id %d type %d\n", __func__, idx, type); BUG_ON(!tee_session_is_supported_type(sess, type)); switch (type) { case TEEC_NONE: case TEEC_VALUE_INPUT: case TEEC_MEMREF_TEMP_INPUT: case TEEC_MEMREF_PARTIAL_INPUT: break; case TEEC_VALUE_OUTPUT: case TEEC_VALUE_INOUT:{ dev_dbg(_DEV_TEE, "%s: a=%08x, b=%08x\n", __func__, cmd->param.params[idx].value.a, cmd->param.params[idx].value.b); if (tee_copy_to_user (ctx, &cmd_io->op->params[idx].value, &cmd->param.params[idx].value, sizeof(cmd_io->op->params[idx].value))) dev_err(_DEV_TEE, "%s:%d: can't update %d result to user\n", __func__, __LINE__, idx); break; } case TEEC_MEMREF_TEMP_OUTPUT: case TEEC_MEMREF_TEMP_INOUT:{ /* Returned updated size */ size_t size = cmd->param.params[idx].shm->size_req; if (size != cmd_io->op->params[idx].tmpref.size) { dev_dbg(_DEV_TEE, "Size has been updated by the TA %zu != %zu\n", size, cmd_io->op->params[idx].tmpref. size); tee_put_user(ctx, size, &cmd_io->op->params[idx]. tmpref.size); } BUG_ON(!cmd->param.params[idx].shm); BUG_ON(! (cmd->param.params[idx].shm-> flags & TEE_SHM_TEMP)); dev_dbg(_DEV_TEE, "%s: tmpref %p\n", __func__, cmd->param.params[idx].shm->kaddr); /* ensure we do not exceed * the shared buffer length */ if (size > cmd_io->op->params[idx].tmpref.size) dev_err(_DEV_TEE, " *** Wrong returned size from %d:%zu > %zu\n", idx, size, cmd_io->op->params[idx].tmpref. size); else if (tee_copy_to_user (ctx, cmd_io->op->params[idx].tmpref.buffer, cmd->param.params[idx].shm->kaddr, size)) dev_err(_DEV_TEE, "%s:%d: can't update %d result to user\n", __func__, __LINE__, idx); break; } case TEEC_MEMREF_WHOLE:{ /* Returned updated size */ size_t size = cmd->param.params[idx].shm->size_req; if (size != cmd_io->op->params[idx].memref.size) { dev_dbg(_DEV_TEE, "Size has been updated by the TA %zu != %zu\n", size, cmd_io->op->params[idx].memref. size); tee_put_user(ctx, size, &cmd_io->op->params[idx]. memref.size); } /* ensure we do not exceed * the shared buffer length */ if (size > cmd->param.c_shm[idx].size) dev_err(_DEV_TEE, " *** Wrong returned size from %d:%zu > %zu\n", idx, size, cmd->param.c_shm[idx].size); else if ((cmd->param.params[idx].shm->flags & (TEE_SHM_MAPPED | TEE_SHM_TEMP)) == (TEE_SHM_MAPPED | TEE_SHM_TEMP)) { BUG_ON(!cmd->param.c_shm[idx].buffer); BUG_ON(!cmd->param.c_shm[idx].size > 0); dev_dbg(_DEV_TEE, "%s: whole %p\n", __func__, cmd->param.params[idx].shm-> kaddr); if (tee_copy_to_user (ctx, cmd->param.c_shm[idx].buffer, cmd->param.params[idx].shm->kaddr, size)) dev_err(_DEV_TEE, "%s: can't update %d result to user\n", __func__, idx); } break; } case TEEC_MEMREF_PARTIAL_OUTPUT: case TEEC_MEMREF_PARTIAL_INOUT:{ int offset = cmd_io->op->params[idx].memref.offset; /* Returned updated size */ size_t size = cmd->param.params[idx].shm->size_req; if (size != cmd_io->op->params[idx].memref.size) { dev_dbg(_DEV_TEE, "Size has been updated by the TA %zu != %zu\n", size, cmd_io->op->params[idx].memref. size); tee_put_user(ctx, size, &cmd_io->op->params[idx]. memref.size); } /* ensure we do not exceed * the shared buffer length */ if ((offset + size) > cmd->param.c_shm[idx].size) dev_err(_DEV_TEE, " *** Wrong returned size from %d:%d +%zu > %zu\n", idx, offset, size, cmd->param.c_shm[idx].size); /* If we allocated a tmpref buffer, * copy back data to the user buffer */ else if ((cmd->param.params[idx].shm->flags & (TEE_SHM_MAPPED | TEE_SHM_TEMP)) == (TEE_SHM_MAPPED | TEE_SHM_TEMP)) { BUG_ON(!cmd->param.c_shm[idx].buffer); BUG_ON(!cmd->param.c_shm[idx].size > 0); if (tee_copy_to_user (ctx, cmd->param.c_shm[idx].buffer + offset, cmd->param.params[idx].shm->kaddr, size)) dev_err(_DEV_TEE, "%s: can't update %d result to user\n", __func__, idx); } break; } default: BUG_ON(1); } } }