xref: /optee_os/core/tee/entry_std.c (revision 25c7667501aa8ec9d44f97b4eba667d55a0fa5e7)
1*25c76675SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
2*25c76675SMarouene Boubakri /*
3*25c76675SMarouene Boubakri  * Copyright (c) 2015-2016, Linaro Limited
4*25c76675SMarouene Boubakri  * Copyright (c) 2014, STMicroelectronics International N.V.
5*25c76675SMarouene Boubakri  */
6*25c76675SMarouene Boubakri 
7*25c76675SMarouene Boubakri #include <assert.h>
8*25c76675SMarouene Boubakri #include <bench.h>
9*25c76675SMarouene Boubakri #include <compiler.h>
10*25c76675SMarouene Boubakri #include <initcall.h>
11*25c76675SMarouene Boubakri #include <io.h>
12*25c76675SMarouene Boubakri #include <kernel/linker.h>
13*25c76675SMarouene Boubakri #include <kernel/msg_param.h>
14*25c76675SMarouene Boubakri #include <kernel/panic.h>
15*25c76675SMarouene Boubakri #include <kernel/tee_misc.h>
16*25c76675SMarouene Boubakri #include <mm/core_memprot.h>
17*25c76675SMarouene Boubakri #include <mm/core_mmu.h>
18*25c76675SMarouene Boubakri #include <mm/mobj.h>
19*25c76675SMarouene Boubakri #include <optee_msg.h>
20*25c76675SMarouene Boubakri #include <sm/optee_smc.h>
21*25c76675SMarouene Boubakri #include <string.h>
22*25c76675SMarouene Boubakri #include <tee/entry_std.h>
23*25c76675SMarouene Boubakri #include <tee/tee_cryp_utl.h>
24*25c76675SMarouene Boubakri #include <tee/uuid.h>
25*25c76675SMarouene Boubakri #include <util.h>
26*25c76675SMarouene Boubakri 
27*25c76675SMarouene Boubakri #define SHM_CACHE_ATTRS	\
28*25c76675SMarouene Boubakri 	(uint32_t)(core_mmu_is_shm_cached() ?  OPTEE_SMC_SHM_CACHED : 0)
29*25c76675SMarouene Boubakri 
30*25c76675SMarouene Boubakri /* Sessions opened from normal world */
31*25c76675SMarouene Boubakri static struct tee_ta_session_head tee_open_sessions =
32*25c76675SMarouene Boubakri TAILQ_HEAD_INITIALIZER(tee_open_sessions);
33*25c76675SMarouene Boubakri 
34*25c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
35*25c76675SMarouene Boubakri static struct mobj *shm_mobj;
36*25c76675SMarouene Boubakri #endif
37*25c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
38*25c76675SMarouene Boubakri static struct mobj **sdp_mem_mobjs;
39*25c76675SMarouene Boubakri #endif
40*25c76675SMarouene Boubakri 
41*25c76675SMarouene Boubakri static unsigned int session_pnum;
42*25c76675SMarouene Boubakri 
43*25c76675SMarouene Boubakri static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem,
44*25c76675SMarouene Boubakri 					       struct mobj *mobj,
45*25c76675SMarouene Boubakri 					       const paddr_t pa,
46*25c76675SMarouene Boubakri 					       const size_t sz)
47*25c76675SMarouene Boubakri {
48*25c76675SMarouene Boubakri 	paddr_t b;
49*25c76675SMarouene Boubakri 
50*25c76675SMarouene Boubakri 	if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS)
51*25c76675SMarouene Boubakri 		panic("mobj_get_pa failed");
52*25c76675SMarouene Boubakri 
53*25c76675SMarouene Boubakri 	if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size))
54*25c76675SMarouene Boubakri 		return false;
55*25c76675SMarouene Boubakri 
56*25c76675SMarouene Boubakri 	mem->mobj = mobj_get(mobj);
57*25c76675SMarouene Boubakri 	mem->offs = pa - b;
58*25c76675SMarouene Boubakri 	mem->size = sz;
59*25c76675SMarouene Boubakri 	return true;
60*25c76675SMarouene Boubakri }
61*25c76675SMarouene Boubakri 
62*25c76675SMarouene Boubakri #ifdef CFG_CORE_FFA
63*25c76675SMarouene Boubakri static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem,
64*25c76675SMarouene Boubakri 				 struct param_mem *mem)
65*25c76675SMarouene Boubakri {
66*25c76675SMarouene Boubakri 	size_t req_size = 0;
67*25c76675SMarouene Boubakri 	uint64_t global_id = READ_ONCE(fmem->global_id);
68*25c76675SMarouene Boubakri 	size_t sz = READ_ONCE(fmem->size);
69*25c76675SMarouene Boubakri 
70*25c76675SMarouene Boubakri 	if (!global_id && !sz) {
71*25c76675SMarouene Boubakri 		mem->mobj = NULL;
72*25c76675SMarouene Boubakri 		mem->offs = 0;
73*25c76675SMarouene Boubakri 		mem->size = 0;
74*25c76675SMarouene Boubakri 		return TEE_SUCCESS;
75*25c76675SMarouene Boubakri 	}
76*25c76675SMarouene Boubakri 	mem->mobj = mobj_ffa_get_by_cookie(global_id,
77*25c76675SMarouene Boubakri 					   READ_ONCE(fmem->internal_offs));
78*25c76675SMarouene Boubakri 	if (!mem->mobj)
79*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
80*25c76675SMarouene Boubakri 
81*25c76675SMarouene Boubakri 	mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high),
82*25c76675SMarouene Boubakri 				   READ_ONCE(fmem->offs_low));
83*25c76675SMarouene Boubakri 	mem->size = sz;
84*25c76675SMarouene Boubakri 
85*25c76675SMarouene Boubakri 	/*
86*25c76675SMarouene Boubakri 	 * Check that the supplied offset and size is covered by the
87*25c76675SMarouene Boubakri 	 * previously verified MOBJ.
88*25c76675SMarouene Boubakri 	 */
89*25c76675SMarouene Boubakri 	if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
90*25c76675SMarouene Boubakri 	    mem->mobj->size < req_size)
91*25c76675SMarouene Boubakri 		return TEE_ERROR_SECURITY;
92*25c76675SMarouene Boubakri 
93*25c76675SMarouene Boubakri 	return TEE_SUCCESS;
94*25c76675SMarouene Boubakri }
95*25c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/
96*25c76675SMarouene Boubakri /* fill 'struct param_mem' structure if buffer matches a valid memory object */
97*25c76675SMarouene Boubakri static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem,
98*25c76675SMarouene Boubakri 				 uint32_t attr, struct param_mem *mem)
99*25c76675SMarouene Boubakri {
100*25c76675SMarouene Boubakri 	struct mobj __maybe_unused **mobj;
101*25c76675SMarouene Boubakri 	paddr_t pa = READ_ONCE(tmem->buf_ptr);
102*25c76675SMarouene Boubakri 	size_t sz = READ_ONCE(tmem->size);
103*25c76675SMarouene Boubakri 
104*25c76675SMarouene Boubakri 	/*
105*25c76675SMarouene Boubakri 	 * Handle NULL memory reference
106*25c76675SMarouene Boubakri 	 */
107*25c76675SMarouene Boubakri 	if (!pa) {
108*25c76675SMarouene Boubakri 		mem->mobj = NULL;
109*25c76675SMarouene Boubakri 		mem->offs = 0;
110*25c76675SMarouene Boubakri 		mem->size = 0;
111*25c76675SMarouene Boubakri 		return TEE_SUCCESS;
112*25c76675SMarouene Boubakri 	}
113*25c76675SMarouene Boubakri 
114*25c76675SMarouene Boubakri 	/* Handle non-contiguous reference from a shared memory area */
115*25c76675SMarouene Boubakri 	if (attr & OPTEE_MSG_ATTR_NONCONTIG) {
116*25c76675SMarouene Boubakri 		uint64_t shm_ref = READ_ONCE(tmem->shm_ref);
117*25c76675SMarouene Boubakri 
118*25c76675SMarouene Boubakri 		mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref,
119*25c76675SMarouene Boubakri 							  false);
120*25c76675SMarouene Boubakri 		if (!mem->mobj)
121*25c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
122*25c76675SMarouene Boubakri 		mem->offs = 0;
123*25c76675SMarouene Boubakri 		mem->size = sz;
124*25c76675SMarouene Boubakri 		return TEE_SUCCESS;
125*25c76675SMarouene Boubakri 	}
126*25c76675SMarouene Boubakri 
127*25c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
128*25c76675SMarouene Boubakri 	/* Handle memory reference in the contiguous shared memory */
129*25c76675SMarouene Boubakri 	if (param_mem_from_mobj(mem, shm_mobj, pa, sz))
130*25c76675SMarouene Boubakri 		return TEE_SUCCESS;
131*25c76675SMarouene Boubakri #endif
132*25c76675SMarouene Boubakri 
133*25c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
134*25c76675SMarouene Boubakri 	/* Handle memory reference to Secure Data Path memory areas */
135*25c76675SMarouene Boubakri 	for (mobj = sdp_mem_mobjs; *mobj; mobj++)
136*25c76675SMarouene Boubakri 		if (param_mem_from_mobj(mem, *mobj, pa, sz))
137*25c76675SMarouene Boubakri 			return TEE_SUCCESS;
138*25c76675SMarouene Boubakri #endif
139*25c76675SMarouene Boubakri 
140*25c76675SMarouene Boubakri 	return TEE_ERROR_BAD_PARAMETERS;
141*25c76675SMarouene Boubakri }
142*25c76675SMarouene Boubakri 
143*25c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
144*25c76675SMarouene Boubakri static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem,
145*25c76675SMarouene Boubakri 				 struct param_mem *mem)
146*25c76675SMarouene Boubakri {
147*25c76675SMarouene Boubakri 	size_t req_size = 0;
148*25c76675SMarouene Boubakri 	uint64_t shm_ref = READ_ONCE(rmem->shm_ref);
149*25c76675SMarouene Boubakri 	size_t sz = READ_ONCE(rmem->size);
150*25c76675SMarouene Boubakri 
151*25c76675SMarouene Boubakri 	mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref);
152*25c76675SMarouene Boubakri 	if (!mem->mobj)
153*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
154*25c76675SMarouene Boubakri 
155*25c76675SMarouene Boubakri 	mem->offs = READ_ONCE(rmem->offs);
156*25c76675SMarouene Boubakri 	mem->size = sz;
157*25c76675SMarouene Boubakri 
158*25c76675SMarouene Boubakri 	/*
159*25c76675SMarouene Boubakri 	 * Check that the supplied offset and size is covered by the
160*25c76675SMarouene Boubakri 	 * previously verified MOBJ.
161*25c76675SMarouene Boubakri 	 */
162*25c76675SMarouene Boubakri 	if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
163*25c76675SMarouene Boubakri 	    mem->mobj->size < req_size)
164*25c76675SMarouene Boubakri 		return TEE_ERROR_SECURITY;
165*25c76675SMarouene Boubakri 
166*25c76675SMarouene Boubakri 	return TEE_SUCCESS;
167*25c76675SMarouene Boubakri }
168*25c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
169*25c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/
170*25c76675SMarouene Boubakri 
171*25c76675SMarouene Boubakri static TEE_Result copy_in_params(const struct optee_msg_param *params,
172*25c76675SMarouene Boubakri 				 uint32_t num_params,
173*25c76675SMarouene Boubakri 				 struct tee_ta_param *ta_param,
174*25c76675SMarouene Boubakri 				 uint64_t *saved_attr)
175*25c76675SMarouene Boubakri {
176*25c76675SMarouene Boubakri 	TEE_Result res;
177*25c76675SMarouene Boubakri 	size_t n;
178*25c76675SMarouene Boubakri 	uint8_t pt[TEE_NUM_PARAMS] = { 0 };
179*25c76675SMarouene Boubakri 
180*25c76675SMarouene Boubakri 	if (num_params > TEE_NUM_PARAMS)
181*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
182*25c76675SMarouene Boubakri 
183*25c76675SMarouene Boubakri 	memset(ta_param, 0, sizeof(*ta_param));
184*25c76675SMarouene Boubakri 
185*25c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
186*25c76675SMarouene Boubakri 		uint32_t attr;
187*25c76675SMarouene Boubakri 
188*25c76675SMarouene Boubakri 		saved_attr[n] = READ_ONCE(params[n].attr);
189*25c76675SMarouene Boubakri 
190*25c76675SMarouene Boubakri 		if (saved_attr[n] & OPTEE_MSG_ATTR_META)
191*25c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
192*25c76675SMarouene Boubakri 
193*25c76675SMarouene Boubakri 		attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK;
194*25c76675SMarouene Boubakri 		switch (attr) {
195*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_NONE:
196*25c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_NONE;
197*25c76675SMarouene Boubakri 			break;
198*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
199*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
200*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
201*25c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr -
202*25c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
203*25c76675SMarouene Boubakri 			ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a);
204*25c76675SMarouene Boubakri 			ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b);
205*25c76675SMarouene Boubakri 			break;
206*25c76675SMarouene Boubakri #ifdef CFG_CORE_FFA
207*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
208*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
209*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
210*25c76675SMarouene Boubakri 			res = set_fmem_param(&params[n].u.fmem,
211*25c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
212*25c76675SMarouene Boubakri 			if (res)
213*25c76675SMarouene Boubakri 				return res;
214*25c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
215*25c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
216*25c76675SMarouene Boubakri 			break;
217*25c76675SMarouene Boubakri #else /*!CFG_CORE_FFA*/
218*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
219*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
220*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
221*25c76675SMarouene Boubakri 			res = set_tmem_param(&params[n].u.tmem, saved_attr[n],
222*25c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
223*25c76675SMarouene Boubakri 			if (res)
224*25c76675SMarouene Boubakri 				return res;
225*25c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
226*25c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
227*25c76675SMarouene Boubakri 			break;
228*25c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
229*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
230*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
231*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
232*25c76675SMarouene Boubakri 			res = set_rmem_param(&params[n].u.rmem,
233*25c76675SMarouene Boubakri 					     &ta_param->u[n].mem);
234*25c76675SMarouene Boubakri 			if (res)
235*25c76675SMarouene Boubakri 				return res;
236*25c76675SMarouene Boubakri 			pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
237*25c76675SMarouene Boubakri 				OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
238*25c76675SMarouene Boubakri 			break;
239*25c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
240*25c76675SMarouene Boubakri #endif /*!CFG_CORE_FFA*/
241*25c76675SMarouene Boubakri 		default:
242*25c76675SMarouene Boubakri 			return TEE_ERROR_BAD_PARAMETERS;
243*25c76675SMarouene Boubakri 		}
244*25c76675SMarouene Boubakri 	}
245*25c76675SMarouene Boubakri 
246*25c76675SMarouene Boubakri 	ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]);
247*25c76675SMarouene Boubakri 
248*25c76675SMarouene Boubakri 	return TEE_SUCCESS;
249*25c76675SMarouene Boubakri }
250*25c76675SMarouene Boubakri 
251*25c76675SMarouene Boubakri static void cleanup_shm_refs(const uint64_t *saved_attr,
252*25c76675SMarouene Boubakri 			     struct tee_ta_param *param, uint32_t num_params)
253*25c76675SMarouene Boubakri {
254*25c76675SMarouene Boubakri 	size_t n;
255*25c76675SMarouene Boubakri 
256*25c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
257*25c76675SMarouene Boubakri 		switch (saved_attr[n]) {
258*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
259*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
260*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
261*25c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
262*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
263*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
264*25c76675SMarouene Boubakri 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
265*25c76675SMarouene Boubakri #endif
266*25c76675SMarouene Boubakri 			mobj_put(param->u[n].mem.mobj);
267*25c76675SMarouene Boubakri 			break;
268*25c76675SMarouene Boubakri 		default:
269*25c76675SMarouene Boubakri 			break;
270*25c76675SMarouene Boubakri 		}
271*25c76675SMarouene Boubakri 	}
272*25c76675SMarouene Boubakri }
273*25c76675SMarouene Boubakri 
274*25c76675SMarouene Boubakri static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
275*25c76675SMarouene Boubakri 			   struct optee_msg_param *params, uint64_t *saved_attr)
276*25c76675SMarouene Boubakri {
277*25c76675SMarouene Boubakri 	size_t n;
278*25c76675SMarouene Boubakri 
279*25c76675SMarouene Boubakri 	for (n = 0; n < num_params; n++) {
280*25c76675SMarouene Boubakri 		switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
281*25c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
282*25c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_MEMREF_INOUT:
283*25c76675SMarouene Boubakri 			switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) {
284*25c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
285*25c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
286*25c76675SMarouene Boubakri 				params[n].u.tmem.size = ta_param->u[n].mem.size;
287*25c76675SMarouene Boubakri 				break;
288*25c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
289*25c76675SMarouene Boubakri 			case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
290*25c76675SMarouene Boubakri 				params[n].u.rmem.size = ta_param->u[n].mem.size;
291*25c76675SMarouene Boubakri 				break;
292*25c76675SMarouene Boubakri 			default:
293*25c76675SMarouene Boubakri 				break;
294*25c76675SMarouene Boubakri 			}
295*25c76675SMarouene Boubakri 			break;
296*25c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
297*25c76675SMarouene Boubakri 		case TEE_PARAM_TYPE_VALUE_INOUT:
298*25c76675SMarouene Boubakri 			params[n].u.value.a = ta_param->u[n].val.a;
299*25c76675SMarouene Boubakri 			params[n].u.value.b = ta_param->u[n].val.b;
300*25c76675SMarouene Boubakri 			break;
301*25c76675SMarouene Boubakri 		default:
302*25c76675SMarouene Boubakri 			break;
303*25c76675SMarouene Boubakri 		}
304*25c76675SMarouene Boubakri 	}
305*25c76675SMarouene Boubakri }
306*25c76675SMarouene Boubakri 
307*25c76675SMarouene Boubakri /*
308*25c76675SMarouene Boubakri  * Extracts mandatory parameter for open session.
309*25c76675SMarouene Boubakri  *
310*25c76675SMarouene Boubakri  * Returns
311*25c76675SMarouene Boubakri  * false : mandatory parameter wasn't found or malformatted
312*25c76675SMarouene Boubakri  * true  : paramater found and OK
313*25c76675SMarouene Boubakri  */
314*25c76675SMarouene Boubakri static TEE_Result get_open_session_meta(size_t num_params,
315*25c76675SMarouene Boubakri 					struct optee_msg_param *params,
316*25c76675SMarouene Boubakri 					size_t *num_meta, TEE_UUID *uuid,
317*25c76675SMarouene Boubakri 					TEE_Identity *clnt_id)
318*25c76675SMarouene Boubakri {
319*25c76675SMarouene Boubakri 	const uint32_t req_attr = OPTEE_MSG_ATTR_META |
320*25c76675SMarouene Boubakri 				  OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
321*25c76675SMarouene Boubakri 
322*25c76675SMarouene Boubakri 	if (num_params < 2)
323*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
324*25c76675SMarouene Boubakri 
325*25c76675SMarouene Boubakri 	if (params[0].attr != req_attr || params[1].attr != req_attr)
326*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
327*25c76675SMarouene Boubakri 
328*25c76675SMarouene Boubakri 	tee_uuid_from_octets(uuid, (void *)&params[0].u.value);
329*25c76675SMarouene Boubakri 	clnt_id->login = params[1].u.value.c;
330*25c76675SMarouene Boubakri 	switch (clnt_id->login) {
331*25c76675SMarouene Boubakri 	case TEE_LOGIN_PUBLIC:
332*25c76675SMarouene Boubakri 	case TEE_LOGIN_REE_KERNEL:
333*25c76675SMarouene Boubakri 		memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
334*25c76675SMarouene Boubakri 		break;
335*25c76675SMarouene Boubakri 	case TEE_LOGIN_USER:
336*25c76675SMarouene Boubakri 	case TEE_LOGIN_GROUP:
337*25c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION:
338*25c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION_USER:
339*25c76675SMarouene Boubakri 	case TEE_LOGIN_APPLICATION_GROUP:
340*25c76675SMarouene Boubakri 		tee_uuid_from_octets(&clnt_id->uuid,
341*25c76675SMarouene Boubakri 				     (void *)&params[1].u.value);
342*25c76675SMarouene Boubakri 		break;
343*25c76675SMarouene Boubakri 	default:
344*25c76675SMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
345*25c76675SMarouene Boubakri 	}
346*25c76675SMarouene Boubakri 
347*25c76675SMarouene Boubakri 	*num_meta = 2;
348*25c76675SMarouene Boubakri 	return TEE_SUCCESS;
349*25c76675SMarouene Boubakri }
350*25c76675SMarouene Boubakri 
351*25c76675SMarouene Boubakri static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params)
352*25c76675SMarouene Boubakri {
353*25c76675SMarouene Boubakri 	TEE_Result res;
354*25c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
355*25c76675SMarouene Boubakri 	struct tee_ta_session *s = NULL;
356*25c76675SMarouene Boubakri 	TEE_Identity clnt_id;
357*25c76675SMarouene Boubakri 	TEE_UUID uuid;
358*25c76675SMarouene Boubakri 	struct tee_ta_param param;
359*25c76675SMarouene Boubakri 	size_t num_meta;
360*25c76675SMarouene Boubakri 	uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
361*25c76675SMarouene Boubakri 
362*25c76675SMarouene Boubakri 	res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid,
363*25c76675SMarouene Boubakri 				    &clnt_id);
364*25c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
365*25c76675SMarouene Boubakri 		goto out;
366*25c76675SMarouene Boubakri 
367*25c76675SMarouene Boubakri 	res = copy_in_params(arg->params + num_meta, num_params - num_meta,
368*25c76675SMarouene Boubakri 			     &param, saved_attr);
369*25c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
370*25c76675SMarouene Boubakri 		goto cleanup_shm_refs;
371*25c76675SMarouene Boubakri 
372*25c76675SMarouene Boubakri 	res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid,
373*25c76675SMarouene Boubakri 				  &clnt_id, TEE_TIMEOUT_INFINITE, &param);
374*25c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
375*25c76675SMarouene Boubakri 		s = NULL;
376*25c76675SMarouene Boubakri 	copy_out_param(&param, num_params - num_meta, arg->params + num_meta,
377*25c76675SMarouene Boubakri 		       saved_attr);
378*25c76675SMarouene Boubakri 
379*25c76675SMarouene Boubakri 	/*
380*25c76675SMarouene Boubakri 	 * The occurrence of open/close session command is usually
381*25c76675SMarouene Boubakri 	 * un-predictable, using this property to increase randomness
382*25c76675SMarouene Boubakri 	 * of prng
383*25c76675SMarouene Boubakri 	 */
384*25c76675SMarouene Boubakri 	plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
385*25c76675SMarouene Boubakri 				     &session_pnum);
386*25c76675SMarouene Boubakri 
387*25c76675SMarouene Boubakri cleanup_shm_refs:
388*25c76675SMarouene Boubakri 	cleanup_shm_refs(saved_attr, &param, num_params - num_meta);
389*25c76675SMarouene Boubakri 
390*25c76675SMarouene Boubakri out:
391*25c76675SMarouene Boubakri 	if (s)
392*25c76675SMarouene Boubakri 		arg->session = s->id;
393*25c76675SMarouene Boubakri 	else
394*25c76675SMarouene Boubakri 		arg->session = 0;
395*25c76675SMarouene Boubakri 	arg->ret = res;
396*25c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
397*25c76675SMarouene Boubakri }
398*25c76675SMarouene Boubakri 
399*25c76675SMarouene Boubakri static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params)
400*25c76675SMarouene Boubakri {
401*25c76675SMarouene Boubakri 	TEE_Result res;
402*25c76675SMarouene Boubakri 	struct tee_ta_session *s;
403*25c76675SMarouene Boubakri 
404*25c76675SMarouene Boubakri 	if (num_params) {
405*25c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
406*25c76675SMarouene Boubakri 		goto out;
407*25c76675SMarouene Boubakri 	}
408*25c76675SMarouene Boubakri 
409*25c76675SMarouene Boubakri 	plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
410*25c76675SMarouene Boubakri 				     &session_pnum);
411*25c76675SMarouene Boubakri 
412*25c76675SMarouene Boubakri 	s = tee_ta_find_session(arg->session, &tee_open_sessions);
413*25c76675SMarouene Boubakri 	res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY);
414*25c76675SMarouene Boubakri out:
415*25c76675SMarouene Boubakri 	arg->ret = res;
416*25c76675SMarouene Boubakri 	arg->ret_origin = TEE_ORIGIN_TEE;
417*25c76675SMarouene Boubakri }
418*25c76675SMarouene Boubakri 
419*25c76675SMarouene Boubakri static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params)
420*25c76675SMarouene Boubakri {
421*25c76675SMarouene Boubakri 	TEE_Result res;
422*25c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
423*25c76675SMarouene Boubakri 	struct tee_ta_session *s;
424*25c76675SMarouene Boubakri 	struct tee_ta_param param = { 0 };
425*25c76675SMarouene Boubakri 	uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
426*25c76675SMarouene Boubakri 
427*25c76675SMarouene Boubakri 	bm_timestamp();
428*25c76675SMarouene Boubakri 
429*25c76675SMarouene Boubakri 	res = copy_in_params(arg->params, num_params, &param, saved_attr);
430*25c76675SMarouene Boubakri 	if (res != TEE_SUCCESS)
431*25c76675SMarouene Boubakri 		goto out;
432*25c76675SMarouene Boubakri 
433*25c76675SMarouene Boubakri 	s = tee_ta_get_session(arg->session, true, &tee_open_sessions);
434*25c76675SMarouene Boubakri 	if (!s) {
435*25c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
436*25c76675SMarouene Boubakri 		goto out;
437*25c76675SMarouene Boubakri 	}
438*25c76675SMarouene Boubakri 
439*25c76675SMarouene Boubakri 	res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
440*25c76675SMarouene Boubakri 				    TEE_TIMEOUT_INFINITE, arg->func, &param);
441*25c76675SMarouene Boubakri 
442*25c76675SMarouene Boubakri 	bm_timestamp();
443*25c76675SMarouene Boubakri 
444*25c76675SMarouene Boubakri 	tee_ta_put_session(s);
445*25c76675SMarouene Boubakri 
446*25c76675SMarouene Boubakri 	copy_out_param(&param, num_params, arg->params, saved_attr);
447*25c76675SMarouene Boubakri 
448*25c76675SMarouene Boubakri out:
449*25c76675SMarouene Boubakri 	cleanup_shm_refs(saved_attr, &param, num_params);
450*25c76675SMarouene Boubakri 
451*25c76675SMarouene Boubakri 	arg->ret = res;
452*25c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
453*25c76675SMarouene Boubakri }
454*25c76675SMarouene Boubakri 
455*25c76675SMarouene Boubakri static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params)
456*25c76675SMarouene Boubakri {
457*25c76675SMarouene Boubakri 	TEE_Result res;
458*25c76675SMarouene Boubakri 	TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
459*25c76675SMarouene Boubakri 	struct tee_ta_session *s;
460*25c76675SMarouene Boubakri 
461*25c76675SMarouene Boubakri 	if (num_params) {
462*25c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
463*25c76675SMarouene Boubakri 		goto out;
464*25c76675SMarouene Boubakri 	}
465*25c76675SMarouene Boubakri 
466*25c76675SMarouene Boubakri 	s = tee_ta_get_session(arg->session, false, &tee_open_sessions);
467*25c76675SMarouene Boubakri 	if (!s) {
468*25c76675SMarouene Boubakri 		res = TEE_ERROR_BAD_PARAMETERS;
469*25c76675SMarouene Boubakri 		goto out;
470*25c76675SMarouene Boubakri 	}
471*25c76675SMarouene Boubakri 
472*25c76675SMarouene Boubakri 	res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY);
473*25c76675SMarouene Boubakri 	tee_ta_put_session(s);
474*25c76675SMarouene Boubakri 
475*25c76675SMarouene Boubakri out:
476*25c76675SMarouene Boubakri 	arg->ret = res;
477*25c76675SMarouene Boubakri 	arg->ret_origin = err_orig;
478*25c76675SMarouene Boubakri }
479*25c76675SMarouene Boubakri 
480*25c76675SMarouene Boubakri #ifndef CFG_CORE_FFA
481*25c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
482*25c76675SMarouene Boubakri static void register_shm(struct optee_msg_arg *arg, uint32_t num_params)
483*25c76675SMarouene Boubakri {
484*25c76675SMarouene Boubakri 	arg->ret = TEE_ERROR_BAD_PARAMETERS;
485*25c76675SMarouene Boubakri 
486*25c76675SMarouene Boubakri 	if (num_params != 1 ||
487*25c76675SMarouene Boubakri 	    (arg->params[0].attr !=
488*25c76675SMarouene Boubakri 	     (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)))
489*25c76675SMarouene Boubakri 		return;
490*25c76675SMarouene Boubakri 
491*25c76675SMarouene Boubakri 	struct optee_msg_param_tmem *tmem = &arg->params[0].u.tmem;
492*25c76675SMarouene Boubakri 	struct mobj *mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr,
493*25c76675SMarouene Boubakri 							  tmem->size,
494*25c76675SMarouene Boubakri 							  tmem->shm_ref, false);
495*25c76675SMarouene Boubakri 
496*25c76675SMarouene Boubakri 	if (!mobj)
497*25c76675SMarouene Boubakri 		return;
498*25c76675SMarouene Boubakri 
499*25c76675SMarouene Boubakri 	mobj_reg_shm_unguard(mobj);
500*25c76675SMarouene Boubakri 	arg->ret = TEE_SUCCESS;
501*25c76675SMarouene Boubakri }
502*25c76675SMarouene Boubakri 
503*25c76675SMarouene Boubakri static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params)
504*25c76675SMarouene Boubakri {
505*25c76675SMarouene Boubakri 	if (num_params == 1) {
506*25c76675SMarouene Boubakri 		uint64_t cookie = arg->params[0].u.rmem.shm_ref;
507*25c76675SMarouene Boubakri 		TEE_Result res = mobj_reg_shm_release_by_cookie(cookie);
508*25c76675SMarouene Boubakri 
509*25c76675SMarouene Boubakri 		if (res)
510*25c76675SMarouene Boubakri 			EMSG("Can't find mapping with given cookie");
511*25c76675SMarouene Boubakri 		arg->ret = res;
512*25c76675SMarouene Boubakri 	} else {
513*25c76675SMarouene Boubakri 		arg->ret = TEE_ERROR_BAD_PARAMETERS;
514*25c76675SMarouene Boubakri 		arg->ret_origin = TEE_ORIGIN_TEE;
515*25c76675SMarouene Boubakri 	}
516*25c76675SMarouene Boubakri }
517*25c76675SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
518*25c76675SMarouene Boubakri #endif
519*25c76675SMarouene Boubakri 
520*25c76675SMarouene Boubakri void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions)
521*25c76675SMarouene Boubakri {
522*25c76675SMarouene Boubakri 	*open_sessions = &tee_open_sessions;
523*25c76675SMarouene Boubakri }
524*25c76675SMarouene Boubakri 
525*25c76675SMarouene Boubakri /* Note: this function is weak to let platforms add special handling */
526*25c76675SMarouene Boubakri uint32_t __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
527*25c76675SMarouene Boubakri {
528*25c76675SMarouene Boubakri 	return __tee_entry_std(arg, num_params);
529*25c76675SMarouene Boubakri }
530*25c76675SMarouene Boubakri 
531*25c76675SMarouene Boubakri /*
532*25c76675SMarouene Boubakri  * If tee_entry_std() is overridden, it's still supposed to call this
533*25c76675SMarouene Boubakri  * function.
534*25c76675SMarouene Boubakri  */
535*25c76675SMarouene Boubakri uint32_t __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
536*25c76675SMarouene Boubakri {
537*25c76675SMarouene Boubakri 	uint32_t rv = OPTEE_SMC_RETURN_OK;
538*25c76675SMarouene Boubakri 
539*25c76675SMarouene Boubakri 	/* Enable foreign interrupts for STD calls */
540*25c76675SMarouene Boubakri 	thread_set_foreign_intr(true);
541*25c76675SMarouene Boubakri 	switch (arg->cmd) {
542*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_OPEN_SESSION:
543*25c76675SMarouene Boubakri 		entry_open_session(arg, num_params);
544*25c76675SMarouene Boubakri 		break;
545*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_CLOSE_SESSION:
546*25c76675SMarouene Boubakri 		entry_close_session(arg, num_params);
547*25c76675SMarouene Boubakri 		break;
548*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_INVOKE_COMMAND:
549*25c76675SMarouene Boubakri 		entry_invoke_command(arg, num_params);
550*25c76675SMarouene Boubakri 		break;
551*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_CANCEL:
552*25c76675SMarouene Boubakri 		entry_cancel(arg, num_params);
553*25c76675SMarouene Boubakri 		break;
554*25c76675SMarouene Boubakri #ifndef CFG_CORE_FFA
555*25c76675SMarouene Boubakri #ifdef CFG_CORE_DYN_SHM
556*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_REGISTER_SHM:
557*25c76675SMarouene Boubakri 		register_shm(arg, num_params);
558*25c76675SMarouene Boubakri 		break;
559*25c76675SMarouene Boubakri 	case OPTEE_MSG_CMD_UNREGISTER_SHM:
560*25c76675SMarouene Boubakri 		unregister_shm(arg, num_params);
561*25c76675SMarouene Boubakri 		break;
562*25c76675SMarouene Boubakri #endif
563*25c76675SMarouene Boubakri #endif
564*25c76675SMarouene Boubakri 	default:
565*25c76675SMarouene Boubakri 		EMSG("Unknown cmd 0x%x", arg->cmd);
566*25c76675SMarouene Boubakri 		rv = OPTEE_SMC_RETURN_EBADCMD;
567*25c76675SMarouene Boubakri 	}
568*25c76675SMarouene Boubakri 
569*25c76675SMarouene Boubakri 	return rv;
570*25c76675SMarouene Boubakri }
571*25c76675SMarouene Boubakri 
572*25c76675SMarouene Boubakri static TEE_Result default_mobj_init(void)
573*25c76675SMarouene Boubakri {
574*25c76675SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
575*25c76675SMarouene Boubakri 	shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr,
576*25c76675SMarouene Boubakri 				   default_nsec_shm_size, SHM_CACHE_ATTRS,
577*25c76675SMarouene Boubakri 				   CORE_MEM_NSEC_SHM);
578*25c76675SMarouene Boubakri 	if (!shm_mobj)
579*25c76675SMarouene Boubakri 		panic("Failed to register shared memory");
580*25c76675SMarouene Boubakri #endif
581*25c76675SMarouene Boubakri 
582*25c76675SMarouene Boubakri #ifdef CFG_SECURE_DATA_PATH
583*25c76675SMarouene Boubakri 	sdp_mem_mobjs = core_sdp_mem_create_mobjs();
584*25c76675SMarouene Boubakri 	if (!sdp_mem_mobjs)
585*25c76675SMarouene Boubakri 		panic("Failed to register SDP memory");
586*25c76675SMarouene Boubakri #endif
587*25c76675SMarouene Boubakri 
588*25c76675SMarouene Boubakri 	return TEE_SUCCESS;
589*25c76675SMarouene Boubakri }
590*25c76675SMarouene Boubakri 
591*25c76675SMarouene Boubakri driver_init_late(default_mobj_init);
592