xref: /optee_os/core/tee/entry_std.c (revision d8158fea038d1facdf879563ab5e56a2fe92aa4f)
125c76675SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
225c76675SMarouene Boubakri /*
325c76675SMarouene Boubakri  * Copyright (c) 2015-2016, Linaro Limited
425c76675SMarouene Boubakri  * Copyright (c) 2014, STMicroelectronics International N.V.
525c76675SMarouene Boubakri  */
625c76675SMarouene Boubakri 
725c76675SMarouene Boubakri #include <assert.h>
825c76675SMarouene Boubakri #include <bench.h>
925c76675SMarouene Boubakri #include <compiler.h>
1025c76675SMarouene Boubakri #include <initcall.h>
1125c76675SMarouene Boubakri #include <io.h>
1225c76675SMarouene Boubakri #include <kernel/linker.h>
1325c76675SMarouene Boubakri #include <kernel/msg_param.h>
14c2d44948SJens Wiklander #include <kernel/notif.h>
1525c76675SMarouene Boubakri #include <kernel/panic.h>
1625c76675SMarouene Boubakri #include <kernel/tee_misc.h>
1725c76675SMarouene Boubakri #include <mm/core_memprot.h>
1825c76675SMarouene Boubakri #include <mm/core_mmu.h>
1925c76675SMarouene Boubakri #include <mm/mobj.h>
2025c76675SMarouene Boubakri #include <optee_msg.h>
2125c76675SMarouene Boubakri #include <sm/optee_smc.h>
2225c76675SMarouene Boubakri #include <string.h>
2325c76675SMarouene Boubakri #include <tee/entry_std.h>
2425c76675SMarouene Boubakri #include <tee/tee_cryp_utl.h>
2525c76675SMarouene Boubakri #include <tee/uuid.h>
2625c76675SMarouene Boubakri #include <util.h>
2725c76675SMarouene Boubakri 
2825c76675SMarouene Boubakri #define SHM_CACHE_ATTRS	\
29*d8158feaSJens Wiklander 	(uint32_t)(core_mmu_is_shm_cached() ? \
30*d8158feaSJens Wiklander 		   TEE_MATTR_CACHE_CACHED : TEE_MATTR_CACHE_NONCACHE)
3125c76675SMarouene Boubakri 
3225c76675SMarouene Boubakri /* Sessions opened from normal world */
3325c76675SMarouene Boubakri static struct tee_ta_session_head tee_open_sessions =
3425c76675SMarouene Boubakri TAILQ_HEAD_INITIALIZER(tee_open_sessions);
3525c76675SMarouene Boubakri 
3625c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
3725c76675SMarouene Boubakri static struct mobj *shm_mobj;
3825c76675SMarouene Boubakri #endif
3925c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
4025c76675SMarouene Boubakri static struct mobj **sdp_mem_mobjs;
4125c76675SMarouene Boubakri #endif
4225c76675SMarouene Boubakri 
4325c76675SMarouene Boubakri static unsigned int session_pnum;
4425c76675SMarouene Boubakri 
4525c76675SMarouene Boubakri static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem,
4625c76675SMarouene Boubakri 					       struct mobj *mobj,
4725c76675SMarouene Boubakri 					       const paddr_t pa,
4825c76675SMarouene Boubakri 					       const size_t sz)
4925c76675SMarouene Boubakri {
5025c76675SMarouene Boubakri 	paddr_t b;
5125c76675SMarouene Boubakri 
5225c76675SMarouene Boubakri 	if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS)
5325c76675SMarouene Boubakri 		panic("mobj_get_pa failed");
5425c76675SMarouene Boubakri 
5525c76675SMarouene Boubakri 	if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size))
5625c76675SMarouene Boubakri 		return false;
5725c76675SMarouene Boubakri 
5825c76675SMarouene Boubakri 	mem->mobj = mobj_get(mobj);
5925c76675SMarouene Boubakri 	mem->offs = pa - b;
6025c76675SMarouene Boubakri 	mem->size = sz;
6125c76675SMarouene Boubakri 	return true;
6225c76675SMarouene Boubakri }
6325c76675SMarouene Boubakri 
6425c76675SMarouene Boubakri #ifdef CFG_CORE_FFA
6525c76675SMarouene Boubakri static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem,
6625c76675SMarouene Boubakri 				 struct param_mem *mem)
6725c76675SMarouene Boubakri {
6825c76675SMarouene Boubakri 	size_t req_size = 0;
6925c76675SMarouene Boubakri 	uint64_t global_id = READ_ONCE(fmem->global_id);
7025c76675SMarouene Boubakri 	size_t sz = READ_ONCE(fmem->size);
7125c76675SMarouene Boubakri 
72c1bdf4fcSJens Wiklander 	if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) {
7325c76675SMarouene Boubakri 		mem->mobj = NULL;
7425c76675SMarouene Boubakri 		mem->offs = 0;
7525c76675SMarouene Boubakri 		mem->size = 0;
7625c76675SMarouene Boubakri 		return TEE_SUCCESS;
7725c76675SMarouene Boubakri 	}
7825c76675SMarouene Boubakri 	mem->mobj = mobj_ffa_get_by_cookie(global_id,
7925c76675SMarouene Boubakri 					   READ_ONCE(fmem->internal_offs));
8025c76675SMarouene Boubakri 	if (!mem->mobj)
8125c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
8225c76675SMarouene Boubakri 
8325c76675SMarouene Boubakri 	mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high),
8425c76675SMarouene Boubakri 				   READ_ONCE(fmem->offs_low));
8525c76675SMarouene Boubakri 	mem->size = sz;
8625c76675SMarouene Boubakri 
8725c76675SMarouene Boubakri 	/*
8825c76675SMarouene Boubakri 	 * Check that the supplied offset and size is covered by the
8925c76675SMarouene Boubakri 	 * previously verified MOBJ.
9025c76675SMarouene Boubakri 	 */
9125c76675SMarouene Boubakri 	if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
9225c76675SMarouene Boubakri 	    mem->mobj->size < req_size)
9325c76675SMarouene Boubakri 		return TEE_ERROR_SECURITY;
9425c76675SMarouene Boubakri 
9525c76675SMarouene Boubakri 	return TEE_SUCCESS;
9625c76675SMarouene Boubakri }
9725c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/
9825c76675SMarouene Boubakri /* fill 'struct param_mem' structure if buffer matches a valid memory object */
9925c76675SMarouene Boubakri static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem,
10025c76675SMarouene Boubakri 				 uint32_t attr, struct param_mem *mem)
10125c76675SMarouene Boubakri {
10225c76675SMarouene Boubakri 	struct mobj __maybe_unused **mobj;
10325c76675SMarouene Boubakri 	paddr_t pa = READ_ONCE(tmem->buf_ptr);
10425c76675SMarouene Boubakri 	size_t sz = READ_ONCE(tmem->size);
10525c76675SMarouene Boubakri 
10625c76675SMarouene Boubakri 	/*
10725c76675SMarouene Boubakri 	 * Handle NULL memory reference
10825c76675SMarouene Boubakri 	 */
10925c76675SMarouene Boubakri 	if (!pa) {
11025c76675SMarouene Boubakri 		mem->mobj = NULL;
11125c76675SMarouene Boubakri 		mem->offs = 0;
11225c76675SMarouene Boubakri 		mem->size = 0;
11325c76675SMarouene Boubakri 		return TEE_SUCCESS;
11425c76675SMarouene Boubakri 	}
11525c76675SMarouene Boubakri 
11625c76675SMarouene Boubakri 	/* Handle non-contiguous reference from a shared memory area */
11725c76675SMarouene Boubakri 	if (attr & OPTEE_MSG_ATTR_NONCONTIG) {
11825c76675SMarouene Boubakri 		uint64_t shm_ref = READ_ONCE(tmem->shm_ref);
11925c76675SMarouene Boubakri 
12025c76675SMarouene Boubakri 		mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref,
12125c76675SMarouene Boubakri 							  false);
12225c76675SMarouene Boubakri 		if (!mem->mobj)
12325c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
12425c76675SMarouene Boubakri 		mem->offs = 0;
12525c76675SMarouene Boubakri 		mem->size = sz;
12625c76675SMarouene Boubakri 		return TEE_SUCCESS;
12725c76675SMarouene Boubakri 	}
12825c76675SMarouene Boubakri 
12925c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
13025c76675SMarouene Boubakri 	/* Handle memory reference in the contiguous shared memory */
13125c76675SMarouene Boubakri 	if (param_mem_from_mobj(mem, shm_mobj, pa, sz))
13225c76675SMarouene Boubakri 		return TEE_SUCCESS;
13325c76675SMarouene Boubakri #endif
13425c76675SMarouene Boubakri 
13525c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
13625c76675SMarouene Boubakri 	/* Handle memory reference to Secure Data Path memory areas */
13725c76675SMarouene Boubakri 	for (mobj = sdp_mem_mobjs; *mobj; mobj++)
13825c76675SMarouene Boubakri 		if (param_mem_from_mobj(mem, *mobj, pa, sz))
13925c76675SMarouene Boubakri 			return TEE_SUCCESS;
14025c76675SMarouene Boubakri #endif
14125c76675SMarouene Boubakri 
14225c76675SMarouene Boubakri 	return TEE_ERROR_BAD_PARAMETERS;
14325c76675SMarouene Boubakri }
14425c76675SMarouene Boubakri 
14525c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
14625c76675SMarouene Boubakri static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem,
14725c76675SMarouene Boubakri 				 struct param_mem *mem)
14825c76675SMarouene Boubakri {
14925c76675SMarouene Boubakri 	size_t req_size = 0;
15025c76675SMarouene Boubakri 	uint64_t shm_ref = READ_ONCE(rmem->shm_ref);
15125c76675SMarouene Boubakri 	size_t sz = READ_ONCE(rmem->size);
15225c76675SMarouene Boubakri 
15325c76675SMarouene Boubakri 	mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref);
15425c76675SMarouene Boubakri 	if (!mem->mobj)
15525c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
15625c76675SMarouene Boubakri 
15725c76675SMarouene Boubakri 	mem->offs = READ_ONCE(rmem->offs);
15825c76675SMarouene Boubakri 	mem->size = sz;
15925c76675SMarouene Boubakri 
16025c76675SMarouene Boubakri 	/*
16125c76675SMarouene Boubakri 	 * Check that the supplied offset and size is covered by the
16225c76675SMarouene Boubakri 	 * previously verified MOBJ.
16325c76675SMarouene Boubakri 	 */
16425c76675SMarouene Boubakri 	if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
16525c76675SMarouene Boubakri 	    mem->mobj->size < req_size)
16625c76675SMarouene Boubakri 		return TEE_ERROR_SECURITY;
16725c76675SMarouene Boubakri 
16825c76675SMarouene Boubakri 	return TEE_SUCCESS;
16925c76675SMarouene Boubakri }
17025c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
17125c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/
17225c76675SMarouene Boubakri 
17325c76675SMarouene Boubakri static TEE_Result copy_in_params(const struct optee_msg_param *params,
17425c76675SMarouene Boubakri 				 uint32_t num_params,
17525c76675SMarouene Boubakri 				 struct tee_ta_param *ta_param,
17625c76675SMarouene Boubakri 				 uint64_t *saved_attr)
17725c76675SMarouene Boubakri {
17825c76675SMarouene Boubakri 	TEE_Result res;
17925c76675SMarouene Boubakri 	size_t n;
18025c76675SMarouene Boubakri 	uint8_t pt[TEE_NUM_PARAMS] = { 0 };
18125c76675SMarouene Boubakri 
18225c76675SMarouene Boubakri 	if (num_params > TEE_NUM_PARAMS)
18325c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
18425c76675SMarouene Boubakri 
18525c76675SMarouene Boubakri 	memset(ta_param, 0, sizeof(*ta_param));
18625c76675SMarouene Boubakri 
18725c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
18825c76675SMarouene Boubakri 		uint32_t attr;
18925c76675SMarouene Boubakri 
19025c76675SMarouene Boubakri 		saved_attr[n] = READ_ONCE(params[n].attr);
19125c76675SMarouene Boubakri 
19225c76675SMarouene Boubakri 		if (saved_attr[n] & OPTEE_MSG_ATTR_META)
19325c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
19425c76675SMarouene Boubakri 
19525c76675SMarouene Boubakri 		attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK;
19625c76675SMarouene Boubakri 		switch (attr) {
19725c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_NONE:
19825c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_NONE;
19925c76675SMarouene Boubakri 			break;
20025c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
20125c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
20225c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
20325c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr -
20425c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
20525c76675SMarouene Boubakri 			ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a);
20625c76675SMarouene Boubakri 			ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b);
20725c76675SMarouene Boubakri 			break;
20825c76675SMarouene Boubakri #ifdef CFG_CORE_FFA
20925c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
21025c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
21125c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
21225c76675SMarouene Boubakri 			res = set_fmem_param(&params[n].u.fmem,
21325c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
21425c76675SMarouene Boubakri 			if (res)
21525c76675SMarouene Boubakri 				return res;
21625c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
21725c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
21825c76675SMarouene Boubakri 			break;
21925c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/
22025c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
22125c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
22225c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
22325c76675SMarouene Boubakri 			res = set_tmem_param(&params[n].u.tmem, saved_attr[n],
22425c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
22525c76675SMarouene Boubakri 			if (res)
22625c76675SMarouene Boubakri 				return res;
22725c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
22825c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
22925c76675SMarouene Boubakri 			break;
23025c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
23125c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
23225c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
23325c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
23425c76675SMarouene Boubakri 			res = set_rmem_param(&params[n].u.rmem,
23525c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
23625c76675SMarouene Boubakri 			if (res)
23725c76675SMarouene Boubakri 				return res;
23825c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
23925c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
24025c76675SMarouene Boubakri 			break;
24125c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
24225c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/
24325c76675SMarouene Boubakri 		default:
24425c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
24525c76675SMarouene Boubakri 		}
24625c76675SMarouene Boubakri 	}
24725c76675SMarouene Boubakri 
24825c76675SMarouene Boubakri 	ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]);
24925c76675SMarouene Boubakri 
25025c76675SMarouene Boubakri 	return TEE_SUCCESS;
25125c76675SMarouene Boubakri }
25225c76675SMarouene Boubakri 
25325c76675SMarouene Boubakri static void cleanup_shm_refs(const uint64_t *saved_attr,
25425c76675SMarouene Boubakri 			     struct tee_ta_param *param, uint32_t num_params)
25525c76675SMarouene Boubakri {
25625c76675SMarouene Boubakri 	size_t n;
25725c76675SMarouene Boubakri 
25825c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
25925c76675SMarouene Boubakri 		switch (saved_attr[n]) {
26025c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
26125c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
26225c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
26325c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
26425c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
26525c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
26625c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
26725c76675SMarouene Boubakri #endif
26825c76675SMarouene Boubakri 			mobj_put(param->u[n].mem.mobj);
26925c76675SMarouene Boubakri 			break;
27025c76675SMarouene Boubakri 		default:
27125c76675SMarouene Boubakri 			break;
27225c76675SMarouene Boubakri 		}
27325c76675SMarouene Boubakri 	}
27425c76675SMarouene Boubakri }
27525c76675SMarouene Boubakri 
27625c76675SMarouene Boubakri static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
27725c76675SMarouene Boubakri 			   struct optee_msg_param *params, uint64_t *saved_attr)
27825c76675SMarouene Boubakri {
27925c76675SMarouene Boubakri 	size_t n;
28025c76675SMarouene Boubakri 
28125c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
28225c76675SMarouene Boubakri 		switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
28325c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
28425c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_MEMREF_INOUT:
28525c76675SMarouene Boubakri 			switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) {
28625c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
28725c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
28825c76675SMarouene Boubakri 				params[n].u.tmem.size = ta_param->u[n].mem.size;
28925c76675SMarouene Boubakri 				break;
29025c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
29125c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
29225c76675SMarouene Boubakri 				params[n].u.rmem.size = ta_param->u[n].mem.size;
29325c76675SMarouene Boubakri 				break;
29425c76675SMarouene Boubakri 			default:
29525c76675SMarouene Boubakri 				break;
29625c76675SMarouene Boubakri 			}
29725c76675SMarouene Boubakri 			break;
29825c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
29925c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_VALUE_INOUT:
30025c76675SMarouene Boubakri 			params[n].u.value.a = ta_param->u[n].val.a;
30125c76675SMarouene Boubakri 			params[n].u.value.b = ta_param->u[n].val.b;
30225c76675SMarouene Boubakri 			break;
30325c76675SMarouene Boubakri 		default:
30425c76675SMarouene Boubakri 			break;
30525c76675SMarouene Boubakri 		}
30625c76675SMarouene Boubakri 	}
30725c76675SMarouene Boubakri }
30825c76675SMarouene Boubakri 
30925c76675SMarouene Boubakri /*
31025c76675SMarouene Boubakri  * Extracts mandatory parameter for open session.
31125c76675SMarouene Boubakri  *
31225c76675SMarouene Boubakri  * Returns
31325c76675SMarouene Boubakri  * false : mandatory parameter wasn't found or malformatted
31425c76675SMarouene Boubakri  * true  : paramater found and OK
31525c76675SMarouene Boubakri  */
31625c76675SMarouene Boubakri static TEE_Result get_open_session_meta(size_t num_params,
31725c76675SMarouene Boubakri 					struct optee_msg_param *params,
31825c76675SMarouene Boubakri 					size_t *num_meta, TEE_UUID *uuid,
31925c76675SMarouene Boubakri 					TEE_Identity *clnt_id)
32025c76675SMarouene Boubakri {
32125c76675SMarouene Boubakri 	const uint32_t req_attr = OPTEE_MSG_ATTR_META |
32225c76675SMarouene Boubakri 				  OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
32325c76675SMarouene Boubakri 
32425c76675SMarouene Boubakri 	if (num_params < 2)
32525c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
32625c76675SMarouene Boubakri 
32725c76675SMarouene Boubakri 	if (params[0].attr != req_attr || params[1].attr != req_attr)
32825c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
32925c76675SMarouene Boubakri 
33025c76675SMarouene Boubakri 	tee_uuid_from_octets(uuid, (void *)&params[0].u.value);
33125c76675SMarouene Boubakri 	clnt_id->login = params[1].u.value.c;
33225c76675SMarouene Boubakri 	switch (clnt_id->login) {
33325c76675SMarouene Boubakri 	case TEE_LOGIN_PUBLIC:
33425c76675SMarouene Boubakri 	case TEE_LOGIN_REE_KERNEL:
33525c76675SMarouene Boubakri 		memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
33625c76675SMarouene Boubakri 		break;
33725c76675SMarouene Boubakri 	case TEE_LOGIN_USER:
33825c76675SMarouene Boubakri 	case TEE_LOGIN_GROUP:
33925c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION:
34025c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION_USER:
34125c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION_GROUP:
34225c76675SMarouene Boubakri 		tee_uuid_from_octets(&clnt_id->uuid,
34325c76675SMarouene Boubakri 				     (void *)&params[1].u.value);
34425c76675SMarouene Boubakri 		break;
34525c76675SMarouene Boubakri 	default:
34625c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
34725c76675SMarouene Boubakri 	}
34825c76675SMarouene Boubakri 
34925c76675SMarouene Boubakri 	*num_meta = 2;
35025c76675SMarouene Boubakri 	return TEE_SUCCESS;
35125c76675SMarouene Boubakri }
35225c76675SMarouene Boubakri 
35325c76675SMarouene Boubakri static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params)
35425c76675SMarouene Boubakri {
35525c76675SMarouene Boubakri 	TEE_Result res;
35625c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
35725c76675SMarouene Boubakri 	struct tee_ta_session *s = NULL;
35825c76675SMarouene Boubakri 	TEE_Identity clnt_id;
35925c76675SMarouene Boubakri 	TEE_UUID uuid;
36025c76675SMarouene Boubakri 	struct tee_ta_param param;
36125c76675SMarouene Boubakri 	size_t num_meta;
36225c76675SMarouene Boubakri 	uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
36325c76675SMarouene Boubakri 
36425c76675SMarouene Boubakri 	res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid,
36525c76675SMarouene Boubakri 				    &clnt_id);
36625c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
36725c76675SMarouene Boubakri 		goto out;
36825c76675SMarouene Boubakri 
36925c76675SMarouene Boubakri 	res = copy_in_params(arg->params + num_meta, num_params - num_meta,
37025c76675SMarouene Boubakri 			     &param, saved_attr);
37125c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
37225c76675SMarouene Boubakri 		goto cleanup_shm_refs;
37325c76675SMarouene Boubakri 
37425c76675SMarouene Boubakri 	res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid,
37525c76675SMarouene Boubakri 				  &clnt_id, TEE_TIMEOUT_INFINITE, &param);
37625c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
37725c76675SMarouene Boubakri 		s = NULL;
37825c76675SMarouene Boubakri 	copy_out_param(&param, num_params - num_meta, arg->params + num_meta,
37925c76675SMarouene Boubakri 		       saved_attr);
38025c76675SMarouene Boubakri 
38125c76675SMarouene Boubakri 	/*
38225c76675SMarouene Boubakri 	 * The occurrence of open/close session command is usually
38325c76675SMarouene Boubakri 	 * un-predictable, using this property to increase randomness
38425c76675SMarouene Boubakri 	 * of prng
38525c76675SMarouene Boubakri 	 */
38625c76675SMarouene Boubakri 	plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
38725c76675SMarouene Boubakri 				     &session_pnum);
38825c76675SMarouene Boubakri 
38925c76675SMarouene Boubakri cleanup_shm_refs:
39025c76675SMarouene Boubakri 	cleanup_shm_refs(saved_attr, &param, num_params - num_meta);
39125c76675SMarouene Boubakri 
39225c76675SMarouene Boubakri out:
39325c76675SMarouene Boubakri 	if (s)
39425c76675SMarouene Boubakri 		arg->session = s->id;
39525c76675SMarouene Boubakri 	else
39625c76675SMarouene Boubakri 		arg->session = 0;
39725c76675SMarouene Boubakri 	arg->ret = res;
39825c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
39925c76675SMarouene Boubakri }
40025c76675SMarouene Boubakri 
40125c76675SMarouene Boubakri static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params)
40225c76675SMarouene Boubakri {
40325c76675SMarouene Boubakri 	TEE_Result res;
40425c76675SMarouene Boubakri 	struct tee_ta_session *s;
40525c76675SMarouene Boubakri 
40625c76675SMarouene Boubakri 	if (num_params) {
40725c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
40825c76675SMarouene Boubakri 		goto out;
40925c76675SMarouene Boubakri 	}
41025c76675SMarouene Boubakri 
41125c76675SMarouene Boubakri 	plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
41225c76675SMarouene Boubakri 				     &session_pnum);
41325c76675SMarouene Boubakri 
41425c76675SMarouene Boubakri 	s = tee_ta_find_session(arg->session, &tee_open_sessions);
41525c76675SMarouene Boubakri 	res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY);
41625c76675SMarouene Boubakri out:
41725c76675SMarouene Boubakri 	arg->ret = res;
41825c76675SMarouene Boubakri 	arg->ret_origin = TEE_ORIGIN_TEE;
41925c76675SMarouene Boubakri }
42025c76675SMarouene Boubakri 
42125c76675SMarouene Boubakri static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params)
42225c76675SMarouene Boubakri {
42325c76675SMarouene Boubakri 	TEE_Result res;
42425c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
42525c76675SMarouene Boubakri 	struct tee_ta_session *s;
42625c76675SMarouene Boubakri 	struct tee_ta_param param = { 0 };
42725c76675SMarouene Boubakri 	uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
42825c76675SMarouene Boubakri 
42925c76675SMarouene Boubakri 	bm_timestamp();
43025c76675SMarouene Boubakri 
43125c76675SMarouene Boubakri 	res = copy_in_params(arg->params, num_params, &param, saved_attr);
43225c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
43325c76675SMarouene Boubakri 		goto out;
43425c76675SMarouene Boubakri 
43525c76675SMarouene Boubakri 	s = tee_ta_get_session(arg->session, true, &tee_open_sessions);
43625c76675SMarouene Boubakri 	if (!s) {
43725c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
43825c76675SMarouene Boubakri 		goto out;
43925c76675SMarouene Boubakri 	}
44025c76675SMarouene Boubakri 
44125c76675SMarouene Boubakri 	res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
44225c76675SMarouene Boubakri 				    TEE_TIMEOUT_INFINITE, arg->func, &param);
44325c76675SMarouene Boubakri 
44425c76675SMarouene Boubakri 	bm_timestamp();
44525c76675SMarouene Boubakri 
44625c76675SMarouene Boubakri 	tee_ta_put_session(s);
44725c76675SMarouene Boubakri 
44825c76675SMarouene Boubakri 	copy_out_param(&param, num_params, arg->params, saved_attr);
44925c76675SMarouene Boubakri 
45025c76675SMarouene Boubakri out:
45125c76675SMarouene Boubakri 	cleanup_shm_refs(saved_attr, &param, num_params);
45225c76675SMarouene Boubakri 
45325c76675SMarouene Boubakri 	arg->ret = res;
45425c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
45525c76675SMarouene Boubakri }
45625c76675SMarouene Boubakri 
45725c76675SMarouene Boubakri static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params)
45825c76675SMarouene Boubakri {
45925c76675SMarouene Boubakri 	TEE_Result res;
46025c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
46125c76675SMarouene Boubakri 	struct tee_ta_session *s;
46225c76675SMarouene Boubakri 
46325c76675SMarouene Boubakri 	if (num_params) {
46425c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
46525c76675SMarouene Boubakri 		goto out;
46625c76675SMarouene Boubakri 	}
46725c76675SMarouene Boubakri 
46825c76675SMarouene Boubakri 	s = tee_ta_get_session(arg->session, false, &tee_open_sessions);
46925c76675SMarouene Boubakri 	if (!s) {
47025c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
47125c76675SMarouene Boubakri 		goto out;
47225c76675SMarouene Boubakri 	}
47325c76675SMarouene Boubakri 
47425c76675SMarouene Boubakri 	res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY);
47525c76675SMarouene Boubakri 	tee_ta_put_session(s);
47625c76675SMarouene Boubakri 
47725c76675SMarouene Boubakri out:
47825c76675SMarouene Boubakri 	arg->ret = res;
47925c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
48025c76675SMarouene Boubakri }
48125c76675SMarouene Boubakri 
48225c76675SMarouene Boubakri #ifndef CFG_CORE_FFA
48325c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
48425c76675SMarouene Boubakri static void register_shm(struct optee_msg_arg *arg, uint32_t num_params)
48525c76675SMarouene Boubakri {
486b259cc96SJens Wiklander 	struct optee_msg_param_tmem *tmem = NULL;
487b259cc96SJens Wiklander 	struct mobj *mobj = NULL;
488b259cc96SJens Wiklander 
48925c76675SMarouene Boubakri 	arg->ret = TEE_ERROR_BAD_PARAMETERS;
49025c76675SMarouene Boubakri 
49125c76675SMarouene Boubakri 	if (num_params != 1 ||
49225c76675SMarouene Boubakri 	    (arg->params[0].attr !=
49325c76675SMarouene Boubakri 	     (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)))
49425c76675SMarouene Boubakri 		return;
49525c76675SMarouene Boubakri 
496b259cc96SJens Wiklander 	tmem = &arg->params[0].u.tmem;
497b259cc96SJens Wiklander 	mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size,
49825c76675SMarouene Boubakri 					     tmem->shm_ref, false);
49925c76675SMarouene Boubakri 
50025c76675SMarouene Boubakri 	if (!mobj)
50125c76675SMarouene Boubakri 		return;
50225c76675SMarouene Boubakri 
50325c76675SMarouene Boubakri 	mobj_reg_shm_unguard(mobj);
50425c76675SMarouene Boubakri 	arg->ret = TEE_SUCCESS;
50525c76675SMarouene Boubakri }
50625c76675SMarouene Boubakri 
50725c76675SMarouene Boubakri static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params)
50825c76675SMarouene Boubakri {
50925c76675SMarouene Boubakri 	if (num_params == 1) {
51025c76675SMarouene Boubakri 		uint64_t cookie = arg->params[0].u.rmem.shm_ref;
51125c76675SMarouene Boubakri 		TEE_Result res = mobj_reg_shm_release_by_cookie(cookie);
51225c76675SMarouene Boubakri 
51325c76675SMarouene Boubakri 		if (res)
51425c76675SMarouene Boubakri 			EMSG("Can't find mapping with given cookie");
51525c76675SMarouene Boubakri 		arg->ret = res;
51625c76675SMarouene Boubakri 	} else {
51725c76675SMarouene Boubakri 		arg->ret = TEE_ERROR_BAD_PARAMETERS;
51825c76675SMarouene Boubakri 		arg->ret_origin = TEE_ORIGIN_TEE;
51925c76675SMarouene Boubakri 	}
52025c76675SMarouene Boubakri }
52125c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
52225c76675SMarouene Boubakri #endif
52325c76675SMarouene Boubakri 
52425c76675SMarouene Boubakri void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions)
52525c76675SMarouene Boubakri {
52625c76675SMarouene Boubakri 	*open_sessions = &tee_open_sessions;
52725c76675SMarouene Boubakri }
52825c76675SMarouene Boubakri 
52925c76675SMarouene Boubakri /* Note: this function is weak to let platforms add special handling */
53025c76675SMarouene Boubakri uint32_t __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
53125c76675SMarouene Boubakri {
53225c76675SMarouene Boubakri 	return __tee_entry_std(arg, num_params);
53325c76675SMarouene Boubakri }
53425c76675SMarouene Boubakri 
53525c76675SMarouene Boubakri /*
53625c76675SMarouene Boubakri  * If tee_entry_std() is overridden, it's still supposed to call this
53725c76675SMarouene Boubakri  * function.
53825c76675SMarouene Boubakri  */
53925c76675SMarouene Boubakri uint32_t __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
54025c76675SMarouene Boubakri {
54125c76675SMarouene Boubakri 	uint32_t rv = OPTEE_SMC_RETURN_OK;
54225c76675SMarouene Boubakri 
54325c76675SMarouene Boubakri 	/* Enable foreign interrupts for STD calls */
54425c76675SMarouene Boubakri 	thread_set_foreign_intr(true);
54525c76675SMarouene Boubakri 	switch (arg->cmd) {
54625c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_OPEN_SESSION:
54725c76675SMarouene Boubakri 		entry_open_session(arg, num_params);
54825c76675SMarouene Boubakri 		break;
54925c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_CLOSE_SESSION:
55025c76675SMarouene Boubakri 		entry_close_session(arg, num_params);
55125c76675SMarouene Boubakri 		break;
55225c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_INVOKE_COMMAND:
55325c76675SMarouene Boubakri 		entry_invoke_command(arg, num_params);
55425c76675SMarouene Boubakri 		break;
55525c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_CANCEL:
55625c76675SMarouene Boubakri 		entry_cancel(arg, num_params);
55725c76675SMarouene Boubakri 		break;
55825c76675SMarouene Boubakri #ifndef CFG_CORE_FFA
55925c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
56025c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_REGISTER_SHM:
56125c76675SMarouene Boubakri 		register_shm(arg, num_params);
56225c76675SMarouene Boubakri 		break;
56325c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_UNREGISTER_SHM:
56425c76675SMarouene Boubakri 		unregister_shm(arg, num_params);
56525c76675SMarouene Boubakri 		break;
56625c76675SMarouene Boubakri #endif
56725c76675SMarouene Boubakri #endif
568c2d44948SJens Wiklander 
569c2d44948SJens Wiklander 	case OPTEE_MSG_CMD_DO_BOTTOM_HALF:
570c2d44948SJens Wiklander 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
571c2d44948SJens Wiklander 			notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF);
572c2d44948SJens Wiklander 		else
573c2d44948SJens Wiklander 			goto err;
574c2d44948SJens Wiklander 		break;
575c2d44948SJens Wiklander 	case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF:
576c2d44948SJens Wiklander 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
577c2d44948SJens Wiklander 			notif_deliver_event(NOTIF_EVENT_STOPPED);
578c2d44948SJens Wiklander 		else
579c2d44948SJens Wiklander 			goto err;
580c2d44948SJens Wiklander 		break;
581c2d44948SJens Wiklander 
58225c76675SMarouene Boubakri 	default:
583c2d44948SJens Wiklander err:
58425c76675SMarouene Boubakri 		EMSG("Unknown cmd 0x%x", arg->cmd);
58525c76675SMarouene Boubakri 		rv = OPTEE_SMC_RETURN_EBADCMD;
58625c76675SMarouene Boubakri 	}
58725c76675SMarouene Boubakri 
58825c76675SMarouene Boubakri 	return rv;
58925c76675SMarouene Boubakri }
59025c76675SMarouene Boubakri 
59125c76675SMarouene Boubakri static TEE_Result default_mobj_init(void)
59225c76675SMarouene Boubakri {
59325c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
59425c76675SMarouene Boubakri 	shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr,
59525c76675SMarouene Boubakri 				   default_nsec_shm_size, SHM_CACHE_ATTRS,
59625c76675SMarouene Boubakri 				   CORE_MEM_NSEC_SHM);
59725c76675SMarouene Boubakri 	if (!shm_mobj)
59825c76675SMarouene Boubakri 		panic("Failed to register shared memory");
59925c76675SMarouene Boubakri #endif
60025c76675SMarouene Boubakri 
60125c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
60225c76675SMarouene Boubakri 	sdp_mem_mobjs = core_sdp_mem_create_mobjs();
60325c76675SMarouene Boubakri 	if (!sdp_mem_mobjs)
60425c76675SMarouene Boubakri 		panic("Failed to register SDP memory");
60525c76675SMarouene Boubakri #endif
60625c76675SMarouene Boubakri 
60725c76675SMarouene Boubakri 	return TEE_SUCCESS;
60825c76675SMarouene Boubakri }
60925c76675SMarouene Boubakri 
61025c76675SMarouene Boubakri driver_init_late(default_mobj_init);
611