1a54f2bb7SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 2a54f2bb7SMarouene Boubakri /* 3a54f2bb7SMarouene Boubakri * Copyright (c) 2014, STMicroelectronics International N.V. 4a54f2bb7SMarouene Boubakri * Copyright (c) 2015, Linaro Limited 5a54f2bb7SMarouene Boubakri * Copyright (c) 2020, Arm Limited 6a54f2bb7SMarouene Boubakri */ 7a54f2bb7SMarouene Boubakri #include <initcall.h> 8a54f2bb7SMarouene Boubakri #include <kernel/linker.h> 9a54f2bb7SMarouene Boubakri #include <kernel/panic.h> 10a54f2bb7SMarouene Boubakri #include <kernel/pseudo_ta.h> 11a54f2bb7SMarouene Boubakri #include <kernel/tee_ta_manager.h> 12653409a2SJerome Forissier #include <kernel/user_access.h> 13a54f2bb7SMarouene Boubakri #include <mm/core_memprot.h> 14a54f2bb7SMarouene Boubakri #include <mm/mobj.h> 15a54f2bb7SMarouene Boubakri #include <stdlib.h> 16a54f2bb7SMarouene Boubakri #include <string.h> 17a54f2bb7SMarouene Boubakri #include <trace.h> 18a54f2bb7SMarouene Boubakri #include <types_ext.h> 19a54f2bb7SMarouene Boubakri 20a54f2bb7SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 21a54f2bb7SMarouene Boubakri static bool client_is_secure(struct ts_session *s) 22a54f2bb7SMarouene Boubakri { 23a54f2bb7SMarouene Boubakri /* rely on core entry to have constrained client IDs */ 24a54f2bb7SMarouene Boubakri if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) 25a54f2bb7SMarouene Boubakri return true; 26a54f2bb7SMarouene Boubakri 27a54f2bb7SMarouene Boubakri return false; 28a54f2bb7SMarouene Boubakri } 29a54f2bb7SMarouene Boubakri 30a54f2bb7SMarouene Boubakri static bool validate_in_param(struct ts_session *s, struct mobj *mobj) 31a54f2bb7SMarouene Boubakri { 32a54f2bb7SMarouene Boubakri /* Supplying NULL to query buffer size is OK */ 33a54f2bb7SMarouene Boubakri if (!mobj) 34a54f2bb7SMarouene Boubakri return true; 35a54f2bb7SMarouene Boubakri 36a54f2bb7SMarouene Boubakri /* for secure clients, core entry always holds valid memref objects */ 37a54f2bb7SMarouene Boubakri if (client_is_secure(s)) 38a54f2bb7SMarouene Boubakri return true; 39a54f2bb7SMarouene Boubakri 40a54f2bb7SMarouene Boubakri /* all non-secure memory references are handled by PTAs */ 41a54f2bb7SMarouene Boubakri if (mobj_is_nonsec(mobj)) 42a54f2bb7SMarouene Boubakri return true; 43a54f2bb7SMarouene Boubakri 44a54f2bb7SMarouene Boubakri return false; 45a54f2bb7SMarouene Boubakri } 46a54f2bb7SMarouene Boubakri #else 47a54f2bb7SMarouene Boubakri static bool validate_in_param(struct ts_session *s __unused, 48a54f2bb7SMarouene Boubakri struct mobj *mobj __unused) 49a54f2bb7SMarouene Boubakri { 50a54f2bb7SMarouene Boubakri /* At this point, core has filled only valid accessible memref mobj */ 51a54f2bb7SMarouene Boubakri return true; 52a54f2bb7SMarouene Boubakri } 53a54f2bb7SMarouene Boubakri #endif 54a54f2bb7SMarouene Boubakri 55a54f2bb7SMarouene Boubakri /* Maps pseudo TA params */ 56a54f2bb7SMarouene Boubakri static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, 57a54f2bb7SMarouene Boubakri struct tee_ta_param *param, 58a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS], 59a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS]) 60a54f2bb7SMarouene Boubakri { 61a54f2bb7SMarouene Boubakri size_t n; 62a54f2bb7SMarouene Boubakri void *va; 63a54f2bb7SMarouene Boubakri struct param_mem *mem; 64a54f2bb7SMarouene Boubakri 65a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 66a54f2bb7SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(param->types, n)) { 67a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INPUT: 68a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 69a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 70a54f2bb7SMarouene Boubakri tee_param[n].value.a = param->u[n].val.a; 71a54f2bb7SMarouene Boubakri tee_param[n].value.b = param->u[n].val.b; 72a54f2bb7SMarouene Boubakri break; 73a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INPUT: 74a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 75a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 76a54f2bb7SMarouene Boubakri mem = ¶m->u[n].mem; 77a54f2bb7SMarouene Boubakri if (!validate_in_param(s, mem->mobj)) 78a54f2bb7SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 79a54f2bb7SMarouene Boubakri if (mem->size) { 80a54f2bb7SMarouene Boubakri TEE_Result res = mobj_inc_map(mem->mobj); 81a54f2bb7SMarouene Boubakri 82a54f2bb7SMarouene Boubakri if (res) 83a54f2bb7SMarouene Boubakri return res; 84a54f2bb7SMarouene Boubakri did_map[n] = true; 859c4aaf67SJens Wiklander va = mobj_get_va(mem->mobj, mem->offs, 869c4aaf67SJens Wiklander mem->size); 87a54f2bb7SMarouene Boubakri if (!va) 88a54f2bb7SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 89a54f2bb7SMarouene Boubakri } else { 90a54f2bb7SMarouene Boubakri va = NULL; 91a54f2bb7SMarouene Boubakri } 92a54f2bb7SMarouene Boubakri 93a54f2bb7SMarouene Boubakri tee_param[n].memref.buffer = va; 94a54f2bb7SMarouene Boubakri tee_param[n].memref.size = mem->size; 95a54f2bb7SMarouene Boubakri break; 96a54f2bb7SMarouene Boubakri default: 97a54f2bb7SMarouene Boubakri memset(tee_param + n, 0, sizeof(TEE_Param)); 98a54f2bb7SMarouene Boubakri break; 99a54f2bb7SMarouene Boubakri } 100a54f2bb7SMarouene Boubakri } 101a54f2bb7SMarouene Boubakri 102a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 103a54f2bb7SMarouene Boubakri } 104a54f2bb7SMarouene Boubakri 105a54f2bb7SMarouene Boubakri static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], 106a54f2bb7SMarouene Boubakri struct tee_ta_param *param) 107a54f2bb7SMarouene Boubakri { 108a54f2bb7SMarouene Boubakri size_t n; 109a54f2bb7SMarouene Boubakri 110a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 111a54f2bb7SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(param->types, n)) { 112a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 113a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 114a54f2bb7SMarouene Boubakri param->u[n].val.a = tee_param[n].value.a; 115a54f2bb7SMarouene Boubakri param->u[n].val.b = tee_param[n].value.b; 116a54f2bb7SMarouene Boubakri break; 117a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 118a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 119a54f2bb7SMarouene Boubakri param->u[n].mem.size = tee_param[n].memref.size; 120a54f2bb7SMarouene Boubakri break; 121a54f2bb7SMarouene Boubakri default: 122a54f2bb7SMarouene Boubakri break; 123a54f2bb7SMarouene Boubakri } 124a54f2bb7SMarouene Boubakri } 125a54f2bb7SMarouene Boubakri } 126a54f2bb7SMarouene Boubakri 127a54f2bb7SMarouene Boubakri static void unmap_mapped_param(struct tee_ta_param *param, 128a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS]) 129a54f2bb7SMarouene Boubakri { 130a54f2bb7SMarouene Boubakri size_t n; 131a54f2bb7SMarouene Boubakri 132a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 133a54f2bb7SMarouene Boubakri if (did_map[n]) { 134a54f2bb7SMarouene Boubakri TEE_Result res __maybe_unused; 135a54f2bb7SMarouene Boubakri 136a54f2bb7SMarouene Boubakri res = mobj_dec_map(param->u[n].mem.mobj); 137a54f2bb7SMarouene Boubakri assert(!res); 138a54f2bb7SMarouene Boubakri } 139a54f2bb7SMarouene Boubakri } 140a54f2bb7SMarouene Boubakri } 141a54f2bb7SMarouene Boubakri 142a54f2bb7SMarouene Boubakri static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) 143a54f2bb7SMarouene Boubakri { 144a54f2bb7SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 145a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 146a54f2bb7SMarouene Boubakri struct tee_ta_session *ta_sess = to_ta_session(s); 147a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 148a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS] = { false }; 149a54f2bb7SMarouene Boubakri 150a54f2bb7SMarouene Boubakri ts_push_current_session(s); 151a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 152a54f2bb7SMarouene Boubakri 153a54f2bb7SMarouene Boubakri if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { 154a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->create_entry_point(); 155a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) 156a54f2bb7SMarouene Boubakri goto out; 157a54f2bb7SMarouene Boubakri } 158a54f2bb7SMarouene Boubakri 159a54f2bb7SMarouene Boubakri if (stc->pseudo_ta->open_session_entry_point) { 160a54f2bb7SMarouene Boubakri void **user_ctx = &s->user_ctx; 161a54f2bb7SMarouene Boubakri uint32_t param_types = 0; 162a54f2bb7SMarouene Boubakri 163a54f2bb7SMarouene Boubakri if (ta_sess->param) { 164a54f2bb7SMarouene Boubakri res = copy_in_param(s, ta_sess->param, tee_param, 165a54f2bb7SMarouene Boubakri did_map); 166a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) { 167a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 168a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TEE; 169a54f2bb7SMarouene Boubakri goto out; 170a54f2bb7SMarouene Boubakri } 171a54f2bb7SMarouene Boubakri param_types = ta_sess->param->types; 172a54f2bb7SMarouene Boubakri } 173a54f2bb7SMarouene Boubakri 174a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->open_session_entry_point(param_types, 175a54f2bb7SMarouene Boubakri tee_param, 176a54f2bb7SMarouene Boubakri user_ctx); 177a54f2bb7SMarouene Boubakri if (ta_sess->param) { 178a54f2bb7SMarouene Boubakri update_out_param(tee_param, ta_sess->param); 179a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 180a54f2bb7SMarouene Boubakri } 181a54f2bb7SMarouene Boubakri } 182a54f2bb7SMarouene Boubakri 183a54f2bb7SMarouene Boubakri out: 184a54f2bb7SMarouene Boubakri ts_pop_current_session(); 185a54f2bb7SMarouene Boubakri return res; 186a54f2bb7SMarouene Boubakri } 187a54f2bb7SMarouene Boubakri 188a54f2bb7SMarouene Boubakri static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) 189a54f2bb7SMarouene Boubakri { 190a54f2bb7SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 191a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 192a54f2bb7SMarouene Boubakri struct tee_ta_session *ta_sess = to_ta_session(s); 193a54f2bb7SMarouene Boubakri uint32_t param_types = 0; 194a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 195a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS] = { false }; 196a54f2bb7SMarouene Boubakri 197a54f2bb7SMarouene Boubakri ts_push_current_session(s); 198a54f2bb7SMarouene Boubakri if (ta_sess->param) { 199a54f2bb7SMarouene Boubakri res = copy_in_param(s, ta_sess->param, tee_param, did_map); 200a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) { 201a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 202a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TEE; 203a54f2bb7SMarouene Boubakri goto out; 204a54f2bb7SMarouene Boubakri } 205a54f2bb7SMarouene Boubakri param_types = ta_sess->param->types; 206a54f2bb7SMarouene Boubakri } 207a54f2bb7SMarouene Boubakri 208a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 209a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, 210a54f2bb7SMarouene Boubakri param_types, 211a54f2bb7SMarouene Boubakri tee_param); 212a54f2bb7SMarouene Boubakri if (ta_sess->param) { 213a54f2bb7SMarouene Boubakri update_out_param(tee_param, ta_sess->param); 214a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 215a54f2bb7SMarouene Boubakri } 216a54f2bb7SMarouene Boubakri out: 217a54f2bb7SMarouene Boubakri ts_pop_current_session(); 218a54f2bb7SMarouene Boubakri return res; 219a54f2bb7SMarouene Boubakri } 220a54f2bb7SMarouene Boubakri 221a54f2bb7SMarouene Boubakri static void pseudo_ta_enter_close_session(struct ts_session *s) 222a54f2bb7SMarouene Boubakri { 223a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 224a54f2bb7SMarouene Boubakri void *user_ctx = s->user_ctx; 225a54f2bb7SMarouene Boubakri 226a54f2bb7SMarouene Boubakri ts_push_current_session(s); 227a54f2bb7SMarouene Boubakri 228a54f2bb7SMarouene Boubakri if (stc->pseudo_ta->close_session_entry_point) 229a54f2bb7SMarouene Boubakri stc->pseudo_ta->close_session_entry_point(user_ctx); 230a54f2bb7SMarouene Boubakri 231a54f2bb7SMarouene Boubakri if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) 232a54f2bb7SMarouene Boubakri stc->pseudo_ta->destroy_entry_point(); 233a54f2bb7SMarouene Boubakri 234a54f2bb7SMarouene Boubakri ts_pop_current_session(); 235a54f2bb7SMarouene Boubakri } 236a54f2bb7SMarouene Boubakri 237a54f2bb7SMarouene Boubakri static void pseudo_ta_destroy(struct ts_ctx *ctx) 238a54f2bb7SMarouene Boubakri { 239a54f2bb7SMarouene Boubakri free(to_pseudo_ta_ctx(ctx)); 240a54f2bb7SMarouene Boubakri } 241a54f2bb7SMarouene Boubakri 242a54f2bb7SMarouene Boubakri static const struct ts_ops pseudo_ta_ops = { 243a54f2bb7SMarouene Boubakri .enter_open_session = pseudo_ta_enter_open_session, 244a54f2bb7SMarouene Boubakri .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, 245a54f2bb7SMarouene Boubakri .enter_close_session = pseudo_ta_enter_close_session, 246a54f2bb7SMarouene Boubakri .destroy = pseudo_ta_destroy, 247a54f2bb7SMarouene Boubakri }; 248a54f2bb7SMarouene Boubakri 249*0a75d408SJens Wiklander bool __noprof is_pseudo_ta_ctx(struct ts_ctx *ctx) 250a54f2bb7SMarouene Boubakri { 251a54f2bb7SMarouene Boubakri return ctx->ops == &pseudo_ta_ops; 252a54f2bb7SMarouene Boubakri } 253a54f2bb7SMarouene Boubakri 254a54f2bb7SMarouene Boubakri /* Insures declared pseudo TAs conforms with core expectations */ 255a54f2bb7SMarouene Boubakri static TEE_Result verify_pseudo_tas_conformance(void) 256a54f2bb7SMarouene Boubakri { 257a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *start = 258a54f2bb7SMarouene Boubakri SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 259a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *end = 260a54f2bb7SMarouene Boubakri SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); 261a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *pta; 262a54f2bb7SMarouene Boubakri 263a54f2bb7SMarouene Boubakri for (pta = start; pta < end; pta++) { 264a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *pta2; 265a54f2bb7SMarouene Boubakri 266a54f2bb7SMarouene Boubakri /* PTAs must all have a specific UUID */ 267a54f2bb7SMarouene Boubakri for (pta2 = pta + 1; pta2 < end; pta2++) { 268a54f2bb7SMarouene Boubakri if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) 269a54f2bb7SMarouene Boubakri goto err; 270a54f2bb7SMarouene Boubakri } 271a54f2bb7SMarouene Boubakri 272a54f2bb7SMarouene Boubakri if (!pta->name || 273a54f2bb7SMarouene Boubakri (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || 274a54f2bb7SMarouene Boubakri pta->flags & ~PTA_ALLOWED_FLAGS || 275a54f2bb7SMarouene Boubakri !pta->invoke_command_entry_point) 276a54f2bb7SMarouene Boubakri goto err; 277a54f2bb7SMarouene Boubakri } 278a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 279a54f2bb7SMarouene Boubakri err: 280a54f2bb7SMarouene Boubakri DMSG("pseudo TA error at %p", (void *)pta); 281a54f2bb7SMarouene Boubakri panic("PTA"); 282a54f2bb7SMarouene Boubakri } 283a54f2bb7SMarouene Boubakri 284a54f2bb7SMarouene Boubakri service_init(verify_pseudo_tas_conformance); 285a54f2bb7SMarouene Boubakri 286a54f2bb7SMarouene Boubakri /*----------------------------------------------------------------------------- 287a54f2bb7SMarouene Boubakri * Initialises a session based on the UUID or ptr to the ta 288a54f2bb7SMarouene Boubakri * Returns ptr to the session (ta_session) and a TEE_Result 289a54f2bb7SMarouene Boubakri *---------------------------------------------------------------------------*/ 290a54f2bb7SMarouene Boubakri TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, 291a54f2bb7SMarouene Boubakri struct tee_ta_session *s) 292a54f2bb7SMarouene Boubakri { 293a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = NULL; 294a54f2bb7SMarouene Boubakri struct tee_ta_ctx *ctx; 295a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *ta; 296a54f2bb7SMarouene Boubakri 297a54f2bb7SMarouene Boubakri DMSG("Lookup pseudo TA %pUl", (void *)uuid); 298a54f2bb7SMarouene Boubakri 299a54f2bb7SMarouene Boubakri ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 300a54f2bb7SMarouene Boubakri while (true) { 301a54f2bb7SMarouene Boubakri if (ta >= SCATTERED_ARRAY_END(pseudo_tas, 302a54f2bb7SMarouene Boubakri struct pseudo_ta_head)) 303a54f2bb7SMarouene Boubakri return TEE_ERROR_ITEM_NOT_FOUND; 304a54f2bb7SMarouene Boubakri if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) 305a54f2bb7SMarouene Boubakri break; 306a54f2bb7SMarouene Boubakri ta++; 307a54f2bb7SMarouene Boubakri } 308a54f2bb7SMarouene Boubakri 309a54f2bb7SMarouene Boubakri /* Load a new TA and create a session */ 310a54f2bb7SMarouene Boubakri DMSG("Open %s", ta->name); 311a54f2bb7SMarouene Boubakri stc = calloc(1, sizeof(struct pseudo_ta_ctx)); 312a54f2bb7SMarouene Boubakri if (!stc) 313a54f2bb7SMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY; 314a54f2bb7SMarouene Boubakri ctx = &stc->ctx; 315a54f2bb7SMarouene Boubakri 316a54f2bb7SMarouene Boubakri ctx->ref_count = 1; 317a54f2bb7SMarouene Boubakri ctx->flags = ta->flags; 318a54f2bb7SMarouene Boubakri stc->pseudo_ta = ta; 319a54f2bb7SMarouene Boubakri ctx->ts_ctx.uuid = ta->uuid; 320a54f2bb7SMarouene Boubakri ctx->ts_ctx.ops = &pseudo_ta_ops; 321a54f2bb7SMarouene Boubakri 322a54f2bb7SMarouene Boubakri mutex_lock(&tee_ta_mutex); 323a54f2bb7SMarouene Boubakri s->ts_sess.ctx = &ctx->ts_ctx; 324a54f2bb7SMarouene Boubakri TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); 325a54f2bb7SMarouene Boubakri mutex_unlock(&tee_ta_mutex); 326a54f2bb7SMarouene Boubakri 327a54f2bb7SMarouene Boubakri DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); 328a54f2bb7SMarouene Boubakri 329a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 330a54f2bb7SMarouene Boubakri } 331653409a2SJerome Forissier 332653409a2SJerome Forissier TEE_Result to_bounce_params(uint32_t param_types, 333653409a2SJerome Forissier TEE_Param params[TEE_NUM_PARAMS], 334653409a2SJerome Forissier TEE_Param bparams[TEE_NUM_PARAMS], 335653409a2SJerome Forissier TEE_Param **oparams) 336653409a2SJerome Forissier { 337653409a2SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 338653409a2SJerome Forissier void *kptr = NULL; 339653409a2SJerome Forissier void *uptr = NULL; 340653409a2SJerome Forissier size_t size = 0; 341653409a2SJerome Forissier int i = 0; 342653409a2SJerome Forissier 343653409a2SJerome Forissier if (!is_caller_ta_with_pan()) { 344653409a2SJerome Forissier *oparams = params; 345653409a2SJerome Forissier return TEE_SUCCESS; 346653409a2SJerome Forissier } 347653409a2SJerome Forissier 348653409a2SJerome Forissier for (i = 0; i < TEE_NUM_PARAMS; i++) { 349653409a2SJerome Forissier switch (TEE_PARAM_TYPE_GET(param_types, i)) { 350653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_INPUT: 351653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_OUTPUT: 352653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_INOUT: 353653409a2SJerome Forissier size = params[i].memref.size; 354653409a2SJerome Forissier uptr = params[i].memref.buffer; 355653409a2SJerome Forissier kptr = bb_alloc(size); 356653409a2SJerome Forissier if (!kptr) 357653409a2SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 358653409a2SJerome Forissier bparams[i].memref.buffer = kptr; 359653409a2SJerome Forissier bparams[i].memref.size = size; 360653409a2SJerome Forissier break; 361653409a2SJerome Forissier default: 362653409a2SJerome Forissier break; 363653409a2SJerome Forissier } 364653409a2SJerome Forissier switch (TEE_PARAM_TYPE_GET(param_types, i)) { 365653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_INPUT: 366653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_INOUT: 367653409a2SJerome Forissier res = copy_from_user(kptr, uptr, size); 368653409a2SJerome Forissier if (res) 369653409a2SJerome Forissier return res; 370653409a2SJerome Forissier break; 371653409a2SJerome Forissier case TEE_PARAM_TYPE_VALUE_INPUT: 372653409a2SJerome Forissier case TEE_PARAM_TYPE_VALUE_INOUT: 373653409a2SJerome Forissier bparams[i].value.a = params[i].value.a; 374653409a2SJerome Forissier bparams[i].value.b = params[i].value.b; 375653409a2SJerome Forissier break; 376653409a2SJerome Forissier default: 377653409a2SJerome Forissier break; 378653409a2SJerome Forissier } 379653409a2SJerome Forissier } 380653409a2SJerome Forissier *oparams = bparams; 381653409a2SJerome Forissier 382653409a2SJerome Forissier return TEE_SUCCESS; 383653409a2SJerome Forissier } 384653409a2SJerome Forissier 385653409a2SJerome Forissier TEE_Result from_bounce_params(uint32_t param_types, 386653409a2SJerome Forissier TEE_Param params[TEE_NUM_PARAMS], 387653409a2SJerome Forissier TEE_Param bparams[TEE_NUM_PARAMS], 388653409a2SJerome Forissier TEE_Param *eparams) 389653409a2SJerome Forissier { 390653409a2SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 391653409a2SJerome Forissier void *kptr = NULL; 392653409a2SJerome Forissier void *uptr = NULL; 393653409a2SJerome Forissier size_t size = 0; 394653409a2SJerome Forissier int i = 0; 395653409a2SJerome Forissier 396653409a2SJerome Forissier if (eparams == params) 397653409a2SJerome Forissier return TEE_SUCCESS; 398653409a2SJerome Forissier 399653409a2SJerome Forissier for (i = 0; i < TEE_NUM_PARAMS; i++) { 400653409a2SJerome Forissier switch (TEE_PARAM_TYPE_GET(param_types, i)) { 401653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_OUTPUT: 402653409a2SJerome Forissier case TEE_PARAM_TYPE_MEMREF_INOUT: 403653409a2SJerome Forissier uptr = params[i].memref.buffer; 404653409a2SJerome Forissier kptr = bparams[i].memref.buffer; 405653409a2SJerome Forissier size = bparams[i].memref.size; 406653409a2SJerome Forissier res = copy_to_user(uptr, kptr, size); 407653409a2SJerome Forissier if (res) 408653409a2SJerome Forissier return res; 409653409a2SJerome Forissier params[i].memref.size = size; 410653409a2SJerome Forissier break; 411653409a2SJerome Forissier case TEE_PARAM_TYPE_VALUE_OUTPUT: 412653409a2SJerome Forissier case TEE_PARAM_TYPE_VALUE_INOUT: 413653409a2SJerome Forissier params[i].value.a = bparams[i].value.a; 414653409a2SJerome Forissier params[i].value.b = bparams[i].value.b; 415653409a2SJerome Forissier break; 416653409a2SJerome Forissier default: 417653409a2SJerome Forissier break; 418653409a2SJerome Forissier } 419653409a2SJerome Forissier } 420653409a2SJerome Forissier 421653409a2SJerome Forissier return res; 422653409a2SJerome Forissier } 423