1*31b31015Sliushiwei // SPDX-License-Identifier: BSD-2-Clause 2*31b31015Sliushiwei /* 3*31b31015Sliushiwei * Copyright (c) 2014, STMicroelectronics International N.V. 4*31b31015Sliushiwei * Copyright (c) 2022, Linaro Limited. 5*31b31015Sliushiwei */ 6*31b31015Sliushiwei #include <compiler.h> 7*31b31015Sliushiwei #include <link.h> 8*31b31015Sliushiwei #include <malloc.h> 9*31b31015Sliushiwei #include <memtag.h> 10*31b31015Sliushiwei #include <stdbool.h> 11*31b31015Sliushiwei #include <stdlib.h> 12*31b31015Sliushiwei #include <string.h> 13*31b31015Sliushiwei #include <sys/queue.h> 14*31b31015Sliushiwei #include <tee_api.h> 15*31b31015Sliushiwei #include <tee_arith_internal.h> 16*31b31015Sliushiwei #include <tee_internal_api_extensions.h> 17*31b31015Sliushiwei #include <tee_ta_api.h> 18*31b31015Sliushiwei #include <user_ta_header.h> 19*31b31015Sliushiwei #include <utee_syscalls.h> 20*31b31015Sliushiwei #include "tee_api_private.h" 21*31b31015Sliushiwei 22*31b31015Sliushiwei struct ta_session { 23*31b31015Sliushiwei uint32_t session_id; 24*31b31015Sliushiwei void *session_ctx; 25*31b31015Sliushiwei TAILQ_ENTRY(ta_session) link; 26*31b31015Sliushiwei }; 27*31b31015Sliushiwei 28*31b31015Sliushiwei static TAILQ_HEAD(ta_sessions, ta_session) ta_sessions = 29*31b31015Sliushiwei TAILQ_HEAD_INITIALIZER(ta_sessions); 30*31b31015Sliushiwei 31*31b31015Sliushiwei static bool init_done; 32*31b31015Sliushiwei 33*31b31015Sliushiwei /* From user_ta_header.c, built within TA */ 34*31b31015Sliushiwei extern uint8_t ta_heap[]; 35*31b31015Sliushiwei extern const size_t ta_heap_size; 36*31b31015Sliushiwei extern struct ta_head ta_head; 37*31b31015Sliushiwei 38*31b31015Sliushiwei uint32_t ta_param_types; 39*31b31015Sliushiwei TEE_Param ta_params[TEE_NUM_PARAMS]; 40*31b31015Sliushiwei 41*31b31015Sliushiwei struct malloc_ctx *__ta_no_share_malloc_ctx; 42*31b31015Sliushiwei 43*31b31015Sliushiwei struct __elf_phdr_info __elf_phdr_info; 44*31b31015Sliushiwei 45*31b31015Sliushiwei struct phdr_info { 46*31b31015Sliushiwei struct dl_phdr_info info; 47*31b31015Sliushiwei TAILQ_ENTRY(phdr_info) link; 48*31b31015Sliushiwei }; 49*31b31015Sliushiwei 50*31b31015Sliushiwei static TAILQ_HEAD(phdr_info_head, phdr_info) __phdr_info_head = 51*31b31015Sliushiwei TAILQ_HEAD_INITIALIZER(__phdr_info_head); 52*31b31015Sliushiwei /* 53*31b31015Sliushiwei * Keep track of how many modules have been initialized so that subsequent 54*31b31015Sliushiwei * dlopen() calls will not run the same initializers again 55*31b31015Sliushiwei */ 56*31b31015Sliushiwei static size_t _num_mod_init; 57*31b31015Sliushiwei 58*31b31015Sliushiwei static int _init_iterate_phdr_cb(struct dl_phdr_info *info, 59*31b31015Sliushiwei size_t size __unused, void *data) 60*31b31015Sliushiwei { 61*31b31015Sliushiwei struct phdr_info *qe = NULL; 62*31b31015Sliushiwei size_t *count = data; 63*31b31015Sliushiwei 64*31b31015Sliushiwei qe = malloc(sizeof(*qe)); 65*31b31015Sliushiwei if (!qe) { 66*31b31015Sliushiwei EMSG("init/fini: out of memory"); 67*31b31015Sliushiwei abort(); 68*31b31015Sliushiwei } 69*31b31015Sliushiwei qe->info = *info; 70*31b31015Sliushiwei TAILQ_INSERT_TAIL(&__phdr_info_head, qe, link); 71*31b31015Sliushiwei (*count)++; 72*31b31015Sliushiwei return 0; 73*31b31015Sliushiwei } 74*31b31015Sliushiwei 75*31b31015Sliushiwei static void _get_fn_array(struct dl_phdr_info *info, Elf_Sword tag_a, 76*31b31015Sliushiwei Elf_Sword tag_s, void (***fn)(void), size_t *num_fn) 77*31b31015Sliushiwei { 78*31b31015Sliushiwei const Elf_Phdr *phdr = NULL; 79*31b31015Sliushiwei Elf_Dyn *dyn = NULL; 80*31b31015Sliushiwei size_t num_dyn = 0; 81*31b31015Sliushiwei size_t i = 0; 82*31b31015Sliushiwei size_t j = 0; 83*31b31015Sliushiwei 84*31b31015Sliushiwei for (i = 0; i < info->dlpi_phnum; i++) { 85*31b31015Sliushiwei phdr = info->dlpi_phdr + i; 86*31b31015Sliushiwei if (phdr->p_type != PT_DYNAMIC) 87*31b31015Sliushiwei continue; 88*31b31015Sliushiwei num_dyn = phdr->p_memsz / sizeof(Elf_Dyn); 89*31b31015Sliushiwei dyn = (Elf_Dyn *)(phdr->p_vaddr + info->dlpi_addr); 90*31b31015Sliushiwei for (j = 0; j < num_dyn; j++) { 91*31b31015Sliushiwei if (*fn && *num_fn) 92*31b31015Sliushiwei break; 93*31b31015Sliushiwei if (dyn->d_tag == DT_NULL) { 94*31b31015Sliushiwei break; 95*31b31015Sliushiwei } else if (dyn->d_tag == tag_a) { 96*31b31015Sliushiwei *fn = (void (**)(void))(dyn->d_un.d_ptr + 97*31b31015Sliushiwei info->dlpi_addr); 98*31b31015Sliushiwei } else if (dyn->d_tag == tag_s) { 99*31b31015Sliushiwei *num_fn = dyn->d_un.d_val / sizeof(Elf_Addr); 100*31b31015Sliushiwei } 101*31b31015Sliushiwei dyn++; 102*31b31015Sliushiwei } 103*31b31015Sliushiwei } 104*31b31015Sliushiwei } 105*31b31015Sliushiwei 106*31b31015Sliushiwei void __utee_call_elf_init_fn(void) 107*31b31015Sliushiwei { 108*31b31015Sliushiwei void (**fn)(void) = NULL; 109*31b31015Sliushiwei size_t num_mod = 0; 110*31b31015Sliushiwei size_t num_fn = 0; 111*31b31015Sliushiwei size_t mod = 0; 112*31b31015Sliushiwei size_t i = 0; 113*31b31015Sliushiwei struct phdr_info *qe = NULL; 114*31b31015Sliushiwei struct phdr_info *qe2 = NULL; 115*31b31015Sliushiwei 116*31b31015Sliushiwei dl_iterate_phdr(_init_iterate_phdr_cb, &num_mod); 117*31b31015Sliushiwei 118*31b31015Sliushiwei /* Reverse order: dependencies first */ 119*31b31015Sliushiwei TAILQ_FOREACH_REVERSE(qe, &__phdr_info_head, phdr_info_head, link) { 120*31b31015Sliushiwei if (mod == num_mod - _num_mod_init) 121*31b31015Sliushiwei break; 122*31b31015Sliushiwei _get_fn_array(&qe->info, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, &fn, 123*31b31015Sliushiwei &num_fn); 124*31b31015Sliushiwei for (i = 0; i < num_fn; i++) 125*31b31015Sliushiwei fn[i](); 126*31b31015Sliushiwei fn = NULL; 127*31b31015Sliushiwei num_fn = 0; 128*31b31015Sliushiwei mod++; 129*31b31015Sliushiwei } 130*31b31015Sliushiwei _num_mod_init += mod; 131*31b31015Sliushiwei 132*31b31015Sliushiwei TAILQ_FOREACH_SAFE(qe, &__phdr_info_head, link, qe2) { 133*31b31015Sliushiwei TAILQ_REMOVE(&__phdr_info_head, qe, link); 134*31b31015Sliushiwei free(qe); 135*31b31015Sliushiwei } 136*31b31015Sliushiwei } 137*31b31015Sliushiwei 138*31b31015Sliushiwei static int _fini_iterate_phdr_cb(struct dl_phdr_info *info, 139*31b31015Sliushiwei size_t size __unused, void *data __unused) 140*31b31015Sliushiwei { 141*31b31015Sliushiwei void (**fn)(void) = NULL; 142*31b31015Sliushiwei size_t num_fn = 0; 143*31b31015Sliushiwei size_t i = 0; 144*31b31015Sliushiwei 145*31b31015Sliushiwei _get_fn_array(info, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, &fn, &num_fn); 146*31b31015Sliushiwei 147*31b31015Sliushiwei for (i = 1; i <= num_fn; i++) 148*31b31015Sliushiwei fn[num_fn - i](); 149*31b31015Sliushiwei 150*31b31015Sliushiwei return 0; 151*31b31015Sliushiwei } 152*31b31015Sliushiwei 153*31b31015Sliushiwei void __utee_call_elf_fini_fn(void) 154*31b31015Sliushiwei { 155*31b31015Sliushiwei dl_iterate_phdr(_fini_iterate_phdr_cb, NULL); 156*31b31015Sliushiwei } 157*31b31015Sliushiwei 158*31b31015Sliushiwei static unsigned int get_memtag_implementation(void) 159*31b31015Sliushiwei { 160*31b31015Sliushiwei const char *s = "org.trustedfirmware.optee.cpu.feat_memtag_implemented"; 161*31b31015Sliushiwei uint32_t v = 0; 162*31b31015Sliushiwei 163*31b31015Sliushiwei if (TEE_GetPropertyAsU32(TEE_PROPSET_TEE_IMPLEMENTATION, s, &v)) 164*31b31015Sliushiwei return 0; 165*31b31015Sliushiwei return v; 166*31b31015Sliushiwei } 167*31b31015Sliushiwei 168*31b31015Sliushiwei static TEE_Result init_instance(void) 169*31b31015Sliushiwei { 170*31b31015Sliushiwei trace_set_level(tahead_get_trace_level()); 171*31b31015Sliushiwei __utee_gprof_init(); 172*31b31015Sliushiwei malloc_add_pool(ta_heap, ta_heap_size); 173*31b31015Sliushiwei if (__ta_no_share_heap_size) { 174*31b31015Sliushiwei __ta_no_share_malloc_ctx = malloc(raw_malloc_get_ctx_size()); 175*31b31015Sliushiwei if (__ta_no_share_malloc_ctx) { 176*31b31015Sliushiwei raw_malloc_init_ctx(__ta_no_share_malloc_ctx); 177*31b31015Sliushiwei raw_malloc_add_pool(__ta_no_share_malloc_ctx, 178*31b31015Sliushiwei __ta_no_share_heap, 179*31b31015Sliushiwei __ta_no_share_heap_size); 180*31b31015Sliushiwei } 181*31b31015Sliushiwei } 182*31b31015Sliushiwei memtag_init_ops(get_memtag_implementation()); 183*31b31015Sliushiwei _TEE_MathAPI_Init(); 184*31b31015Sliushiwei __utee_tcb_init(); 185*31b31015Sliushiwei __utee_call_elf_init_fn(); 186*31b31015Sliushiwei return TA_CreateEntryPoint(); 187*31b31015Sliushiwei } 188*31b31015Sliushiwei 189*31b31015Sliushiwei static void uninit_instance(void) 190*31b31015Sliushiwei { 191*31b31015Sliushiwei __utee_gprof_fini(); 192*31b31015Sliushiwei TA_DestroyEntryPoint(); 193*31b31015Sliushiwei __utee_call_elf_fini_fn(); 194*31b31015Sliushiwei } 195*31b31015Sliushiwei 196*31b31015Sliushiwei static void ta_header_save_params(uint32_t param_types, 197*31b31015Sliushiwei TEE_Param params[TEE_NUM_PARAMS]) 198*31b31015Sliushiwei { 199*31b31015Sliushiwei ta_param_types = param_types; 200*31b31015Sliushiwei 201*31b31015Sliushiwei if (params) 202*31b31015Sliushiwei memcpy(ta_params, params, sizeof(ta_params)); 203*31b31015Sliushiwei else 204*31b31015Sliushiwei memset(ta_params, 0, sizeof(ta_params)); 205*31b31015Sliushiwei } 206*31b31015Sliushiwei 207*31b31015Sliushiwei static struct ta_session *ta_header_get_session(uint32_t session_id) 208*31b31015Sliushiwei { 209*31b31015Sliushiwei struct ta_session *itr; 210*31b31015Sliushiwei 211*31b31015Sliushiwei TAILQ_FOREACH(itr, &ta_sessions, link) { 212*31b31015Sliushiwei if (itr->session_id == session_id) 213*31b31015Sliushiwei return itr; 214*31b31015Sliushiwei } 215*31b31015Sliushiwei return NULL; 216*31b31015Sliushiwei } 217*31b31015Sliushiwei 218*31b31015Sliushiwei static TEE_Result ta_header_add_session(uint32_t session_id) 219*31b31015Sliushiwei { 220*31b31015Sliushiwei struct ta_session *itr = ta_header_get_session(session_id); 221*31b31015Sliushiwei TEE_Result res; 222*31b31015Sliushiwei 223*31b31015Sliushiwei if (itr) 224*31b31015Sliushiwei return TEE_SUCCESS; 225*31b31015Sliushiwei 226*31b31015Sliushiwei if (!init_done) { 227*31b31015Sliushiwei init_done = true; 228*31b31015Sliushiwei res = init_instance(); 229*31b31015Sliushiwei if (res) 230*31b31015Sliushiwei return res; 231*31b31015Sliushiwei } 232*31b31015Sliushiwei 233*31b31015Sliushiwei itr = TEE_Malloc(sizeof(struct ta_session), 234*31b31015Sliushiwei TEE_USER_MEM_HINT_NO_FILL_ZERO); 235*31b31015Sliushiwei if (!itr) 236*31b31015Sliushiwei return TEE_ERROR_OUT_OF_MEMORY; 237*31b31015Sliushiwei itr->session_id = session_id; 238*31b31015Sliushiwei itr->session_ctx = 0; 239*31b31015Sliushiwei TAILQ_INSERT_TAIL(&ta_sessions, itr, link); 240*31b31015Sliushiwei 241*31b31015Sliushiwei return TEE_SUCCESS; 242*31b31015Sliushiwei } 243*31b31015Sliushiwei 244*31b31015Sliushiwei static void ta_header_remove_session(uint32_t session_id) 245*31b31015Sliushiwei { 246*31b31015Sliushiwei struct ta_session *itr; 247*31b31015Sliushiwei bool keep_alive; 248*31b31015Sliushiwei 249*31b31015Sliushiwei TAILQ_FOREACH(itr, &ta_sessions, link) { 250*31b31015Sliushiwei if (itr->session_id == session_id) { 251*31b31015Sliushiwei TAILQ_REMOVE(&ta_sessions, itr, link); 252*31b31015Sliushiwei TEE_Free(itr); 253*31b31015Sliushiwei 254*31b31015Sliushiwei keep_alive = 255*31b31015Sliushiwei (ta_head.flags & TA_FLAG_SINGLE_INSTANCE) && 256*31b31015Sliushiwei (ta_head.flags & TA_FLAG_INSTANCE_KEEP_ALIVE); 257*31b31015Sliushiwei if (TAILQ_EMPTY(&ta_sessions) && !keep_alive) 258*31b31015Sliushiwei uninit_instance(); 259*31b31015Sliushiwei 260*31b31015Sliushiwei return; 261*31b31015Sliushiwei } 262*31b31015Sliushiwei } 263*31b31015Sliushiwei } 264*31b31015Sliushiwei 265*31b31015Sliushiwei static void to_utee_params(struct utee_params *up, uint32_t param_types, 266*31b31015Sliushiwei const TEE_Param params[TEE_NUM_PARAMS]) 267*31b31015Sliushiwei { 268*31b31015Sliushiwei size_t n = 0; 269*31b31015Sliushiwei 270*31b31015Sliushiwei up->types = param_types; 271*31b31015Sliushiwei for (n = 0; n < TEE_NUM_PARAMS; n++) { 272*31b31015Sliushiwei switch (TEE_PARAM_TYPE_GET(param_types, n)) { 273*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_INPUT: 274*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_OUTPUT: 275*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_INOUT: 276*31b31015Sliushiwei up->vals[n * 2] = params[n].value.a; 277*31b31015Sliushiwei up->vals[n * 2 + 1] = params[n].value.b; 278*31b31015Sliushiwei break; 279*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_INPUT: 280*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_OUTPUT: 281*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_INOUT: 282*31b31015Sliushiwei up->vals[n * 2] = (uintptr_t)params[n].memref.buffer; 283*31b31015Sliushiwei up->vals[n * 2 + 1] = params[n].memref.size; 284*31b31015Sliushiwei break; 285*31b31015Sliushiwei default: 286*31b31015Sliushiwei up->vals[n * 2] = 0; 287*31b31015Sliushiwei up->vals[n * 2 + 1] = 0; 288*31b31015Sliushiwei break; 289*31b31015Sliushiwei } 290*31b31015Sliushiwei } 291*31b31015Sliushiwei } 292*31b31015Sliushiwei 293*31b31015Sliushiwei static void from_utee_params(TEE_Param params[TEE_NUM_PARAMS], 294*31b31015Sliushiwei uint32_t *param_types, 295*31b31015Sliushiwei const struct utee_params *up) 296*31b31015Sliushiwei { 297*31b31015Sliushiwei size_t n; 298*31b31015Sliushiwei uint32_t types = up->types; 299*31b31015Sliushiwei 300*31b31015Sliushiwei for (n = 0; n < TEE_NUM_PARAMS; n++) { 301*31b31015Sliushiwei uintptr_t a = up->vals[n * 2]; 302*31b31015Sliushiwei uintptr_t b = up->vals[n * 2 + 1]; 303*31b31015Sliushiwei 304*31b31015Sliushiwei switch (TEE_PARAM_TYPE_GET(types, n)) { 305*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_INPUT: 306*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_OUTPUT: 307*31b31015Sliushiwei case TEE_PARAM_TYPE_VALUE_INOUT: 308*31b31015Sliushiwei params[n].value.a = a; 309*31b31015Sliushiwei params[n].value.b = b; 310*31b31015Sliushiwei break; 311*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_INPUT: 312*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_OUTPUT: 313*31b31015Sliushiwei case TEE_PARAM_TYPE_MEMREF_INOUT: 314*31b31015Sliushiwei params[n].memref.buffer = (void *)a; 315*31b31015Sliushiwei params[n].memref.size = b; 316*31b31015Sliushiwei break; 317*31b31015Sliushiwei default: 318*31b31015Sliushiwei break; 319*31b31015Sliushiwei } 320*31b31015Sliushiwei } 321*31b31015Sliushiwei 322*31b31015Sliushiwei if (param_types) 323*31b31015Sliushiwei *param_types = types; 324*31b31015Sliushiwei } 325*31b31015Sliushiwei 326*31b31015Sliushiwei static TEE_Result entry_open_session(unsigned long session_id, 327*31b31015Sliushiwei struct utee_params *up) 328*31b31015Sliushiwei { 329*31b31015Sliushiwei TEE_Result res; 330*31b31015Sliushiwei struct ta_session *session; 331*31b31015Sliushiwei uint32_t param_types; 332*31b31015Sliushiwei TEE_Param params[TEE_NUM_PARAMS]; 333*31b31015Sliushiwei 334*31b31015Sliushiwei res = ta_header_add_session(session_id); 335*31b31015Sliushiwei if (res != TEE_SUCCESS) 336*31b31015Sliushiwei return res; 337*31b31015Sliushiwei 338*31b31015Sliushiwei session = ta_header_get_session(session_id); 339*31b31015Sliushiwei if (!session) 340*31b31015Sliushiwei return TEE_ERROR_BAD_STATE; 341*31b31015Sliushiwei 342*31b31015Sliushiwei from_utee_params(params, ¶m_types, up); 343*31b31015Sliushiwei ta_header_save_params(param_types, params); 344*31b31015Sliushiwei 345*31b31015Sliushiwei res = TA_OpenSessionEntryPoint(param_types, params, 346*31b31015Sliushiwei &session->session_ctx); 347*31b31015Sliushiwei 348*31b31015Sliushiwei to_utee_params(up, param_types, params); 349*31b31015Sliushiwei 350*31b31015Sliushiwei if (res != TEE_SUCCESS) 351*31b31015Sliushiwei ta_header_remove_session(session_id); 352*31b31015Sliushiwei return res; 353*31b31015Sliushiwei } 354*31b31015Sliushiwei 355*31b31015Sliushiwei static TEE_Result entry_close_session(unsigned long session_id) 356*31b31015Sliushiwei { 357*31b31015Sliushiwei struct ta_session *session = ta_header_get_session(session_id); 358*31b31015Sliushiwei 359*31b31015Sliushiwei if (!session) 360*31b31015Sliushiwei return TEE_ERROR_BAD_STATE; 361*31b31015Sliushiwei 362*31b31015Sliushiwei TA_CloseSessionEntryPoint(session->session_ctx); 363*31b31015Sliushiwei 364*31b31015Sliushiwei ta_header_remove_session(session_id); 365*31b31015Sliushiwei return TEE_SUCCESS; 366*31b31015Sliushiwei } 367*31b31015Sliushiwei 368*31b31015Sliushiwei static TEE_Result entry_invoke_command(unsigned long session_id, 369*31b31015Sliushiwei struct utee_params *up, unsigned long cmd_id) 370*31b31015Sliushiwei { 371*31b31015Sliushiwei TEE_Result res; 372*31b31015Sliushiwei uint32_t param_types; 373*31b31015Sliushiwei TEE_Param params[TEE_NUM_PARAMS]; 374*31b31015Sliushiwei struct ta_session *session = ta_header_get_session(session_id); 375*31b31015Sliushiwei 376*31b31015Sliushiwei if (!session) 377*31b31015Sliushiwei return TEE_ERROR_BAD_STATE; 378*31b31015Sliushiwei 379*31b31015Sliushiwei from_utee_params(params, ¶m_types, up); 380*31b31015Sliushiwei ta_header_save_params(param_types, params); 381*31b31015Sliushiwei 382*31b31015Sliushiwei res = TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id, 383*31b31015Sliushiwei param_types, params); 384*31b31015Sliushiwei 385*31b31015Sliushiwei to_utee_params(up, param_types, params); 386*31b31015Sliushiwei return res; 387*31b31015Sliushiwei } 388*31b31015Sliushiwei 389*31b31015Sliushiwei #if defined(CFG_TA_STATS) 390*31b31015Sliushiwei static TEE_Result entry_dump_memstats(unsigned long session_id __unused, 391*31b31015Sliushiwei struct utee_params *up) 392*31b31015Sliushiwei { 393*31b31015Sliushiwei uint32_t param_types = 0; 394*31b31015Sliushiwei TEE_Param params[TEE_NUM_PARAMS] = { }; 395*31b31015Sliushiwei struct malloc_stats stats = { }; 396*31b31015Sliushiwei 397*31b31015Sliushiwei from_utee_params(params, ¶m_types, up); 398*31b31015Sliushiwei ta_header_save_params(param_types, params); 399*31b31015Sliushiwei 400*31b31015Sliushiwei if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 401*31b31015Sliushiwei TEE_PARAM_TYPE_VALUE_OUTPUT, 402*31b31015Sliushiwei TEE_PARAM_TYPE_VALUE_OUTPUT, 403*31b31015Sliushiwei TEE_PARAM_TYPE_NONE) != param_types) 404*31b31015Sliushiwei return TEE_ERROR_BAD_PARAMETERS; 405*31b31015Sliushiwei 406*31b31015Sliushiwei malloc_get_stats(&stats); 407*31b31015Sliushiwei params[0].value.a = stats.allocated; 408*31b31015Sliushiwei params[0].value.b = stats.max_allocated; 409*31b31015Sliushiwei params[1].value.a = stats.size; 410*31b31015Sliushiwei params[1].value.b = stats.num_alloc_fail; 411*31b31015Sliushiwei params[2].value.a = stats.biggest_alloc_fail; 412*31b31015Sliushiwei params[2].value.b = stats.biggest_alloc_fail_used; 413*31b31015Sliushiwei to_utee_params(up, param_types, params); 414*31b31015Sliushiwei 415*31b31015Sliushiwei return TEE_SUCCESS; 416*31b31015Sliushiwei } 417*31b31015Sliushiwei #endif 418*31b31015Sliushiwei 419*31b31015Sliushiwei TEE_Result __utee_entry(unsigned long func, unsigned long session_id, 420*31b31015Sliushiwei struct utee_params *up, unsigned long cmd_id) 421*31b31015Sliushiwei { 422*31b31015Sliushiwei TEE_Result res; 423*31b31015Sliushiwei 424*31b31015Sliushiwei switch (func) { 425*31b31015Sliushiwei case UTEE_ENTRY_FUNC_OPEN_SESSION: 426*31b31015Sliushiwei res = entry_open_session(session_id, up); 427*31b31015Sliushiwei break; 428*31b31015Sliushiwei case UTEE_ENTRY_FUNC_CLOSE_SESSION: 429*31b31015Sliushiwei res = entry_close_session(session_id); 430*31b31015Sliushiwei break; 431*31b31015Sliushiwei case UTEE_ENTRY_FUNC_INVOKE_COMMAND: 432*31b31015Sliushiwei res = entry_invoke_command(session_id, up, cmd_id); 433*31b31015Sliushiwei break; 434*31b31015Sliushiwei #if defined(CFG_TA_STATS) 435*31b31015Sliushiwei case UTEE_ENTRY_FUNC_DUMP_MEMSTATS: 436*31b31015Sliushiwei res = entry_dump_memstats(session_id, up); 437*31b31015Sliushiwei break; 438*31b31015Sliushiwei #endif 439*31b31015Sliushiwei default: 440*31b31015Sliushiwei res = TEE_ERROR_NOT_SUPPORTED; 441*31b31015Sliushiwei break; 442*31b31015Sliushiwei } 443*31b31015Sliushiwei ta_header_save_params(0, NULL); 444*31b31015Sliushiwei 445*31b31015Sliushiwei return res; 446*31b31015Sliushiwei } 447