xref: /optee_os/lib/libutee/user_ta_entry.c (revision 31b31015b854f6688ce8ea71aed055a1e7f493e1)
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, &param_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, &param_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, &param_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