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> 12a54f2bb7SMarouene Boubakri #include <mm/core_memprot.h> 13a54f2bb7SMarouene Boubakri #include <mm/mobj.h> 14a54f2bb7SMarouene Boubakri #include <stdlib.h> 15a54f2bb7SMarouene Boubakri #include <string.h> 16a54f2bb7SMarouene Boubakri #include <trace.h> 17a54f2bb7SMarouene Boubakri #include <types_ext.h> 18a54f2bb7SMarouene Boubakri 19a54f2bb7SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH 20a54f2bb7SMarouene Boubakri static bool client_is_secure(struct ts_session *s) 21a54f2bb7SMarouene Boubakri { 22a54f2bb7SMarouene Boubakri /* rely on core entry to have constrained client IDs */ 23a54f2bb7SMarouene Boubakri if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) 24a54f2bb7SMarouene Boubakri return true; 25a54f2bb7SMarouene Boubakri 26a54f2bb7SMarouene Boubakri return false; 27a54f2bb7SMarouene Boubakri } 28a54f2bb7SMarouene Boubakri 29a54f2bb7SMarouene Boubakri static bool validate_in_param(struct ts_session *s, struct mobj *mobj) 30a54f2bb7SMarouene Boubakri { 31a54f2bb7SMarouene Boubakri /* Supplying NULL to query buffer size is OK */ 32a54f2bb7SMarouene Boubakri if (!mobj) 33a54f2bb7SMarouene Boubakri return true; 34a54f2bb7SMarouene Boubakri 35a54f2bb7SMarouene Boubakri /* for secure clients, core entry always holds valid memref objects */ 36a54f2bb7SMarouene Boubakri if (client_is_secure(s)) 37a54f2bb7SMarouene Boubakri return true; 38a54f2bb7SMarouene Boubakri 39a54f2bb7SMarouene Boubakri /* all non-secure memory references are handled by PTAs */ 40a54f2bb7SMarouene Boubakri if (mobj_is_nonsec(mobj)) 41a54f2bb7SMarouene Boubakri return true; 42a54f2bb7SMarouene Boubakri 43a54f2bb7SMarouene Boubakri return false; 44a54f2bb7SMarouene Boubakri } 45a54f2bb7SMarouene Boubakri #else 46a54f2bb7SMarouene Boubakri static bool validate_in_param(struct ts_session *s __unused, 47a54f2bb7SMarouene Boubakri struct mobj *mobj __unused) 48a54f2bb7SMarouene Boubakri { 49a54f2bb7SMarouene Boubakri /* At this point, core has filled only valid accessible memref mobj */ 50a54f2bb7SMarouene Boubakri return true; 51a54f2bb7SMarouene Boubakri } 52a54f2bb7SMarouene Boubakri #endif 53a54f2bb7SMarouene Boubakri 54a54f2bb7SMarouene Boubakri /* Maps pseudo TA params */ 55a54f2bb7SMarouene Boubakri static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, 56a54f2bb7SMarouene Boubakri struct tee_ta_param *param, 57a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS], 58a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS]) 59a54f2bb7SMarouene Boubakri { 60a54f2bb7SMarouene Boubakri size_t n; 61a54f2bb7SMarouene Boubakri void *va; 62a54f2bb7SMarouene Boubakri struct param_mem *mem; 63a54f2bb7SMarouene Boubakri 64a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 65a54f2bb7SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(param->types, n)) { 66a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INPUT: 67a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 68a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 69a54f2bb7SMarouene Boubakri tee_param[n].value.a = param->u[n].val.a; 70a54f2bb7SMarouene Boubakri tee_param[n].value.b = param->u[n].val.b; 71a54f2bb7SMarouene Boubakri break; 72a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INPUT: 73a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 74a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 75a54f2bb7SMarouene Boubakri mem = ¶m->u[n].mem; 76a54f2bb7SMarouene Boubakri if (!validate_in_param(s, mem->mobj)) 77a54f2bb7SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 78a54f2bb7SMarouene Boubakri if (mem->size) { 79a54f2bb7SMarouene Boubakri TEE_Result res = mobj_inc_map(mem->mobj); 80a54f2bb7SMarouene Boubakri 81a54f2bb7SMarouene Boubakri if (res) 82a54f2bb7SMarouene Boubakri return res; 83a54f2bb7SMarouene Boubakri did_map[n] = true; 84*9c4aaf67SJens Wiklander va = mobj_get_va(mem->mobj, mem->offs, 85*9c4aaf67SJens Wiklander mem->size); 86a54f2bb7SMarouene Boubakri if (!va) 87a54f2bb7SMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 88a54f2bb7SMarouene Boubakri } else { 89a54f2bb7SMarouene Boubakri va = NULL; 90a54f2bb7SMarouene Boubakri } 91a54f2bb7SMarouene Boubakri 92a54f2bb7SMarouene Boubakri tee_param[n].memref.buffer = va; 93a54f2bb7SMarouene Boubakri tee_param[n].memref.size = mem->size; 94a54f2bb7SMarouene Boubakri break; 95a54f2bb7SMarouene Boubakri default: 96a54f2bb7SMarouene Boubakri memset(tee_param + n, 0, sizeof(TEE_Param)); 97a54f2bb7SMarouene Boubakri break; 98a54f2bb7SMarouene Boubakri } 99a54f2bb7SMarouene Boubakri } 100a54f2bb7SMarouene Boubakri 101a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 102a54f2bb7SMarouene Boubakri } 103a54f2bb7SMarouene Boubakri 104a54f2bb7SMarouene Boubakri static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], 105a54f2bb7SMarouene Boubakri struct tee_ta_param *param) 106a54f2bb7SMarouene Boubakri { 107a54f2bb7SMarouene Boubakri size_t n; 108a54f2bb7SMarouene Boubakri 109a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 110a54f2bb7SMarouene Boubakri switch (TEE_PARAM_TYPE_GET(param->types, n)) { 111a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_OUTPUT: 112a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_VALUE_INOUT: 113a54f2bb7SMarouene Boubakri param->u[n].val.a = tee_param[n].value.a; 114a54f2bb7SMarouene Boubakri param->u[n].val.b = tee_param[n].value.b; 115a54f2bb7SMarouene Boubakri break; 116a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_OUTPUT: 117a54f2bb7SMarouene Boubakri case TEE_PARAM_TYPE_MEMREF_INOUT: 118a54f2bb7SMarouene Boubakri param->u[n].mem.size = tee_param[n].memref.size; 119a54f2bb7SMarouene Boubakri break; 120a54f2bb7SMarouene Boubakri default: 121a54f2bb7SMarouene Boubakri break; 122a54f2bb7SMarouene Boubakri } 123a54f2bb7SMarouene Boubakri } 124a54f2bb7SMarouene Boubakri } 125a54f2bb7SMarouene Boubakri 126a54f2bb7SMarouene Boubakri static void unmap_mapped_param(struct tee_ta_param *param, 127a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS]) 128a54f2bb7SMarouene Boubakri { 129a54f2bb7SMarouene Boubakri size_t n; 130a54f2bb7SMarouene Boubakri 131a54f2bb7SMarouene Boubakri for (n = 0; n < TEE_NUM_PARAMS; n++) { 132a54f2bb7SMarouene Boubakri if (did_map[n]) { 133a54f2bb7SMarouene Boubakri TEE_Result res __maybe_unused; 134a54f2bb7SMarouene Boubakri 135a54f2bb7SMarouene Boubakri res = mobj_dec_map(param->u[n].mem.mobj); 136a54f2bb7SMarouene Boubakri assert(!res); 137a54f2bb7SMarouene Boubakri } 138a54f2bb7SMarouene Boubakri } 139a54f2bb7SMarouene Boubakri } 140a54f2bb7SMarouene Boubakri 141a54f2bb7SMarouene Boubakri static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) 142a54f2bb7SMarouene Boubakri { 143a54f2bb7SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 144a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 145a54f2bb7SMarouene Boubakri struct tee_ta_session *ta_sess = to_ta_session(s); 146a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 147a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS] = { false }; 148a54f2bb7SMarouene Boubakri 149a54f2bb7SMarouene Boubakri ts_push_current_session(s); 150a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 151a54f2bb7SMarouene Boubakri 152a54f2bb7SMarouene Boubakri if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { 153a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->create_entry_point(); 154a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) 155a54f2bb7SMarouene Boubakri goto out; 156a54f2bb7SMarouene Boubakri } 157a54f2bb7SMarouene Boubakri 158a54f2bb7SMarouene Boubakri if (stc->pseudo_ta->open_session_entry_point) { 159a54f2bb7SMarouene Boubakri void **user_ctx = &s->user_ctx; 160a54f2bb7SMarouene Boubakri uint32_t param_types = 0; 161a54f2bb7SMarouene Boubakri 162a54f2bb7SMarouene Boubakri if (ta_sess->param) { 163a54f2bb7SMarouene Boubakri res = copy_in_param(s, ta_sess->param, tee_param, 164a54f2bb7SMarouene Boubakri did_map); 165a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) { 166a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 167a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TEE; 168a54f2bb7SMarouene Boubakri goto out; 169a54f2bb7SMarouene Boubakri } 170a54f2bb7SMarouene Boubakri param_types = ta_sess->param->types; 171a54f2bb7SMarouene Boubakri } 172a54f2bb7SMarouene Boubakri 173a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->open_session_entry_point(param_types, 174a54f2bb7SMarouene Boubakri tee_param, 175a54f2bb7SMarouene Boubakri user_ctx); 176a54f2bb7SMarouene Boubakri if (ta_sess->param) { 177a54f2bb7SMarouene Boubakri update_out_param(tee_param, ta_sess->param); 178a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 179a54f2bb7SMarouene Boubakri } 180a54f2bb7SMarouene Boubakri } 181a54f2bb7SMarouene Boubakri 182a54f2bb7SMarouene Boubakri out: 183a54f2bb7SMarouene Boubakri ts_pop_current_session(); 184a54f2bb7SMarouene Boubakri return res; 185a54f2bb7SMarouene Boubakri } 186a54f2bb7SMarouene Boubakri 187a54f2bb7SMarouene Boubakri static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) 188a54f2bb7SMarouene Boubakri { 189a54f2bb7SMarouene Boubakri TEE_Result res = TEE_SUCCESS; 190a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 191a54f2bb7SMarouene Boubakri struct tee_ta_session *ta_sess = to_ta_session(s); 192a54f2bb7SMarouene Boubakri uint32_t param_types = 0; 193a54f2bb7SMarouene Boubakri TEE_Param tee_param[TEE_NUM_PARAMS] = { }; 194a54f2bb7SMarouene Boubakri bool did_map[TEE_NUM_PARAMS] = { false }; 195a54f2bb7SMarouene Boubakri 196a54f2bb7SMarouene Boubakri ts_push_current_session(s); 197a54f2bb7SMarouene Boubakri if (ta_sess->param) { 198a54f2bb7SMarouene Boubakri res = copy_in_param(s, ta_sess->param, tee_param, did_map); 199a54f2bb7SMarouene Boubakri if (res != TEE_SUCCESS) { 200a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 201a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TEE; 202a54f2bb7SMarouene Boubakri goto out; 203a54f2bb7SMarouene Boubakri } 204a54f2bb7SMarouene Boubakri param_types = ta_sess->param->types; 205a54f2bb7SMarouene Boubakri } 206a54f2bb7SMarouene Boubakri 207a54f2bb7SMarouene Boubakri ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; 208a54f2bb7SMarouene Boubakri res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, 209a54f2bb7SMarouene Boubakri param_types, 210a54f2bb7SMarouene Boubakri tee_param); 211a54f2bb7SMarouene Boubakri if (ta_sess->param) { 212a54f2bb7SMarouene Boubakri update_out_param(tee_param, ta_sess->param); 213a54f2bb7SMarouene Boubakri unmap_mapped_param(ta_sess->param, did_map); 214a54f2bb7SMarouene Boubakri } 215a54f2bb7SMarouene Boubakri out: 216a54f2bb7SMarouene Boubakri ts_pop_current_session(); 217a54f2bb7SMarouene Boubakri return res; 218a54f2bb7SMarouene Boubakri } 219a54f2bb7SMarouene Boubakri 220a54f2bb7SMarouene Boubakri static void pseudo_ta_enter_close_session(struct ts_session *s) 221a54f2bb7SMarouene Boubakri { 222a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); 223a54f2bb7SMarouene Boubakri void *user_ctx = s->user_ctx; 224a54f2bb7SMarouene Boubakri 225a54f2bb7SMarouene Boubakri ts_push_current_session(s); 226a54f2bb7SMarouene Boubakri 227a54f2bb7SMarouene Boubakri if (stc->pseudo_ta->close_session_entry_point) 228a54f2bb7SMarouene Boubakri stc->pseudo_ta->close_session_entry_point(user_ctx); 229a54f2bb7SMarouene Boubakri 230a54f2bb7SMarouene Boubakri if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) 231a54f2bb7SMarouene Boubakri stc->pseudo_ta->destroy_entry_point(); 232a54f2bb7SMarouene Boubakri 233a54f2bb7SMarouene Boubakri ts_pop_current_session(); 234a54f2bb7SMarouene Boubakri } 235a54f2bb7SMarouene Boubakri 236a54f2bb7SMarouene Boubakri static void pseudo_ta_destroy(struct ts_ctx *ctx) 237a54f2bb7SMarouene Boubakri { 238a54f2bb7SMarouene Boubakri free(to_pseudo_ta_ctx(ctx)); 239a54f2bb7SMarouene Boubakri } 240a54f2bb7SMarouene Boubakri 241a54f2bb7SMarouene Boubakri static const struct ts_ops pseudo_ta_ops = { 242a54f2bb7SMarouene Boubakri .enter_open_session = pseudo_ta_enter_open_session, 243a54f2bb7SMarouene Boubakri .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, 244a54f2bb7SMarouene Boubakri .enter_close_session = pseudo_ta_enter_close_session, 245a54f2bb7SMarouene Boubakri .destroy = pseudo_ta_destroy, 246a54f2bb7SMarouene Boubakri }; 247a54f2bb7SMarouene Boubakri 248a54f2bb7SMarouene Boubakri bool is_pseudo_ta_ctx(struct ts_ctx *ctx) 249a54f2bb7SMarouene Boubakri { 250a54f2bb7SMarouene Boubakri return ctx->ops == &pseudo_ta_ops; 251a54f2bb7SMarouene Boubakri } 252a54f2bb7SMarouene Boubakri 253a54f2bb7SMarouene Boubakri /* Insures declared pseudo TAs conforms with core expectations */ 254a54f2bb7SMarouene Boubakri static TEE_Result verify_pseudo_tas_conformance(void) 255a54f2bb7SMarouene Boubakri { 256a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *start = 257a54f2bb7SMarouene Boubakri SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 258a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *end = 259a54f2bb7SMarouene Boubakri SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); 260a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *pta; 261a54f2bb7SMarouene Boubakri 262a54f2bb7SMarouene Boubakri for (pta = start; pta < end; pta++) { 263a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *pta2; 264a54f2bb7SMarouene Boubakri 265a54f2bb7SMarouene Boubakri /* PTAs must all have a specific UUID */ 266a54f2bb7SMarouene Boubakri for (pta2 = pta + 1; pta2 < end; pta2++) { 267a54f2bb7SMarouene Boubakri if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) 268a54f2bb7SMarouene Boubakri goto err; 269a54f2bb7SMarouene Boubakri } 270a54f2bb7SMarouene Boubakri 271a54f2bb7SMarouene Boubakri if (!pta->name || 272a54f2bb7SMarouene Boubakri (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || 273a54f2bb7SMarouene Boubakri pta->flags & ~PTA_ALLOWED_FLAGS || 274a54f2bb7SMarouene Boubakri !pta->invoke_command_entry_point) 275a54f2bb7SMarouene Boubakri goto err; 276a54f2bb7SMarouene Boubakri } 277a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 278a54f2bb7SMarouene Boubakri err: 279a54f2bb7SMarouene Boubakri DMSG("pseudo TA error at %p", (void *)pta); 280a54f2bb7SMarouene Boubakri panic("PTA"); 281a54f2bb7SMarouene Boubakri } 282a54f2bb7SMarouene Boubakri 283a54f2bb7SMarouene Boubakri service_init(verify_pseudo_tas_conformance); 284a54f2bb7SMarouene Boubakri 285a54f2bb7SMarouene Boubakri /*----------------------------------------------------------------------------- 286a54f2bb7SMarouene Boubakri * Initialises a session based on the UUID or ptr to the ta 287a54f2bb7SMarouene Boubakri * Returns ptr to the session (ta_session) and a TEE_Result 288a54f2bb7SMarouene Boubakri *---------------------------------------------------------------------------*/ 289a54f2bb7SMarouene Boubakri TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, 290a54f2bb7SMarouene Boubakri struct tee_ta_session *s) 291a54f2bb7SMarouene Boubakri { 292a54f2bb7SMarouene Boubakri struct pseudo_ta_ctx *stc = NULL; 293a54f2bb7SMarouene Boubakri struct tee_ta_ctx *ctx; 294a54f2bb7SMarouene Boubakri const struct pseudo_ta_head *ta; 295a54f2bb7SMarouene Boubakri 296a54f2bb7SMarouene Boubakri DMSG("Lookup pseudo TA %pUl", (void *)uuid); 297a54f2bb7SMarouene Boubakri 298a54f2bb7SMarouene Boubakri ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); 299a54f2bb7SMarouene Boubakri while (true) { 300a54f2bb7SMarouene Boubakri if (ta >= SCATTERED_ARRAY_END(pseudo_tas, 301a54f2bb7SMarouene Boubakri struct pseudo_ta_head)) 302a54f2bb7SMarouene Boubakri return TEE_ERROR_ITEM_NOT_FOUND; 303a54f2bb7SMarouene Boubakri if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) 304a54f2bb7SMarouene Boubakri break; 305a54f2bb7SMarouene Boubakri ta++; 306a54f2bb7SMarouene Boubakri } 307a54f2bb7SMarouene Boubakri 308a54f2bb7SMarouene Boubakri /* Load a new TA and create a session */ 309a54f2bb7SMarouene Boubakri DMSG("Open %s", ta->name); 310a54f2bb7SMarouene Boubakri stc = calloc(1, sizeof(struct pseudo_ta_ctx)); 311a54f2bb7SMarouene Boubakri if (!stc) 312a54f2bb7SMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY; 313a54f2bb7SMarouene Boubakri ctx = &stc->ctx; 314a54f2bb7SMarouene Boubakri 315a54f2bb7SMarouene Boubakri ctx->ref_count = 1; 316a54f2bb7SMarouene Boubakri ctx->flags = ta->flags; 317a54f2bb7SMarouene Boubakri stc->pseudo_ta = ta; 318a54f2bb7SMarouene Boubakri ctx->ts_ctx.uuid = ta->uuid; 319a54f2bb7SMarouene Boubakri ctx->ts_ctx.ops = &pseudo_ta_ops; 320a54f2bb7SMarouene Boubakri 321a54f2bb7SMarouene Boubakri mutex_lock(&tee_ta_mutex); 322a54f2bb7SMarouene Boubakri s->ts_sess.ctx = &ctx->ts_ctx; 323a54f2bb7SMarouene Boubakri TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); 324a54f2bb7SMarouene Boubakri mutex_unlock(&tee_ta_mutex); 325a54f2bb7SMarouene Boubakri 326a54f2bb7SMarouene Boubakri DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); 327a54f2bb7SMarouene Boubakri 328a54f2bb7SMarouene Boubakri return TEE_SUCCESS; 329a54f2bb7SMarouene Boubakri } 330