static void handle_rpc_func_cmd_to_supplicant(struct tee_tz *ptee, struct teesmc32_arg *arg32) { struct teesmc32_param *params; struct tee_rpc_invoke inv; size_t n; uint32_t ret; if (arg32->num_params > TEE_RPC_BUFFER_NUMBER) { arg32->ret = TEEC_ERROR_GENERIC; return; } params = TEESMC32_GET_PARAMS(arg32); memset(&inv, 0, sizeof(inv)); inv.cmd = arg32->cmd; /* * Set a suitable error code in case tee-supplicant * ignores the request. */ inv.res = TEEC_ERROR_NOT_IMPLEMENTED; inv.nbr_bf = arg32->num_params; for (n = 0; n < arg32->num_params; n++) { inv.cmds[n].buffer = (void *)(uintptr_t)params[n].u.memref.buf_ptr; inv.cmds[n].size = params[n].u.memref.size; switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) { case TEESMC_ATTR_TYPE_VALUE_INPUT: case TEESMC_ATTR_TYPE_VALUE_OUTPUT: case TEESMC_ATTR_TYPE_VALUE_INOUT: inv.cmds[n].type = TEE_RPC_VALUE; break; case TEESMC_ATTR_TYPE_MEMREF_INPUT: case TEESMC_ATTR_TYPE_MEMREF_OUTPUT: case TEESMC_ATTR_TYPE_MEMREF_INOUT: inv.cmds[n].type = TEE_RPC_BUFFER; break; default: arg32->ret = TEEC_ERROR_GENERIC; return; } } ret = tee_supp_cmd(ptee->tee, TEE_RPC_ICMD_INVOKE, &inv, sizeof(inv)); if (ret == TEEC_RPC_OK) arg32->ret = inv.res; for (n = 0; n < arg32->num_params; n++) { switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) { case TEESMC_ATTR_TYPE_VALUE_INPUT: case TEESMC_ATTR_TYPE_VALUE_OUTPUT: case TEESMC_ATTR_TYPE_VALUE_INOUT: case TEESMC_ATTR_TYPE_MEMREF_OUTPUT: case TEESMC_ATTR_TYPE_MEMREF_INOUT: /* * Allow supplicant to assign a new pointer * to an out-buffer. Needed when the * supplicant allocates a new buffer, for * instance when loading a TA. */ params[n].u.memref.buf_ptr = (uint32_t)(uintptr_t)inv.cmds[n].buffer; params[n].u.memref.size = inv.cmds[n].size; break; default: break; } } }
static u32 handle_rpc(struct smc_param *param) { switch (TEESMC_RETURN_GET_RPC_FUNC(param->a0)) { case TEESMC_RPC_FUNC_ALLOC_ARG: param->a1 = tee_shm_pool_alloc(DEV, TZop.Allocator, param->a1, 4); case TEESMC_RPC_FUNC_ALLOC_PAYLOAD: /* Can't support payload shared memory with this interface */ param->a2 = 0; break; case TEESMC_RPC_FUNC_FREE_ARG: tee_shm_pool_free(DEV, TZop.Allocator, param->a1, 0); break; case TEESMC_RPC_FUNC_FREE_PAYLOAD: /* Can't support payload shared memory with this interface */ break; case TEESMC_ST_RPC_FUNC_ALLOC_PAYLOAD: { struct tee_shm *shm; shm = tee_shm_allocate(&TZop, 0, param->a1, 0); if (!shm) { param->a1 = 0; break; } param->a1 = shm->paddr; param->a2 = (uint32_t)shm; break; } case TEESMC_ST_RPC_FUNC_FREE_PAYLOAD: if (param->a1) tee_shm_unallocate((struct tee_shm *)param->a1); break; case TEESMC_RPC_FUNC_IRQ: break; case TEESMC_RPC_FUNC_CMD: { struct teesmc32_arg *arg32; struct teesmc32_param *params; struct tee_rpc_invoke inv; size_t n; uint32_t ret; arg32 = tee_shm_pool_p2v(DEV, TZop.Allocator, param->a1); if (arg32->num_params > TEE_RPC_BUFFER_NUMBER) { arg32->ret = TEEC_ERROR_GENERIC; goto out; } params = TEESMC32_GET_PARAMS(arg32); memset(&inv, 0, sizeof(inv)); inv.cmd = arg32->cmd; /* * Set a suitable error code in case tee-supplicant * ignores the request. */ inv.res = TEEC_ERROR_NOT_IMPLEMENTED; inv.nbr_bf = arg32->num_params; for (n = 0; n < arg32->num_params; n++) { inv.cmds[n].buffer = (void *)params[n].u.memref.buf_ptr; inv.cmds[n].size = params[n].u.memref.size; switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) { case TEESMC_ATTR_TYPE_VALUE_INPUT: case TEESMC_ATTR_TYPE_VALUE_OUTPUT: case TEESMC_ATTR_TYPE_VALUE_INOUT: inv.cmds[n].type = TEE_RPC_VALUE; break; case TEESMC_ATTR_TYPE_MEMREF_INPUT: case TEESMC_ATTR_TYPE_MEMREF_OUTPUT: case TEESMC_ATTR_TYPE_MEMREF_INOUT: inv.cmds[n].type = TEE_RPC_BUFFER; break; default: arg32->ret = TEEC_ERROR_GENERIC; goto out; } } ret = tee_supp_cmd(&TZop, TEE_RPC_ICMD_INVOKE, &inv, sizeof(inv)); if (ret == TEEC_RPC_OK) arg32->ret = inv.res; for (n = 0; n < arg32->num_params; n++) { switch (params[n].attr & TEESMC_ATTR_TYPE_MASK) { case TEESMC_ATTR_TYPE_VALUE_INPUT: case TEESMC_ATTR_TYPE_VALUE_OUTPUT: case TEESMC_ATTR_TYPE_VALUE_INOUT: case TEESMC_ATTR_TYPE_MEMREF_OUTPUT: case TEESMC_ATTR_TYPE_MEMREF_INOUT: /* * Allow supplicant to assign a new pointer * to an out-buffer. Needed when the * supplicant allocates a new buffer, for * instance when loading a TA. */ params[n].u.memref.buf_ptr = (uint32_t)inv.cmds[n].buffer; params[n].u.memref.size = inv.cmds[n].size; break; default: break; } } break; } default: dev_warn(DEV, "Unknown RPC func 0x%x\n", TEESMC_RETURN_GET_RPC_FUNC(param->a0)); break; } out: if (irqs_disabled()) return TEESMC32_FASTCALL_RETURN_FROM_RPC; else return TEESMC32_CALL_RETURN_FROM_RPC; }