125c76675SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 225c76675SMarouene Boubakri /* 325c76675SMarouene Boubakri * Copyright (c) 2015-2016, Linaro Limited 425c76675SMarouene Boubakri * Copyright (c) 2014, STMicroelectronics International N.V. 525c76675SMarouene Boubakri */ 625c76675SMarouene Boubakri 725c76675SMarouene Boubakri #include <assert.h> 825c76675SMarouene Boubakri #include <bench.h> 925c76675SMarouene Boubakri #include <compiler.h> 1025c76675SMarouene Boubakri #include <initcall.h> 1125c76675SMarouene Boubakri #include <io.h> 1225c76675SMarouene Boubakri #include <kernel/linker.h> 1325c76675SMarouene Boubakri #include <kernel/msg_param.h> 14c2d44948SJens Wiklander #include <kernel/notif.h> 1525c76675SMarouene Boubakri #include <kernel/panic.h> 1625c76675SMarouene Boubakri #include <kernel/tee_misc.h> 1725c76675SMarouene Boubakri #include <mm/core_memprot.h> 1825c76675SMarouene Boubakri #include <mm/core_mmu.h> 1925c76675SMarouene Boubakri #include <mm/mobj.h> 2025c76675SMarouene Boubakri #include <optee_msg.h> 2125c76675SMarouene Boubakri #include <sm/optee_smc.h> 2225c76675SMarouene Boubakri #include <string.h> 2325c76675SMarouene Boubakri #include <tee/entry_std.h> 2425c76675SMarouene Boubakri #include <tee/tee_cryp_utl.h> 2525c76675SMarouene Boubakri #include <tee/uuid.h> 2625c76675SMarouene Boubakri #include <util.h> 2725c76675SMarouene Boubakri 2825c76675SMarouene Boubakri #define SHM_CACHE_ATTRS \ 29*d8158feaSJens Wiklander (uint32_t)(core_mmu_is_shm_cached() ? \ 30*d8158feaSJens Wiklander TEE_MATTR_CACHE_CACHED : TEE_MATTR_CACHE_NONCACHE) 3125c76675SMarouene Boubakri 3225c76675SMarouene Boubakri /* Sessions opened from normal world */ 3325c76675SMarouene Boubakri static struct tee_ta_session_head tee_open_sessions = 3425c76675SMarouene Boubakri TAILQ_HEAD_INITIALIZER(tee_open_sessions); 3525c76675SMarouene Boubakri 3625c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 3725c76675SMarouene Boubakri static struct mobj *shm_mobj; 3825c76675SMarouene Boubakri #endif 3925c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 4025c76675SMarouene Boubakri static struct mobj **sdp_mem_mobjs; 4125c76675SMarouene Boubakri #endif 4225c76675SMarouene Boubakri 4325c76675SMarouene Boubakri static unsigned int session_pnum; 4425c76675SMarouene Boubakri 4525c76675SMarouene Boubakri static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem, 4625c76675SMarouene Boubakri struct mobj *mobj, 4725c76675SMarouene Boubakri const paddr_t pa, 4825c76675SMarouene Boubakri const size_t sz) 4925c76675SMarouene Boubakri { 5025c76675SMarouene Boubakri paddr_t b; 5125c76675SMarouene Boubakri 5225c76675SMarouene Boubakri if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS) 5325c76675SMarouene Boubakri panic("mobj_get_pa failed"); 5425c76675SMarouene Boubakri 5525c76675SMarouene Boubakri if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size)) 5625c76675SMarouene Boubakri return false; 5725c76675SMarouene Boubakri 5825c76675SMarouene Boubakri mem->mobj = mobj_get(mobj); 5925c76675SMarouene Boubakri mem->offs = pa - b; 6025c76675SMarouene Boubakri mem->size = sz; 6125c76675SMarouene Boubakri return true; 6225c76675SMarouene Boubakri } 6325c76675SMarouene Boubakri 6425c76675SMarouene Boubakri #ifdef CFG_CORE_FFA 6525c76675SMarouene Boubakri static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem, 6625c76675SMarouene Boubakri struct param_mem *mem) 6725c76675SMarouene Boubakri { 6825c76675SMarouene Boubakri size_t req_size = 0; 6925c76675SMarouene Boubakri uint64_t global_id = READ_ONCE(fmem->global_id); 7025c76675SMarouene Boubakri size_t sz = READ_ONCE(fmem->size); 7125c76675SMarouene Boubakri 72c1bdf4fcSJens Wiklander if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) { 7325c76675SMarouene Boubakri mem->mobj = NULL; 7425c76675SMarouene Boubakri mem->offs = 0; 7525c76675SMarouene Boubakri mem->size = 0; 7625c76675SMarouene Boubakri return TEE_SUCCESS; 7725c76675SMarouene Boubakri } 7825c76675SMarouene Boubakri mem->mobj = mobj_ffa_get_by_cookie(global_id, 7925c76675SMarouene Boubakri READ_ONCE(fmem->internal_offs)); 8025c76675SMarouene Boubakri if (!mem->mobj) 8125c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 8225c76675SMarouene Boubakri 8325c76675SMarouene Boubakri mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high), 8425c76675SMarouene Boubakri READ_ONCE(fmem->offs_low)); 8525c76675SMarouene Boubakri mem->size = sz; 8625c76675SMarouene Boubakri 8725c76675SMarouene Boubakri /* 8825c76675SMarouene Boubakri * Check that the supplied offset and size is covered by the 8925c76675SMarouene Boubakri * previously verified MOBJ. 9025c76675SMarouene Boubakri */ 9125c76675SMarouene Boubakri if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || 9225c76675SMarouene Boubakri mem->mobj->size < req_size) 9325c76675SMarouene Boubakri return TEE_ERROR_SECURITY; 9425c76675SMarouene Boubakri 9525c76675SMarouene Boubakri return TEE_SUCCESS; 9625c76675SMarouene Boubakri } 9725c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/ 9825c76675SMarouene Boubakri /* fill 'struct param_mem' structure if buffer matches a valid memory object */ 9925c76675SMarouene Boubakri static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem, 10025c76675SMarouene Boubakri uint32_t attr, struct param_mem *mem) 10125c76675SMarouene Boubakri { 10225c76675SMarouene Boubakri struct mobj __maybe_unused **mobj; 10325c76675SMarouene Boubakri paddr_t pa = READ_ONCE(tmem->buf_ptr); 10425c76675SMarouene Boubakri size_t sz = READ_ONCE(tmem->size); 10525c76675SMarouene Boubakri 10625c76675SMarouene Boubakri /* 10725c76675SMarouene Boubakri * Handle NULL memory reference 10825c76675SMarouene Boubakri */ 10925c76675SMarouene Boubakri if (!pa) { 11025c76675SMarouene Boubakri mem->mobj = NULL; 11125c76675SMarouene Boubakri mem->offs = 0; 11225c76675SMarouene Boubakri mem->size = 0; 11325c76675SMarouene Boubakri return TEE_SUCCESS; 11425c76675SMarouene Boubakri } 11525c76675SMarouene Boubakri 11625c76675SMarouene Boubakri /* Handle non-contiguous reference from a shared memory area */ 11725c76675SMarouene Boubakri if (attr & OPTEE_MSG_ATTR_NONCONTIG) { 11825c76675SMarouene Boubakri uint64_t shm_ref = READ_ONCE(tmem->shm_ref); 11925c76675SMarouene Boubakri 12025c76675SMarouene Boubakri mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref, 12125c76675SMarouene Boubakri false); 12225c76675SMarouene Boubakri if (!mem->mobj) 12325c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 12425c76675SMarouene Boubakri mem->offs = 0; 12525c76675SMarouene Boubakri mem->size = sz; 12625c76675SMarouene Boubakri return TEE_SUCCESS; 12725c76675SMarouene Boubakri } 12825c76675SMarouene Boubakri 12925c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 13025c76675SMarouene Boubakri /* Handle memory reference in the contiguous shared memory */ 13125c76675SMarouene Boubakri if (param_mem_from_mobj(mem, shm_mobj, pa, sz)) 13225c76675SMarouene Boubakri return TEE_SUCCESS; 13325c76675SMarouene Boubakri #endif 13425c76675SMarouene Boubakri 13525c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 13625c76675SMarouene Boubakri /* Handle memory reference to Secure Data Path memory areas */ 13725c76675SMarouene Boubakri for (mobj = sdp_mem_mobjs; *mobj; mobj++) 13825c76675SMarouene Boubakri if (param_mem_from_mobj(mem, *mobj, pa, sz)) 13925c76675SMarouene Boubakri return TEE_SUCCESS; 14025c76675SMarouene Boubakri #endif 14125c76675SMarouene Boubakri 14225c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 14325c76675SMarouene Boubakri } 14425c76675SMarouene Boubakri 14525c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 14625c76675SMarouene Boubakri static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem, 14725c76675SMarouene Boubakri struct param_mem *mem) 14825c76675SMarouene Boubakri { 14925c76675SMarouene Boubakri size_t req_size = 0; 15025c76675SMarouene Boubakri uint64_t shm_ref = READ_ONCE(rmem->shm_ref); 15125c76675SMarouene Boubakri size_t sz = READ_ONCE(rmem->size); 15225c76675SMarouene Boubakri 15325c76675SMarouene Boubakri mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref); 15425c76675SMarouene Boubakri if (!mem->mobj) 15525c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 15625c76675SMarouene Boubakri 15725c76675SMarouene Boubakri mem->offs = READ_ONCE(rmem->offs); 15825c76675SMarouene Boubakri mem->size = sz; 15925c76675SMarouene Boubakri 16025c76675SMarouene Boubakri /* 16125c76675SMarouene Boubakri * Check that the supplied offset and size is covered by the 16225c76675SMarouene Boubakri * previously verified MOBJ. 16325c76675SMarouene Boubakri */ 16425c76675SMarouene Boubakri if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || 16525c76675SMarouene Boubakri mem->mobj->size < req_size) 16625c76675SMarouene Boubakri return TEE_ERROR_SECURITY; 16725c76675SMarouene Boubakri 16825c76675SMarouene Boubakri return TEE_SUCCESS; 16925c76675SMarouene Boubakri } 17025c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 17125c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/ 17225c76675SMarouene Boubakri 17325c76675SMarouene Boubakri static TEE_Result copy_in_params(const struct optee_msg_param *params, 17425c76675SMarouene Boubakri uint32_t num_params, 17525c76675SMarouene Boubakri struct tee_ta_param *ta_param, 17625c76675SMarouene Boubakri uint64_t *saved_attr) 17725c76675SMarouene Boubakri { 17825c76675SMarouene Boubakri TEE_Result res; 17925c76675SMarouene Boubakri size_t n; 18025c76675SMarouene Boubakri uint8_t pt[TEE_NUM_PARAMS] = { 0 }; 18125c76675SMarouene Boubakri 18225c76675SMarouene Boubakri if (num_params > TEE_NUM_PARAMS) 18325c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 18425c76675SMarouene Boubakri 18525c76675SMarouene Boubakri memset(ta_param, 0, sizeof(*ta_param)); 18625c76675SMarouene Boubakri 18725c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 18825c76675SMarouene Boubakri uint32_t attr; 18925c76675SMarouene Boubakri 19025c76675SMarouene Boubakri saved_attr[n] = READ_ONCE(params[n].attr); 19125c76675SMarouene Boubakri 19225c76675SMarouene Boubakri if (saved_attr[n] & OPTEE_MSG_ATTR_META) 19325c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 19425c76675SMarouene Boubakri 19525c76675SMarouene Boubakri attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK; 19625c76675SMarouene Boubakri switch (attr) { 19725c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_NONE: 19825c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_NONE; 19925c76675SMarouene Boubakri break; 20025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: 20125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: 20225c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: 20325c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr - 20425c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 20525c76675SMarouene Boubakri ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a); 20625c76675SMarouene Boubakri ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b); 20725c76675SMarouene Boubakri break; 20825c76675SMarouene Boubakri #ifdef CFG_CORE_FFA 20925c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: 21025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: 21125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: 21225c76675SMarouene Boubakri res = set_fmem_param(¶ms[n].u.fmem, 21325c76675SMarouene Boubakri &ta_param->u[n].mem); 21425c76675SMarouene Boubakri if (res) 21525c76675SMarouene Boubakri return res; 21625c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 21725c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; 21825c76675SMarouene Boubakri break; 21925c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/ 22025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: 22125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 22225c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 22325c76675SMarouene Boubakri res = set_tmem_param(¶ms[n].u.tmem, saved_attr[n], 22425c76675SMarouene Boubakri &ta_param->u[n].mem); 22525c76675SMarouene Boubakri if (res) 22625c76675SMarouene Boubakri return res; 22725c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 22825c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 22925c76675SMarouene Boubakri break; 23025c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 23125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: 23225c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 23325c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 23425c76675SMarouene Boubakri res = set_rmem_param(¶ms[n].u.rmem, 23525c76675SMarouene Boubakri &ta_param->u[n].mem); 23625c76675SMarouene Boubakri if (res) 23725c76675SMarouene Boubakri return res; 23825c76675SMarouene Boubakri pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - 23925c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; 24025c76675SMarouene Boubakri break; 24125c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 24225c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/ 24325c76675SMarouene Boubakri default: 24425c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 24525c76675SMarouene Boubakri } 24625c76675SMarouene Boubakri } 24725c76675SMarouene Boubakri 24825c76675SMarouene Boubakri ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); 24925c76675SMarouene Boubakri 25025c76675SMarouene Boubakri return TEE_SUCCESS; 25125c76675SMarouene Boubakri } 25225c76675SMarouene Boubakri 25325c76675SMarouene Boubakri static void cleanup_shm_refs(const uint64_t *saved_attr, 25425c76675SMarouene Boubakri struct tee_ta_param *param, uint32_t num_params) 25525c76675SMarouene Boubakri { 25625c76675SMarouene Boubakri size_t n; 25725c76675SMarouene Boubakri 25825c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 25925c76675SMarouene Boubakri switch (saved_attr[n]) { 26025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: 26125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 26225c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 26325c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 26425c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: 26525c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 26625c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 26725c76675SMarouene Boubakri #endif 26825c76675SMarouene Boubakri mobj_put(param->u[n].mem.mobj); 26925c76675SMarouene Boubakri break; 27025c76675SMarouene Boubakri default: 27125c76675SMarouene Boubakri break; 27225c76675SMarouene Boubakri } 27325c76675SMarouene Boubakri } 27425c76675SMarouene Boubakri } 27525c76675SMarouene Boubakri 27625c76675SMarouene Boubakri static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params, 27725c76675SMarouene Boubakri struct optee_msg_param *params, uint64_t *saved_attr) 27825c76675SMarouene Boubakri { 27925c76675SMarouene Boubakri size_t n; 28025c76675SMarouene Boubakri 28125c76675SMarouene Boubakri for (n = 0; n < num_params; n++) { 28225c76675SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) { 28325c76675SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 28425c76675SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 28525c76675SMarouene Boubakri switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) { 28625c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: 28725c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: 28825c76675SMarouene Boubakri params[n].u.tmem.size = ta_param->u[n].mem.size; 28925c76675SMarouene Boubakri break; 29025c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: 29125c76675SMarouene Boubakri case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: 29225c76675SMarouene Boubakri params[n].u.rmem.size = ta_param->u[n].mem.size; 29325c76675SMarouene Boubakri break; 29425c76675SMarouene Boubakri default: 29525c76675SMarouene Boubakri break; 29625c76675SMarouene Boubakri } 29725c76675SMarouene Boubakri break; 29825c76675SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 29925c76675SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 30025c76675SMarouene Boubakri params[n].u.value.a = ta_param->u[n].val.a; 30125c76675SMarouene Boubakri params[n].u.value.b = ta_param->u[n].val.b; 30225c76675SMarouene Boubakri break; 30325c76675SMarouene Boubakri default: 30425c76675SMarouene Boubakri break; 30525c76675SMarouene Boubakri } 30625c76675SMarouene Boubakri } 30725c76675SMarouene Boubakri } 30825c76675SMarouene Boubakri 30925c76675SMarouene Boubakri /* 31025c76675SMarouene Boubakri * Extracts mandatory parameter for open session. 31125c76675SMarouene Boubakri * 31225c76675SMarouene Boubakri * Returns 31325c76675SMarouene Boubakri * false : mandatory parameter wasn't found or malformatted 31425c76675SMarouene Boubakri * true : paramater found and OK 31525c76675SMarouene Boubakri */ 31625c76675SMarouene Boubakri static TEE_Result get_open_session_meta(size_t num_params, 31725c76675SMarouene Boubakri struct optee_msg_param *params, 31825c76675SMarouene Boubakri size_t *num_meta, TEE_UUID *uuid, 31925c76675SMarouene Boubakri TEE_Identity *clnt_id) 32025c76675SMarouene Boubakri { 32125c76675SMarouene Boubakri const uint32_t req_attr = OPTEE_MSG_ATTR_META | 32225c76675SMarouene Boubakri OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 32325c76675SMarouene Boubakri 32425c76675SMarouene Boubakri if (num_params < 2) 32525c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 32625c76675SMarouene Boubakri 32725c76675SMarouene Boubakri if (params[0].attr != req_attr || params[1].attr != req_attr) 32825c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 32925c76675SMarouene Boubakri 33025c76675SMarouene Boubakri tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value); 33125c76675SMarouene Boubakri clnt_id->login = params[1].u.value.c; 33225c76675SMarouene Boubakri switch (clnt_id->login) { 33325c76675SMarouene Boubakri case TEE_LOGIN_PUBLIC: 33425c76675SMarouene Boubakri case TEE_LOGIN_REE_KERNEL: 33525c76675SMarouene Boubakri memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid)); 33625c76675SMarouene Boubakri break; 33725c76675SMarouene Boubakri case TEE_LOGIN_USER: 33825c76675SMarouene Boubakri case TEE_LOGIN_GROUP: 33925c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION: 34025c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION_USER: 34125c76675SMarouene Boubakri case TEE_LOGIN_APPLICATION_GROUP: 34225c76675SMarouene Boubakri tee_uuid_from_octets(&clnt_id->uuid, 34325c76675SMarouene Boubakri (void *)¶ms[1].u.value); 34425c76675SMarouene Boubakri break; 34525c76675SMarouene Boubakri default: 34625c76675SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 34725c76675SMarouene Boubakri } 34825c76675SMarouene Boubakri 34925c76675SMarouene Boubakri *num_meta = 2; 35025c76675SMarouene Boubakri return TEE_SUCCESS; 35125c76675SMarouene Boubakri } 35225c76675SMarouene Boubakri 35325c76675SMarouene Boubakri static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params) 35425c76675SMarouene Boubakri { 35525c76675SMarouene Boubakri TEE_Result res; 35625c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 35725c76675SMarouene Boubakri struct tee_ta_session *s = NULL; 35825c76675SMarouene Boubakri TEE_Identity clnt_id; 35925c76675SMarouene Boubakri TEE_UUID uuid; 36025c76675SMarouene Boubakri struct tee_ta_param param; 36125c76675SMarouene Boubakri size_t num_meta; 36225c76675SMarouene Boubakri uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 36325c76675SMarouene Boubakri 36425c76675SMarouene Boubakri res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid, 36525c76675SMarouene Boubakri &clnt_id); 36625c76675SMarouene Boubakri if (res != TEE_SUCCESS) 36725c76675SMarouene Boubakri goto out; 36825c76675SMarouene Boubakri 36925c76675SMarouene Boubakri res = copy_in_params(arg->params + num_meta, num_params - num_meta, 37025c76675SMarouene Boubakri ¶m, saved_attr); 37125c76675SMarouene Boubakri if (res != TEE_SUCCESS) 37225c76675SMarouene Boubakri goto cleanup_shm_refs; 37325c76675SMarouene Boubakri 37425c76675SMarouene Boubakri res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, 37525c76675SMarouene Boubakri &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); 37625c76675SMarouene Boubakri if (res != TEE_SUCCESS) 37725c76675SMarouene Boubakri s = NULL; 37825c76675SMarouene Boubakri copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, 37925c76675SMarouene Boubakri saved_attr); 38025c76675SMarouene Boubakri 38125c76675SMarouene Boubakri /* 38225c76675SMarouene Boubakri * The occurrence of open/close session command is usually 38325c76675SMarouene Boubakri * un-predictable, using this property to increase randomness 38425c76675SMarouene Boubakri * of prng 38525c76675SMarouene Boubakri */ 38625c76675SMarouene Boubakri plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 38725c76675SMarouene Boubakri &session_pnum); 38825c76675SMarouene Boubakri 38925c76675SMarouene Boubakri cleanup_shm_refs: 39025c76675SMarouene Boubakri cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); 39125c76675SMarouene Boubakri 39225c76675SMarouene Boubakri out: 39325c76675SMarouene Boubakri if (s) 39425c76675SMarouene Boubakri arg->session = s->id; 39525c76675SMarouene Boubakri else 39625c76675SMarouene Boubakri arg->session = 0; 39725c76675SMarouene Boubakri arg->ret = res; 39825c76675SMarouene Boubakri arg->ret_origin = err_orig; 39925c76675SMarouene Boubakri } 40025c76675SMarouene Boubakri 40125c76675SMarouene Boubakri static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params) 40225c76675SMarouene Boubakri { 40325c76675SMarouene Boubakri TEE_Result res; 40425c76675SMarouene Boubakri struct tee_ta_session *s; 40525c76675SMarouene Boubakri 40625c76675SMarouene Boubakri if (num_params) { 40725c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 40825c76675SMarouene Boubakri goto out; 40925c76675SMarouene Boubakri } 41025c76675SMarouene Boubakri 41125c76675SMarouene Boubakri plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 41225c76675SMarouene Boubakri &session_pnum); 41325c76675SMarouene Boubakri 41425c76675SMarouene Boubakri s = tee_ta_find_session(arg->session, &tee_open_sessions); 41525c76675SMarouene Boubakri res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY); 41625c76675SMarouene Boubakri out: 41725c76675SMarouene Boubakri arg->ret = res; 41825c76675SMarouene Boubakri arg->ret_origin = TEE_ORIGIN_TEE; 41925c76675SMarouene Boubakri } 42025c76675SMarouene Boubakri 42125c76675SMarouene Boubakri static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params) 42225c76675SMarouene Boubakri { 42325c76675SMarouene Boubakri TEE_Result res; 42425c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 42525c76675SMarouene Boubakri struct tee_ta_session *s; 42625c76675SMarouene Boubakri struct tee_ta_param param = { 0 }; 42725c76675SMarouene Boubakri uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 42825c76675SMarouene Boubakri 42925c76675SMarouene Boubakri bm_timestamp(); 43025c76675SMarouene Boubakri 43125c76675SMarouene Boubakri res = copy_in_params(arg->params, num_params, ¶m, saved_attr); 43225c76675SMarouene Boubakri if (res != TEE_SUCCESS) 43325c76675SMarouene Boubakri goto out; 43425c76675SMarouene Boubakri 43525c76675SMarouene Boubakri s = tee_ta_get_session(arg->session, true, &tee_open_sessions); 43625c76675SMarouene Boubakri if (!s) { 43725c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 43825c76675SMarouene Boubakri goto out; 43925c76675SMarouene Boubakri } 44025c76675SMarouene Boubakri 44125c76675SMarouene Boubakri res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, 44225c76675SMarouene Boubakri TEE_TIMEOUT_INFINITE, arg->func, ¶m); 44325c76675SMarouene Boubakri 44425c76675SMarouene Boubakri bm_timestamp(); 44525c76675SMarouene Boubakri 44625c76675SMarouene Boubakri tee_ta_put_session(s); 44725c76675SMarouene Boubakri 44825c76675SMarouene Boubakri copy_out_param(¶m, num_params, arg->params, saved_attr); 44925c76675SMarouene Boubakri 45025c76675SMarouene Boubakri out: 45125c76675SMarouene Boubakri cleanup_shm_refs(saved_attr, ¶m, num_params); 45225c76675SMarouene Boubakri 45325c76675SMarouene Boubakri arg->ret = res; 45425c76675SMarouene Boubakri arg->ret_origin = err_orig; 45525c76675SMarouene Boubakri } 45625c76675SMarouene Boubakri 45725c76675SMarouene Boubakri static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params) 45825c76675SMarouene Boubakri { 45925c76675SMarouene Boubakri TEE_Result res; 46025c76675SMarouene Boubakri TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 46125c76675SMarouene Boubakri struct tee_ta_session *s; 46225c76675SMarouene Boubakri 46325c76675SMarouene Boubakri if (num_params) { 46425c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 46525c76675SMarouene Boubakri goto out; 46625c76675SMarouene Boubakri } 46725c76675SMarouene Boubakri 46825c76675SMarouene Boubakri s = tee_ta_get_session(arg->session, false, &tee_open_sessions); 46925c76675SMarouene Boubakri if (!s) { 47025c76675SMarouene Boubakri res = TEE_ERROR_BAD_PARAMETERS; 47125c76675SMarouene Boubakri goto out; 47225c76675SMarouene Boubakri } 47325c76675SMarouene Boubakri 47425c76675SMarouene Boubakri res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY); 47525c76675SMarouene Boubakri tee_ta_put_session(s); 47625c76675SMarouene Boubakri 47725c76675SMarouene Boubakri out: 47825c76675SMarouene Boubakri arg->ret = res; 47925c76675SMarouene Boubakri arg->ret_origin = err_orig; 48025c76675SMarouene Boubakri } 48125c76675SMarouene Boubakri 48225c76675SMarouene Boubakri #ifndef CFG_CORE_FFA 48325c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 48425c76675SMarouene Boubakri static void register_shm(struct optee_msg_arg *arg, uint32_t num_params) 48525c76675SMarouene Boubakri { 486b259cc96SJens Wiklander struct optee_msg_param_tmem *tmem = NULL; 487b259cc96SJens Wiklander struct mobj *mobj = NULL; 488b259cc96SJens Wiklander 48925c76675SMarouene Boubakri arg->ret = TEE_ERROR_BAD_PARAMETERS; 49025c76675SMarouene Boubakri 49125c76675SMarouene Boubakri if (num_params != 1 || 49225c76675SMarouene Boubakri (arg->params[0].attr != 49325c76675SMarouene Boubakri (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) 49425c76675SMarouene Boubakri return; 49525c76675SMarouene Boubakri 496b259cc96SJens Wiklander tmem = &arg->params[0].u.tmem; 497b259cc96SJens Wiklander mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size, 49825c76675SMarouene Boubakri tmem->shm_ref, false); 49925c76675SMarouene Boubakri 50025c76675SMarouene Boubakri if (!mobj) 50125c76675SMarouene Boubakri return; 50225c76675SMarouene Boubakri 50325c76675SMarouene Boubakri mobj_reg_shm_unguard(mobj); 50425c76675SMarouene Boubakri arg->ret = TEE_SUCCESS; 50525c76675SMarouene Boubakri } 50625c76675SMarouene Boubakri 50725c76675SMarouene Boubakri static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params) 50825c76675SMarouene Boubakri { 50925c76675SMarouene Boubakri if (num_params == 1) { 51025c76675SMarouene Boubakri uint64_t cookie = arg->params[0].u.rmem.shm_ref; 51125c76675SMarouene Boubakri TEE_Result res = mobj_reg_shm_release_by_cookie(cookie); 51225c76675SMarouene Boubakri 51325c76675SMarouene Boubakri if (res) 51425c76675SMarouene Boubakri EMSG("Can't find mapping with given cookie"); 51525c76675SMarouene Boubakri arg->ret = res; 51625c76675SMarouene Boubakri } else { 51725c76675SMarouene Boubakri arg->ret = TEE_ERROR_BAD_PARAMETERS; 51825c76675SMarouene Boubakri arg->ret_origin = TEE_ORIGIN_TEE; 51925c76675SMarouene Boubakri } 52025c76675SMarouene Boubakri } 52125c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/ 52225c76675SMarouene Boubakri #endif 52325c76675SMarouene Boubakri 52425c76675SMarouene Boubakri void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions) 52525c76675SMarouene Boubakri { 52625c76675SMarouene Boubakri *open_sessions = &tee_open_sessions; 52725c76675SMarouene Boubakri } 52825c76675SMarouene Boubakri 52925c76675SMarouene Boubakri /* Note: this function is weak to let platforms add special handling */ 53025c76675SMarouene Boubakri uint32_t __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 53125c76675SMarouene Boubakri { 53225c76675SMarouene Boubakri return __tee_entry_std(arg, num_params); 53325c76675SMarouene Boubakri } 53425c76675SMarouene Boubakri 53525c76675SMarouene Boubakri /* 53625c76675SMarouene Boubakri * If tee_entry_std() is overridden, it's still supposed to call this 53725c76675SMarouene Boubakri * function. 53825c76675SMarouene Boubakri */ 53925c76675SMarouene Boubakri uint32_t __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 54025c76675SMarouene Boubakri { 54125c76675SMarouene Boubakri uint32_t rv = OPTEE_SMC_RETURN_OK; 54225c76675SMarouene Boubakri 54325c76675SMarouene Boubakri /* Enable foreign interrupts for STD calls */ 54425c76675SMarouene Boubakri thread_set_foreign_intr(true); 54525c76675SMarouene Boubakri switch (arg->cmd) { 54625c76675SMarouene Boubakri case OPTEE_MSG_CMD_OPEN_SESSION: 54725c76675SMarouene Boubakri entry_open_session(arg, num_params); 54825c76675SMarouene Boubakri break; 54925c76675SMarouene Boubakri case OPTEE_MSG_CMD_CLOSE_SESSION: 55025c76675SMarouene Boubakri entry_close_session(arg, num_params); 55125c76675SMarouene Boubakri break; 55225c76675SMarouene Boubakri case OPTEE_MSG_CMD_INVOKE_COMMAND: 55325c76675SMarouene Boubakri entry_invoke_command(arg, num_params); 55425c76675SMarouene Boubakri break; 55525c76675SMarouene Boubakri case OPTEE_MSG_CMD_CANCEL: 55625c76675SMarouene Boubakri entry_cancel(arg, num_params); 55725c76675SMarouene Boubakri break; 55825c76675SMarouene Boubakri #ifndef CFG_CORE_FFA 55925c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM 56025c76675SMarouene Boubakri case OPTEE_MSG_CMD_REGISTER_SHM: 56125c76675SMarouene Boubakri register_shm(arg, num_params); 56225c76675SMarouene Boubakri break; 56325c76675SMarouene Boubakri case OPTEE_MSG_CMD_UNREGISTER_SHM: 56425c76675SMarouene Boubakri unregister_shm(arg, num_params); 56525c76675SMarouene Boubakri break; 56625c76675SMarouene Boubakri #endif 56725c76675SMarouene Boubakri #endif 568c2d44948SJens Wiklander 569c2d44948SJens Wiklander case OPTEE_MSG_CMD_DO_BOTTOM_HALF: 570c2d44948SJens Wiklander if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) 571c2d44948SJens Wiklander notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF); 572c2d44948SJens Wiklander else 573c2d44948SJens Wiklander goto err; 574c2d44948SJens Wiklander break; 575c2d44948SJens Wiklander case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF: 576c2d44948SJens Wiklander if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) 577c2d44948SJens Wiklander notif_deliver_event(NOTIF_EVENT_STOPPED); 578c2d44948SJens Wiklander else 579c2d44948SJens Wiklander goto err; 580c2d44948SJens Wiklander break; 581c2d44948SJens Wiklander 58225c76675SMarouene Boubakri default: 583c2d44948SJens Wiklander err: 58425c76675SMarouene Boubakri EMSG("Unknown cmd 0x%x", arg->cmd); 58525c76675SMarouene Boubakri rv = OPTEE_SMC_RETURN_EBADCMD; 58625c76675SMarouene Boubakri } 58725c76675SMarouene Boubakri 58825c76675SMarouene Boubakri return rv; 58925c76675SMarouene Boubakri } 59025c76675SMarouene Boubakri 59125c76675SMarouene Boubakri static TEE_Result default_mobj_init(void) 59225c76675SMarouene Boubakri { 59325c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM 59425c76675SMarouene Boubakri shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr, 59525c76675SMarouene Boubakri default_nsec_shm_size, SHM_CACHE_ATTRS, 59625c76675SMarouene Boubakri CORE_MEM_NSEC_SHM); 59725c76675SMarouene Boubakri if (!shm_mobj) 59825c76675SMarouene Boubakri panic("Failed to register shared memory"); 59925c76675SMarouene Boubakri #endif 60025c76675SMarouene Boubakri 60125c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 60225c76675SMarouene Boubakri sdp_mem_mobjs = core_sdp_mem_create_mobjs(); 60325c76675SMarouene Boubakri if (!sdp_mem_mobjs) 60425c76675SMarouene Boubakri panic("Failed to register SDP memory"); 60525c76675SMarouene Boubakri #endif 60625c76675SMarouene Boubakri 60725c76675SMarouene Boubakri return TEE_SUCCESS; 60825c76675SMarouene Boubakri } 60925c76675SMarouene Boubakri 61025c76675SMarouene Boubakri driver_init_late(default_mobj_init); 611