xref: /optee_os/lib/libutee/user_ta_entry.c (revision 3eb0c44511ce81e239f92442cfc548b262d9956b)
131b31015Sliushiwei // SPDX-License-Identifier: BSD-2-Clause
231b31015Sliushiwei /*
331b31015Sliushiwei  * Copyright (c) 2014, STMicroelectronics International N.V.
431b31015Sliushiwei  * Copyright (c) 2022, Linaro Limited.
531b31015Sliushiwei  */
631b31015Sliushiwei #include <compiler.h>
731b31015Sliushiwei #include <link.h>
831b31015Sliushiwei #include <malloc.h>
931b31015Sliushiwei #include <memtag.h>
1031b31015Sliushiwei #include <stdbool.h>
1131b31015Sliushiwei #include <stdlib.h>
1231b31015Sliushiwei #include <string.h>
1331b31015Sliushiwei #include <sys/queue.h>
1431b31015Sliushiwei #include <tee_api.h>
1531b31015Sliushiwei #include <tee_arith_internal.h>
1631b31015Sliushiwei #include <tee_internal_api_extensions.h>
1731b31015Sliushiwei #include <tee_ta_api.h>
1831b31015Sliushiwei #include <user_ta_header.h>
1931b31015Sliushiwei #include <utee_syscalls.h>
2031b31015Sliushiwei #include "tee_api_private.h"
2131b31015Sliushiwei 
2231b31015Sliushiwei struct ta_session {
2331b31015Sliushiwei 	uint32_t session_id;
2431b31015Sliushiwei 	void *session_ctx;
2531b31015Sliushiwei 	TAILQ_ENTRY(ta_session) link;
2631b31015Sliushiwei };
2731b31015Sliushiwei 
2831b31015Sliushiwei static TAILQ_HEAD(ta_sessions, ta_session) ta_sessions =
2931b31015Sliushiwei 		TAILQ_HEAD_INITIALIZER(ta_sessions);
3031b31015Sliushiwei 
3131b31015Sliushiwei /* From user_ta_header.c, built within TA */
3231b31015Sliushiwei extern uint8_t ta_heap[];
3331b31015Sliushiwei extern const size_t ta_heap_size;
3431b31015Sliushiwei extern struct ta_head ta_head;
3531b31015Sliushiwei 
3631b31015Sliushiwei uint32_t ta_param_types;
3731b31015Sliushiwei TEE_Param ta_params[TEE_NUM_PARAMS];
3831b31015Sliushiwei 
3931b31015Sliushiwei struct malloc_ctx *__ta_no_share_malloc_ctx;
4031b31015Sliushiwei 
4131b31015Sliushiwei struct __elf_phdr_info __elf_phdr_info;
4231b31015Sliushiwei 
4331b31015Sliushiwei struct phdr_info {
4431b31015Sliushiwei 	struct dl_phdr_info info;
4531b31015Sliushiwei 	TAILQ_ENTRY(phdr_info) link;
4631b31015Sliushiwei };
4731b31015Sliushiwei 
4831b31015Sliushiwei static TAILQ_HEAD(phdr_info_head, phdr_info) __phdr_info_head =
4931b31015Sliushiwei 		TAILQ_HEAD_INITIALIZER(__phdr_info_head);
5031b31015Sliushiwei /*
5131b31015Sliushiwei  * Keep track of how many modules have been initialized so that subsequent
5231b31015Sliushiwei  * dlopen() calls will not run the same initializers again
5331b31015Sliushiwei  */
5431b31015Sliushiwei static size_t _num_mod_init;
5531b31015Sliushiwei 
_init_iterate_phdr_cb(struct dl_phdr_info * info,size_t size __unused,void * data)5631b31015Sliushiwei static int _init_iterate_phdr_cb(struct dl_phdr_info *info,
5731b31015Sliushiwei 				 size_t size __unused, void *data)
5831b31015Sliushiwei {
5931b31015Sliushiwei 	struct phdr_info *qe = NULL;
6031b31015Sliushiwei 	size_t *count = data;
6131b31015Sliushiwei 
6231b31015Sliushiwei 	qe = malloc(sizeof(*qe));
6331b31015Sliushiwei 	if (!qe) {
6431b31015Sliushiwei 		EMSG("init/fini: out of memory");
6531b31015Sliushiwei 		abort();
6631b31015Sliushiwei 	}
6731b31015Sliushiwei 	qe->info = *info;
6831b31015Sliushiwei 	TAILQ_INSERT_TAIL(&__phdr_info_head, qe, link);
6931b31015Sliushiwei 	(*count)++;
7031b31015Sliushiwei 	return 0;
7131b31015Sliushiwei }
7231b31015Sliushiwei 
_get_fn_array(struct dl_phdr_info * info,Elf_Sword tag_a,Elf_Sword tag_s,void (*** fn)(void),size_t * num_fn)7331b31015Sliushiwei static void _get_fn_array(struct dl_phdr_info *info, Elf_Sword tag_a,
7431b31015Sliushiwei 			  Elf_Sword tag_s, void (***fn)(void), size_t *num_fn)
7531b31015Sliushiwei {
7631b31015Sliushiwei 	const Elf_Phdr *phdr = NULL;
7731b31015Sliushiwei 	Elf_Dyn *dyn = NULL;
7831b31015Sliushiwei 	size_t num_dyn = 0;
7931b31015Sliushiwei 	size_t i = 0;
8031b31015Sliushiwei 	size_t j = 0;
8131b31015Sliushiwei 
8231b31015Sliushiwei 	for (i = 0; i < info->dlpi_phnum; i++) {
8331b31015Sliushiwei 		phdr = info->dlpi_phdr + i;
8431b31015Sliushiwei 		if (phdr->p_type != PT_DYNAMIC)
8531b31015Sliushiwei 			continue;
8631b31015Sliushiwei 		num_dyn = phdr->p_memsz / sizeof(Elf_Dyn);
8731b31015Sliushiwei 		dyn = (Elf_Dyn *)(phdr->p_vaddr + info->dlpi_addr);
8831b31015Sliushiwei 		for (j = 0; j < num_dyn; j++) {
8931b31015Sliushiwei 			if (*fn && *num_fn)
9031b31015Sliushiwei 				break;
9131b31015Sliushiwei 			if (dyn->d_tag == DT_NULL) {
9231b31015Sliushiwei 				break;
9331b31015Sliushiwei 			} else if (dyn->d_tag == tag_a) {
9431b31015Sliushiwei 				*fn = (void (**)(void))(dyn->d_un.d_ptr +
9531b31015Sliushiwei 							info->dlpi_addr);
9631b31015Sliushiwei 			} else if (dyn->d_tag == tag_s) {
9731b31015Sliushiwei 				*num_fn = dyn->d_un.d_val / sizeof(Elf_Addr);
9831b31015Sliushiwei 			}
9931b31015Sliushiwei 			dyn++;
10031b31015Sliushiwei 		}
10131b31015Sliushiwei 	}
10231b31015Sliushiwei }
10331b31015Sliushiwei 
__utee_call_elf_init_fn(void)10431b31015Sliushiwei void __utee_call_elf_init_fn(void)
10531b31015Sliushiwei {
10631b31015Sliushiwei 	void (**fn)(void) = NULL;
10731b31015Sliushiwei 	size_t num_mod = 0;
10831b31015Sliushiwei 	size_t num_fn = 0;
10931b31015Sliushiwei 	size_t mod = 0;
11031b31015Sliushiwei 	size_t i = 0;
11131b31015Sliushiwei 	struct phdr_info *qe = NULL;
11231b31015Sliushiwei 	struct phdr_info *qe2 = NULL;
11331b31015Sliushiwei 
11431b31015Sliushiwei 	dl_iterate_phdr(_init_iterate_phdr_cb, &num_mod);
11531b31015Sliushiwei 
11631b31015Sliushiwei 	/* Reverse order: dependencies first */
11731b31015Sliushiwei 	TAILQ_FOREACH_REVERSE(qe, &__phdr_info_head, phdr_info_head, link) {
11831b31015Sliushiwei 		if (mod == num_mod - _num_mod_init)
11931b31015Sliushiwei 			break;
12031b31015Sliushiwei 		_get_fn_array(&qe->info, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, &fn,
12131b31015Sliushiwei 			      &num_fn);
12231b31015Sliushiwei 		for (i = 0; i < num_fn; i++)
12331b31015Sliushiwei 			fn[i]();
12431b31015Sliushiwei 		fn = NULL;
12531b31015Sliushiwei 		num_fn = 0;
12631b31015Sliushiwei 		mod++;
12731b31015Sliushiwei 	}
12831b31015Sliushiwei 	_num_mod_init += mod;
12931b31015Sliushiwei 
13031b31015Sliushiwei 	TAILQ_FOREACH_SAFE(qe, &__phdr_info_head, link, qe2) {
13131b31015Sliushiwei 		TAILQ_REMOVE(&__phdr_info_head, qe, link);
13231b31015Sliushiwei 		free(qe);
13331b31015Sliushiwei 	}
13431b31015Sliushiwei }
13531b31015Sliushiwei 
_fini_iterate_phdr_cb(struct dl_phdr_info * info,size_t size __unused,void * data __unused)13631b31015Sliushiwei static int _fini_iterate_phdr_cb(struct dl_phdr_info *info,
13731b31015Sliushiwei 				 size_t size __unused, void *data __unused)
13831b31015Sliushiwei {
13931b31015Sliushiwei 	void (**fn)(void) = NULL;
14031b31015Sliushiwei 	size_t num_fn = 0;
14131b31015Sliushiwei 	size_t i = 0;
14231b31015Sliushiwei 
14331b31015Sliushiwei 	_get_fn_array(info, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, &fn, &num_fn);
14431b31015Sliushiwei 
14531b31015Sliushiwei 	for (i = 1; i <= num_fn; i++)
14631b31015Sliushiwei 		fn[num_fn - i]();
14731b31015Sliushiwei 
14831b31015Sliushiwei 	return 0;
14931b31015Sliushiwei }
15031b31015Sliushiwei 
__utee_call_elf_fini_fn(void)15131b31015Sliushiwei void __utee_call_elf_fini_fn(void)
15231b31015Sliushiwei {
15331b31015Sliushiwei 	dl_iterate_phdr(_fini_iterate_phdr_cb, NULL);
15431b31015Sliushiwei }
15531b31015Sliushiwei 
get_memtag_implementation(void)15631b31015Sliushiwei static unsigned int get_memtag_implementation(void)
15731b31015Sliushiwei {
15831b31015Sliushiwei 	const char *s = "org.trustedfirmware.optee.cpu.feat_memtag_implemented";
15931b31015Sliushiwei 	uint32_t v = 0;
16031b31015Sliushiwei 
16131b31015Sliushiwei 	if (TEE_GetPropertyAsU32(TEE_PROPSET_TEE_IMPLEMENTATION, s, &v))
16231b31015Sliushiwei 		return 0;
16331b31015Sliushiwei 	return v;
16431b31015Sliushiwei }
16531b31015Sliushiwei 
init_instance(void)16631b31015Sliushiwei static TEE_Result init_instance(void)
16731b31015Sliushiwei {
168*3eb0c445SJohan Korsnes 	static bool internal_init_done;
169*3eb0c445SJohan Korsnes 	static bool init_done;
170*3eb0c445SJohan Korsnes 	TEE_Result res;
171*3eb0c445SJohan Korsnes 
172*3eb0c445SJohan Korsnes 	if (init_done)
173*3eb0c445SJohan Korsnes 		return TEE_SUCCESS;
174*3eb0c445SJohan Korsnes 
175*3eb0c445SJohan Korsnes 	if (internal_init_done)
176*3eb0c445SJohan Korsnes 		goto create_entrypoint;
177*3eb0c445SJohan Korsnes 
17831b31015Sliushiwei 	trace_set_level(tahead_get_trace_level());
17931b31015Sliushiwei 	__utee_gprof_init();
18031b31015Sliushiwei 	malloc_add_pool(ta_heap, ta_heap_size);
18131b31015Sliushiwei 	if (__ta_no_share_heap_size) {
18231b31015Sliushiwei 		__ta_no_share_malloc_ctx = malloc(raw_malloc_get_ctx_size());
18331b31015Sliushiwei 		if (__ta_no_share_malloc_ctx) {
18431b31015Sliushiwei 			raw_malloc_init_ctx(__ta_no_share_malloc_ctx);
18531b31015Sliushiwei 			raw_malloc_add_pool(__ta_no_share_malloc_ctx,
18631b31015Sliushiwei 					    __ta_no_share_heap,
18731b31015Sliushiwei 					    __ta_no_share_heap_size);
18831b31015Sliushiwei 		}
18931b31015Sliushiwei 	}
19031b31015Sliushiwei 	memtag_init_ops(get_memtag_implementation());
19131b31015Sliushiwei 	_TEE_MathAPI_Init();
19231b31015Sliushiwei 	__utee_tcb_init();
19331b31015Sliushiwei 	__utee_call_elf_init_fn();
194*3eb0c445SJohan Korsnes 	internal_init_done = true;
195*3eb0c445SJohan Korsnes 
196*3eb0c445SJohan Korsnes create_entrypoint:
197*3eb0c445SJohan Korsnes 	res = TA_CreateEntryPoint();
198*3eb0c445SJohan Korsnes 	if (!res)
199*3eb0c445SJohan Korsnes 		init_done = true;
200*3eb0c445SJohan Korsnes 
201*3eb0c445SJohan Korsnes 	return res;
20231b31015Sliushiwei }
20331b31015Sliushiwei 
uninit_instance(void)20431b31015Sliushiwei static void uninit_instance(void)
20531b31015Sliushiwei {
20631b31015Sliushiwei 	__utee_gprof_fini();
20731b31015Sliushiwei 	TA_DestroyEntryPoint();
20831b31015Sliushiwei 	__utee_call_elf_fini_fn();
20931b31015Sliushiwei }
21031b31015Sliushiwei 
ta_header_save_params(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])21131b31015Sliushiwei static void ta_header_save_params(uint32_t param_types,
21231b31015Sliushiwei 				  TEE_Param params[TEE_NUM_PARAMS])
21331b31015Sliushiwei {
21431b31015Sliushiwei 	ta_param_types = param_types;
21531b31015Sliushiwei 
21631b31015Sliushiwei 	if (params)
21731b31015Sliushiwei 		memcpy(ta_params, params, sizeof(ta_params));
21831b31015Sliushiwei 	else
21931b31015Sliushiwei 		memset(ta_params, 0, sizeof(ta_params));
22031b31015Sliushiwei }
22131b31015Sliushiwei 
ta_header_get_session(uint32_t session_id)22231b31015Sliushiwei static struct ta_session *ta_header_get_session(uint32_t session_id)
22331b31015Sliushiwei {
22431b31015Sliushiwei 	struct ta_session *itr;
22531b31015Sliushiwei 
22631b31015Sliushiwei 	TAILQ_FOREACH(itr, &ta_sessions, link) {
22731b31015Sliushiwei 		if (itr->session_id == session_id)
22831b31015Sliushiwei 			return itr;
22931b31015Sliushiwei 	}
23031b31015Sliushiwei 	return NULL;
23131b31015Sliushiwei }
23231b31015Sliushiwei 
ta_header_add_session(uint32_t session_id)23331b31015Sliushiwei static TEE_Result ta_header_add_session(uint32_t session_id)
23431b31015Sliushiwei {
23531b31015Sliushiwei 	struct ta_session *itr = ta_header_get_session(session_id);
23631b31015Sliushiwei 	TEE_Result res;
23731b31015Sliushiwei 
23831b31015Sliushiwei 	if (itr)
23931b31015Sliushiwei 		return TEE_SUCCESS;
24031b31015Sliushiwei 
24131b31015Sliushiwei 	res = init_instance();
24231b31015Sliushiwei 	if (res)
24331b31015Sliushiwei 		return res;
24431b31015Sliushiwei 
24531b31015Sliushiwei 	itr = TEE_Malloc(sizeof(struct ta_session),
24631b31015Sliushiwei 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
24731b31015Sliushiwei 	if (!itr)
24831b31015Sliushiwei 		return TEE_ERROR_OUT_OF_MEMORY;
24931b31015Sliushiwei 	itr->session_id = session_id;
25031b31015Sliushiwei 	itr->session_ctx = 0;
25131b31015Sliushiwei 	TAILQ_INSERT_TAIL(&ta_sessions, itr, link);
25231b31015Sliushiwei 
25331b31015Sliushiwei 	return TEE_SUCCESS;
25431b31015Sliushiwei }
25531b31015Sliushiwei 
ta_header_remove_session(uint32_t session_id)25631b31015Sliushiwei static void ta_header_remove_session(uint32_t session_id)
25731b31015Sliushiwei {
25831b31015Sliushiwei 	struct ta_session *itr;
25931b31015Sliushiwei 	bool keep_alive;
26031b31015Sliushiwei 
26131b31015Sliushiwei 	TAILQ_FOREACH(itr, &ta_sessions, link) {
26231b31015Sliushiwei 		if (itr->session_id == session_id) {
26331b31015Sliushiwei 			TAILQ_REMOVE(&ta_sessions, itr, link);
26431b31015Sliushiwei 			TEE_Free(itr);
26531b31015Sliushiwei 
26631b31015Sliushiwei 			keep_alive =
26731b31015Sliushiwei 				(ta_head.flags & TA_FLAG_SINGLE_INSTANCE) &&
26831b31015Sliushiwei 				(ta_head.flags & TA_FLAG_INSTANCE_KEEP_ALIVE);
26931b31015Sliushiwei 			if (TAILQ_EMPTY(&ta_sessions) && !keep_alive)
27031b31015Sliushiwei 				uninit_instance();
27131b31015Sliushiwei 
27231b31015Sliushiwei 			return;
27331b31015Sliushiwei 		}
27431b31015Sliushiwei 	}
27531b31015Sliushiwei }
27631b31015Sliushiwei 
to_utee_params(struct utee_params * up,uint32_t param_types,const TEE_Param params[TEE_NUM_PARAMS])27731b31015Sliushiwei static void to_utee_params(struct utee_params *up, uint32_t param_types,
27831b31015Sliushiwei 			   const TEE_Param params[TEE_NUM_PARAMS])
27931b31015Sliushiwei {
28031b31015Sliushiwei 	size_t n = 0;
28131b31015Sliushiwei 
28231b31015Sliushiwei 	up->types = param_types;
28331b31015Sliushiwei 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
28431b31015Sliushiwei 		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
28531b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_INPUT:
28631b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
28731b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_INOUT:
28831b31015Sliushiwei 			up->vals[n * 2] = params[n].value.a;
28931b31015Sliushiwei 			up->vals[n * 2 + 1] = params[n].value.b;
29031b31015Sliushiwei 			break;
29131b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_INPUT:
29231b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
29331b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_INOUT:
29431b31015Sliushiwei 			up->vals[n * 2] = (uintptr_t)params[n].memref.buffer;
29531b31015Sliushiwei 			up->vals[n * 2 + 1] = params[n].memref.size;
29631b31015Sliushiwei 			break;
29731b31015Sliushiwei 		default:
29831b31015Sliushiwei 			up->vals[n * 2] = 0;
29931b31015Sliushiwei 			up->vals[n * 2 + 1] = 0;
30031b31015Sliushiwei 			break;
30131b31015Sliushiwei 		}
30231b31015Sliushiwei 	}
30331b31015Sliushiwei }
30431b31015Sliushiwei 
from_utee_params(TEE_Param params[TEE_NUM_PARAMS],uint32_t * param_types,const struct utee_params * up)30531b31015Sliushiwei static void from_utee_params(TEE_Param params[TEE_NUM_PARAMS],
30631b31015Sliushiwei 			     uint32_t *param_types,
30731b31015Sliushiwei 			     const struct utee_params *up)
30831b31015Sliushiwei {
30931b31015Sliushiwei 	size_t n;
31031b31015Sliushiwei 	uint32_t types = up->types;
31131b31015Sliushiwei 
31231b31015Sliushiwei 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
31331b31015Sliushiwei 		uintptr_t a = up->vals[n * 2];
31431b31015Sliushiwei 		uintptr_t b = up->vals[n * 2 + 1];
31531b31015Sliushiwei 
31631b31015Sliushiwei 		switch (TEE_PARAM_TYPE_GET(types, n)) {
31731b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_INPUT:
31831b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
31931b31015Sliushiwei 		case TEE_PARAM_TYPE_VALUE_INOUT:
32031b31015Sliushiwei 			params[n].value.a = a;
32131b31015Sliushiwei 			params[n].value.b = b;
32231b31015Sliushiwei 			break;
32331b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_INPUT:
32431b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
32531b31015Sliushiwei 		case TEE_PARAM_TYPE_MEMREF_INOUT:
32631b31015Sliushiwei 			params[n].memref.buffer = (void *)a;
32731b31015Sliushiwei 			params[n].memref.size = b;
32831b31015Sliushiwei 			break;
32931b31015Sliushiwei 		default:
33031b31015Sliushiwei 			break;
33131b31015Sliushiwei 		}
33231b31015Sliushiwei 	}
33331b31015Sliushiwei 
33431b31015Sliushiwei 	if (param_types)
33531b31015Sliushiwei 		*param_types = types;
33631b31015Sliushiwei }
33731b31015Sliushiwei 
entry_open_session(unsigned long session_id,struct utee_params * up)33831b31015Sliushiwei static TEE_Result entry_open_session(unsigned long session_id,
33931b31015Sliushiwei 			struct utee_params *up)
34031b31015Sliushiwei {
34131b31015Sliushiwei 	TEE_Result res;
34231b31015Sliushiwei 	struct ta_session *session;
34331b31015Sliushiwei 	uint32_t param_types;
34431b31015Sliushiwei 	TEE_Param params[TEE_NUM_PARAMS];
34531b31015Sliushiwei 
34631b31015Sliushiwei 	res = ta_header_add_session(session_id);
34731b31015Sliushiwei 	if (res != TEE_SUCCESS)
34831b31015Sliushiwei 		return res;
34931b31015Sliushiwei 
35031b31015Sliushiwei 	session = ta_header_get_session(session_id);
35131b31015Sliushiwei 	if (!session)
35231b31015Sliushiwei 		return TEE_ERROR_BAD_STATE;
35331b31015Sliushiwei 
35431b31015Sliushiwei 	from_utee_params(params, &param_types, up);
35531b31015Sliushiwei 	ta_header_save_params(param_types, params);
35631b31015Sliushiwei 
35731b31015Sliushiwei 	res = TA_OpenSessionEntryPoint(param_types, params,
35831b31015Sliushiwei 				       &session->session_ctx);
35931b31015Sliushiwei 
36031b31015Sliushiwei 	to_utee_params(up, param_types, params);
36131b31015Sliushiwei 
36231b31015Sliushiwei 	if (res != TEE_SUCCESS)
36331b31015Sliushiwei 		ta_header_remove_session(session_id);
36431b31015Sliushiwei 	return res;
36531b31015Sliushiwei }
36631b31015Sliushiwei 
entry_close_session(unsigned long session_id)36731b31015Sliushiwei static TEE_Result entry_close_session(unsigned long session_id)
36831b31015Sliushiwei {
36931b31015Sliushiwei 	struct ta_session *session = ta_header_get_session(session_id);
37031b31015Sliushiwei 
37131b31015Sliushiwei 	if (!session)
37231b31015Sliushiwei 		return TEE_ERROR_BAD_STATE;
37331b31015Sliushiwei 
37431b31015Sliushiwei 	TA_CloseSessionEntryPoint(session->session_ctx);
37531b31015Sliushiwei 
37631b31015Sliushiwei 	ta_header_remove_session(session_id);
37731b31015Sliushiwei 	return TEE_SUCCESS;
37831b31015Sliushiwei }
37931b31015Sliushiwei 
entry_invoke_command(unsigned long session_id,struct utee_params * up,unsigned long cmd_id)38031b31015Sliushiwei static TEE_Result entry_invoke_command(unsigned long session_id,
38131b31015Sliushiwei 			struct utee_params *up, unsigned long cmd_id)
38231b31015Sliushiwei {
38331b31015Sliushiwei 	TEE_Result res;
38431b31015Sliushiwei 	uint32_t param_types;
38531b31015Sliushiwei 	TEE_Param params[TEE_NUM_PARAMS];
38631b31015Sliushiwei 	struct ta_session *session = ta_header_get_session(session_id);
38731b31015Sliushiwei 
38831b31015Sliushiwei 	if (!session)
38931b31015Sliushiwei 		return TEE_ERROR_BAD_STATE;
39031b31015Sliushiwei 
39131b31015Sliushiwei 	from_utee_params(params, &param_types, up);
39231b31015Sliushiwei 	ta_header_save_params(param_types, params);
39331b31015Sliushiwei 
39431b31015Sliushiwei 	res = TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id,
39531b31015Sliushiwei 					 param_types, params);
39631b31015Sliushiwei 
39731b31015Sliushiwei 	to_utee_params(up, param_types, params);
39831b31015Sliushiwei 	return res;
39931b31015Sliushiwei }
40031b31015Sliushiwei 
40131b31015Sliushiwei #if defined(CFG_TA_STATS)
entry_dump_memstats(unsigned long session_id __unused,struct utee_params * up)40231b31015Sliushiwei static TEE_Result entry_dump_memstats(unsigned long session_id __unused,
40331b31015Sliushiwei 				      struct utee_params *up)
40431b31015Sliushiwei {
40531b31015Sliushiwei 	uint32_t param_types = 0;
40631b31015Sliushiwei 	TEE_Param params[TEE_NUM_PARAMS] = { };
4072617f49fSEtienne Carriere 	struct pta_stats_alloc stats = { };
40831b31015Sliushiwei 
40931b31015Sliushiwei 	from_utee_params(params, &param_types, up);
41031b31015Sliushiwei 	ta_header_save_params(param_types, params);
41131b31015Sliushiwei 
41231b31015Sliushiwei 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
41331b31015Sliushiwei 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
41431b31015Sliushiwei 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
41531b31015Sliushiwei 			    TEE_PARAM_TYPE_NONE) != param_types)
41631b31015Sliushiwei 		return TEE_ERROR_BAD_PARAMETERS;
41731b31015Sliushiwei 
41831b31015Sliushiwei 	malloc_get_stats(&stats);
41931b31015Sliushiwei 	params[0].value.a = stats.allocated;
42031b31015Sliushiwei 	params[0].value.b = stats.max_allocated;
42131b31015Sliushiwei 	params[1].value.a = stats.size;
42231b31015Sliushiwei 	params[1].value.b = stats.num_alloc_fail;
42331b31015Sliushiwei 	params[2].value.a = stats.biggest_alloc_fail;
42431b31015Sliushiwei 	params[2].value.b = stats.biggest_alloc_fail_used;
42531b31015Sliushiwei 	to_utee_params(up, param_types, params);
42631b31015Sliushiwei 
42731b31015Sliushiwei 	return TEE_SUCCESS;
42831b31015Sliushiwei }
42931b31015Sliushiwei #endif
43031b31015Sliushiwei 
__utee_entry(unsigned long func,unsigned long session_id,struct utee_params * up,unsigned long cmd_id)43131b31015Sliushiwei TEE_Result __utee_entry(unsigned long func, unsigned long session_id,
43231b31015Sliushiwei 			struct utee_params *up, unsigned long cmd_id)
43331b31015Sliushiwei {
43431b31015Sliushiwei 	TEE_Result res;
43531b31015Sliushiwei 
43631b31015Sliushiwei 	switch (func) {
43731b31015Sliushiwei 	case UTEE_ENTRY_FUNC_OPEN_SESSION:
43831b31015Sliushiwei 		res = entry_open_session(session_id, up);
43931b31015Sliushiwei 		break;
44031b31015Sliushiwei 	case UTEE_ENTRY_FUNC_CLOSE_SESSION:
44131b31015Sliushiwei 		res = entry_close_session(session_id);
44231b31015Sliushiwei 		break;
44331b31015Sliushiwei 	case UTEE_ENTRY_FUNC_INVOKE_COMMAND:
44431b31015Sliushiwei 		res = entry_invoke_command(session_id, up, cmd_id);
44531b31015Sliushiwei 		break;
44631b31015Sliushiwei #if defined(CFG_TA_STATS)
44731b31015Sliushiwei 	case UTEE_ENTRY_FUNC_DUMP_MEMSTATS:
44831b31015Sliushiwei 		res = entry_dump_memstats(session_id, up);
44931b31015Sliushiwei 		break;
45031b31015Sliushiwei #endif
45131b31015Sliushiwei 	default:
45231b31015Sliushiwei 		res = TEE_ERROR_NOT_SUPPORTED;
45331b31015Sliushiwei 		break;
45431b31015Sliushiwei 	}
45531b31015Sliushiwei 	ta_header_save_params(0, NULL);
45631b31015Sliushiwei 
45731b31015Sliushiwei 	return res;
45831b31015Sliushiwei }
459