// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include <common.h> #include <log.h> #include <malloc.h> #include <tee.h> #include <linux/types.h> #include "optee_msg.h" #include "optee_msg_supplicant.h" #include "optee_private.h" #include "optee_smc.h" static void cmd_shm_alloc(struct udevice *dev, struct optee_msg_arg *arg, void **page_list) { int rc; struct tee_shm *shm; void *pl; u64 ph_ptr; arg->ret_origin = TEE_ORIGIN_COMMS; if (arg->num_params != 1 || arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { arg->ret = TEE_ERROR_BAD_PARAMETERS; return; } rc = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b, TEE_SHM_REGISTER | TEE_SHM_ALLOC, &shm); if (rc) { if (rc == -ENOMEM) arg->ret = TEE_ERROR_OUT_OF_MEMORY; else arg->ret = TEE_ERROR_GENERIC; return; } pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr); if (!pl) { arg->ret = TEE_ERROR_OUT_OF_MEMORY; tee_shm_free(shm); return; } *page_list = pl; arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG; arg->params[0].u.tmem.buf_ptr = ph_ptr; arg->params[0].u.tmem.size = shm->size; arg->params[0].u.tmem.shm_ref = (ulong)shm; arg->ret = TEE_SUCCESS; } static void cmd_shm_free(struct optee_msg_arg *arg) { arg->ret_origin = TEE_ORIGIN_COMMS; if (arg->num_params != 1 || arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) { arg->ret = TEE_ERROR_BAD_PARAMETERS; return; } tee_shm_free((struct tee_shm *)(ulong)arg->params[0].u.value.b); arg->ret = TEE_SUCCESS; } void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg, void **page_list) { struct optee_msg_arg *arg = shm_arg->addr; switch (arg->cmd) { case OPTEE_MSG_RPC_CMD_SHM_ALLOC: cmd_shm_alloc(dev, arg, page_list); break; case OPTEE_MSG_RPC_CMD_SHM_FREE: cmd_shm_free(arg); break; case OPTEE_MSG_RPC_CMD_FS: debug("REE FS storage isn't available\n"); arg->ret = TEE_ERROR_STORAGE_NOT_AVAILABLE; break; case OPTEE_MSG_RPC_CMD_RPMB: optee_suppl_cmd_rpmb(dev, arg); break; case OPTEE_MSG_RPC_CMD_I2C_TRANSFER: optee_suppl_cmd_i2c_transfer(arg); break; default: arg->ret = TEE_ERROR_NOT_IMPLEMENTED; } arg->ret_origin = TEE_ORIGIN_COMMS; }