1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2015-2016, Linaro Limited
4 * Copyright (c) 2014, STMicroelectronics International N.V.
5 */
6
7 #include <assert.h>
8 #include <compiler.h>
9 #include <initcall.h>
10 #include <io.h>
11 #include <kernel/linker.h>
12 #include <kernel/msg_param.h>
13 #include <kernel/notif.h>
14 #include <kernel/panic.h>
15 #include <kernel/tee_misc.h>
16 #include <mm/core_memprot.h>
17 #include <mm/core_mmu.h>
18 #include <mm/mobj.h>
19 #include <optee_msg.h>
20 #include <string.h>
21 #include <tee/entry_std.h>
22 #include <tee/tee_cryp_utl.h>
23 #include <tee/uuid.h>
24 #include <util.h>
25
26 #ifdef CFG_CORE_FFA
27 #include <kernel/thread_spmc.h>
28 #endif
29
30 #define SHM_CACHE_ATTRS \
31 (uint32_t)(core_mmu_is_shm_cached() ? \
32 TEE_MATTR_MEM_TYPE_CACHED : TEE_MATTR_MEM_TYPE_DEV)
33
34 /* Sessions opened from normal world */
35 static struct tee_ta_session_head tee_open_sessions =
36 TAILQ_HEAD_INITIALIZER(tee_open_sessions);
37
38 #ifdef CFG_CORE_RESERVED_SHM
39 static struct mobj *shm_mobj;
40 #endif
41 #ifdef CFG_SECURE_DATA_PATH
42 static struct mobj **sdp_mem_mobjs;
43 #endif
44
45 static unsigned int session_pnum;
46
param_mem_from_mobj(struct param_mem * mem,struct mobj * mobj,const paddr_t pa,const size_t sz)47 static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem,
48 struct mobj *mobj,
49 const paddr_t pa,
50 const size_t sz)
51 {
52 paddr_t b;
53
54 if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS)
55 panic("mobj_get_pa failed");
56
57 if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size))
58 return false;
59
60 mem->mobj = mobj_get(mobj);
61 mem->offs = pa - b;
62 mem->size = sz;
63 return true;
64 }
65
66 #ifdef CFG_CORE_FFA
set_fmem_param(const struct optee_msg_param_fmem * fmem,struct param_mem * mem)67 static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem,
68 struct param_mem *mem)
69 {
70 size_t req_size = 0;
71 uint64_t global_id = READ_ONCE(fmem->global_id);
72 size_t sz = READ_ONCE(fmem->size);
73
74 if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) {
75 mem->mobj = NULL;
76 mem->offs = 0;
77 mem->size = 0;
78 return TEE_SUCCESS;
79 }
80 mem->mobj = mobj_ffa_get_by_cookie(global_id,
81 READ_ONCE(fmem->internal_offs));
82 if (!mem->mobj)
83 return TEE_ERROR_BAD_PARAMETERS;
84
85 mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high),
86 READ_ONCE(fmem->offs_low));
87 mem->size = sz;
88
89 /*
90 * Check that the supplied offset and size is covered by the
91 * previously verified MOBJ.
92 */
93 if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
94 mem->mobj->size < req_size)
95 return TEE_ERROR_SECURITY;
96
97 return TEE_SUCCESS;
98 }
99 #else /*!CFG_CORE_FFA*/
100 /* fill 'struct param_mem' structure if buffer matches a valid memory object */
set_tmem_param(const struct optee_msg_param_tmem * tmem,uint32_t attr,struct param_mem * mem)101 static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem,
102 uint32_t attr, struct param_mem *mem)
103 {
104 struct mobj __maybe_unused **mobj = NULL;
105 paddr_t pa = READ_ONCE(tmem->buf_ptr);
106 size_t sz = READ_ONCE(tmem->size);
107 struct mobj *rmobj = NULL;
108
109 /*
110 * Handle NULL memory reference
111 */
112 if (!pa) {
113 mem->mobj = NULL;
114 mem->offs = 0;
115 mem->size = 0;
116 return TEE_SUCCESS;
117 }
118
119 /* Handle non-contiguous reference from a shared memory area */
120 if (attr & OPTEE_MSG_ATTR_NONCONTIG) {
121 uint64_t shm_ref = READ_ONCE(tmem->shm_ref);
122
123 mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref,
124 false);
125 if (!mem->mobj)
126 return TEE_ERROR_BAD_PARAMETERS;
127 mem->offs = 0;
128 mem->size = sz;
129 return TEE_SUCCESS;
130 }
131
132 #ifdef CFG_CORE_RESERVED_SHM
133 /* Handle memory reference in the contiguous shared memory */
134 if (param_mem_from_mobj(mem, shm_mobj, pa, sz))
135 return TEE_SUCCESS;
136 #endif
137
138 #ifdef CFG_SECURE_DATA_PATH
139 /* Handle memory reference to Secure Data Path memory areas */
140 for (mobj = sdp_mem_mobjs; *mobj; mobj++)
141 if (param_mem_from_mobj(mem, *mobj, pa, sz))
142 return TEE_SUCCESS;
143 #endif
144 rmobj = mobj_protmem_get_by_pa(pa, sz);
145 if (rmobj) {
146 bool rc = param_mem_from_mobj(mem, rmobj, pa, sz);
147
148 mobj_put(rmobj);
149 if (rc)
150 return TEE_SUCCESS;
151 }
152
153 return TEE_ERROR_BAD_PARAMETERS;
154 }
155
156 #ifdef CFG_CORE_DYN_SHM
set_rmem_param(const struct optee_msg_param_rmem * rmem,struct param_mem * mem)157 static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem,
158 struct param_mem *mem)
159 {
160 size_t req_size = 0;
161 uint64_t shm_ref = READ_ONCE(rmem->shm_ref);
162 size_t sz = READ_ONCE(rmem->size);
163
164 mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref);
165 if (!mem->mobj)
166 return TEE_ERROR_BAD_PARAMETERS;
167
168 mem->offs = READ_ONCE(rmem->offs);
169 mem->size = sz;
170
171 /*
172 * Check that the supplied offset and size is covered by the
173 * previously verified MOBJ.
174 */
175 if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) ||
176 mem->mobj->size < req_size)
177 return TEE_ERROR_SECURITY;
178
179 return TEE_SUCCESS;
180 }
181 #endif /*CFG_CORE_DYN_SHM*/
182 #endif /*!CFG_CORE_FFA*/
183
copy_in_params(const struct optee_msg_param * params,uint32_t num_params,struct tee_ta_param * ta_param,uint64_t * saved_attr)184 static TEE_Result copy_in_params(const struct optee_msg_param *params,
185 uint32_t num_params,
186 struct tee_ta_param *ta_param,
187 uint64_t *saved_attr)
188 {
189 TEE_Result res;
190 size_t n;
191 uint8_t pt[TEE_NUM_PARAMS] = { 0 };
192
193 if (num_params > TEE_NUM_PARAMS)
194 return TEE_ERROR_BAD_PARAMETERS;
195
196 memset(ta_param, 0, sizeof(*ta_param));
197
198 for (n = 0; n < num_params; n++) {
199 uint32_t attr;
200
201 saved_attr[n] = READ_ONCE(params[n].attr);
202
203 if (saved_attr[n] & OPTEE_MSG_ATTR_META)
204 return TEE_ERROR_BAD_PARAMETERS;
205
206 attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK;
207 switch (attr) {
208 case OPTEE_MSG_ATTR_TYPE_NONE:
209 pt[n] = TEE_PARAM_TYPE_NONE;
210 break;
211 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
212 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
213 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
214 pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr -
215 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
216 ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a);
217 ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b);
218 break;
219 #ifdef CFG_CORE_FFA
220 case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT:
221 case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT:
222 case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT:
223 res = set_fmem_param(¶ms[n].u.fmem,
224 &ta_param->u[n].mem);
225 if (res)
226 return res;
227 pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
228 OPTEE_MSG_ATTR_TYPE_FMEM_INPUT;
229 break;
230 #else /*!CFG_CORE_FFA*/
231 case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
232 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
233 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
234 res = set_tmem_param(¶ms[n].u.tmem, saved_attr[n],
235 &ta_param->u[n].mem);
236 if (res)
237 return res;
238 pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
239 OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
240 break;
241 #ifdef CFG_CORE_DYN_SHM
242 case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
243 case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
244 case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
245 res = set_rmem_param(¶ms[n].u.rmem,
246 &ta_param->u[n].mem);
247 if (res)
248 return res;
249 pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
250 OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
251 break;
252 #endif /*CFG_CORE_DYN_SHM*/
253 #endif /*!CFG_CORE_FFA*/
254 default:
255 return TEE_ERROR_BAD_PARAMETERS;
256 }
257 }
258
259 ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]);
260
261 return TEE_SUCCESS;
262 }
263
cleanup_shm_refs(const uint64_t * saved_attr,struct tee_ta_param * param,uint32_t num_params)264 static void cleanup_shm_refs(const uint64_t *saved_attr,
265 struct tee_ta_param *param, uint32_t num_params)
266 {
267 size_t n;
268
269 for (n = 0; n < MIN((unsigned int)TEE_NUM_PARAMS, num_params); n++) {
270 switch (saved_attr[n]) {
271 case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
272 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
273 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
274 #ifdef CFG_CORE_DYN_SHM
275 case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
276 case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
277 case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
278 #endif
279 mobj_put(param->u[n].mem.mobj);
280 break;
281 default:
282 break;
283 }
284 }
285 }
286
copy_out_param(struct tee_ta_param * ta_param,uint32_t num_params,struct optee_msg_param * params,uint64_t * saved_attr)287 static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
288 struct optee_msg_param *params, uint64_t *saved_attr)
289 {
290 size_t n;
291
292 for (n = 0; n < num_params; n++) {
293 switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
294 case TEE_PARAM_TYPE_MEMREF_OUTPUT:
295 case TEE_PARAM_TYPE_MEMREF_INOUT:
296 switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) {
297 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
298 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
299 params[n].u.tmem.size = ta_param->u[n].mem.size;
300 break;
301 case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
302 case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
303 params[n].u.rmem.size = ta_param->u[n].mem.size;
304 break;
305 default:
306 break;
307 }
308 break;
309 case TEE_PARAM_TYPE_VALUE_OUTPUT:
310 case TEE_PARAM_TYPE_VALUE_INOUT:
311 params[n].u.value.a = ta_param->u[n].val.a;
312 params[n].u.value.b = ta_param->u[n].val.b;
313 break;
314 default:
315 break;
316 }
317 }
318 }
319
320 /*
321 * Extracts mandatory parameter for open session.
322 *
323 * Returns
324 * false : mandatory parameter wasn't found or malformatted
325 * true : paramater found and OK
326 */
get_open_session_meta(size_t num_params,struct optee_msg_param * params,size_t * num_meta,TEE_UUID * uuid,TEE_Identity * clnt_id)327 static TEE_Result get_open_session_meta(size_t num_params,
328 struct optee_msg_param *params,
329 size_t *num_meta, TEE_UUID *uuid,
330 TEE_Identity *clnt_id)
331 {
332 const uint32_t req_attr = OPTEE_MSG_ATTR_META |
333 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
334
335 if (num_params < 2)
336 return TEE_ERROR_BAD_PARAMETERS;
337
338 if (params[0].attr != req_attr || params[1].attr != req_attr)
339 return TEE_ERROR_BAD_PARAMETERS;
340
341 tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value);
342 clnt_id->login = params[1].u.value.c;
343 switch (clnt_id->login) {
344 case TEE_LOGIN_PUBLIC:
345 case TEE_LOGIN_REE_KERNEL:
346 memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
347 break;
348 case TEE_LOGIN_USER:
349 case TEE_LOGIN_GROUP:
350 case TEE_LOGIN_APPLICATION:
351 case TEE_LOGIN_APPLICATION_USER:
352 case TEE_LOGIN_APPLICATION_GROUP:
353 tee_uuid_from_octets(&clnt_id->uuid,
354 (void *)¶ms[1].u.value);
355 break;
356 default:
357 return TEE_ERROR_BAD_PARAMETERS;
358 }
359
360 *num_meta = 2;
361 return TEE_SUCCESS;
362 }
363
entry_open_session(struct optee_msg_arg * arg,uint32_t num_params)364 static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params)
365 {
366 TEE_Result res = TEE_ERROR_GENERIC;
367 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
368 struct tee_ta_session *s = NULL;
369 TEE_Identity clnt_id = { };
370 TEE_UUID uuid = { };
371 struct tee_ta_param param = { };
372 size_t num_meta = 0;
373 uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
374
375 res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid,
376 &clnt_id);
377 if (res != TEE_SUCCESS)
378 goto out;
379
380 res = copy_in_params(arg->params + num_meta, num_params - num_meta,
381 ¶m, saved_attr);
382 if (res != TEE_SUCCESS)
383 goto cleanup_shm_refs;
384
385 res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid,
386 &clnt_id, TEE_TIMEOUT_INFINITE, ¶m);
387 if (res != TEE_SUCCESS)
388 s = NULL;
389 copy_out_param(¶m, num_params - num_meta, arg->params + num_meta,
390 saved_attr);
391
392 /*
393 * The occurrence of open/close session command is usually
394 * un-predictable, using this property to increase randomness
395 * of prng
396 */
397 plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
398 &session_pnum);
399
400 cleanup_shm_refs:
401 cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta);
402
403 out:
404 if (s)
405 arg->session = s->id;
406 else
407 arg->session = 0;
408 arg->ret = res;
409 arg->ret_origin = err_orig;
410 }
411
entry_close_session(struct optee_msg_arg * arg,uint32_t num_params)412 static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params)
413 {
414 TEE_Result res;
415 struct tee_ta_session *s;
416
417 if (num_params) {
418 res = TEE_ERROR_BAD_PARAMETERS;
419 goto out;
420 }
421
422 plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION,
423 &session_pnum);
424
425 s = tee_ta_find_session(arg->session, &tee_open_sessions);
426 res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY);
427 out:
428 arg->ret = res;
429 arg->ret_origin = TEE_ORIGIN_TEE;
430 }
431
entry_invoke_command(struct optee_msg_arg * arg,uint32_t num_params)432 static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params)
433 {
434 TEE_Result res;
435 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
436 struct tee_ta_session *s;
437 struct tee_ta_param param = { 0 };
438 uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
439
440 res = copy_in_params(arg->params, num_params, ¶m, saved_attr);
441 if (res != TEE_SUCCESS)
442 goto out;
443
444 s = tee_ta_get_session(arg->session, true, &tee_open_sessions);
445 if (!s) {
446 res = TEE_ERROR_BAD_PARAMETERS;
447 goto out;
448 }
449
450 res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
451 TEE_TIMEOUT_INFINITE, arg->func, ¶m);
452
453 tee_ta_put_session(s);
454
455 copy_out_param(¶m, num_params, arg->params, saved_attr);
456
457 out:
458 cleanup_shm_refs(saved_attr, ¶m, num_params);
459
460 arg->ret = res;
461 arg->ret_origin = err_orig;
462 }
463
entry_cancel(struct optee_msg_arg * arg,uint32_t num_params)464 static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params)
465 {
466 TEE_Result res;
467 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
468 struct tee_ta_session *s;
469
470 if (num_params) {
471 res = TEE_ERROR_BAD_PARAMETERS;
472 goto out;
473 }
474
475 s = tee_ta_get_session(arg->session, false, &tee_open_sessions);
476 if (!s) {
477 res = TEE_ERROR_BAD_PARAMETERS;
478 goto out;
479 }
480
481 res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY);
482 tee_ta_put_session(s);
483
484 out:
485 arg->ret = res;
486 arg->ret_origin = err_orig;
487 }
488
489 #ifndef CFG_CORE_FFA
490 #ifdef CFG_CORE_DYN_SHM
register_shm(struct optee_msg_arg * arg,uint32_t num_params)491 static void register_shm(struct optee_msg_arg *arg, uint32_t num_params)
492 {
493 struct optee_msg_param_tmem *tmem = NULL;
494 struct mobj *mobj = NULL;
495
496 arg->ret = TEE_ERROR_BAD_PARAMETERS;
497
498 if (num_params != 1 ||
499 (arg->params[0].attr !=
500 (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)))
501 return;
502
503 tmem = &arg->params[0].u.tmem;
504 mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size,
505 tmem->shm_ref, false);
506
507 if (!mobj)
508 return;
509
510 mobj_reg_shm_unguard(mobj);
511 arg->ret = TEE_SUCCESS;
512 }
513
unregister_shm(struct optee_msg_arg * arg,uint32_t num_params)514 static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params)
515 {
516 if (num_params == 1) {
517 uint64_t cookie = arg->params[0].u.rmem.shm_ref;
518 TEE_Result res = mobj_reg_shm_release_by_cookie(cookie);
519
520 if (res)
521 EMSG("Can't find mapping with given cookie");
522 arg->ret = res;
523 } else {
524 arg->ret = TEE_ERROR_BAD_PARAMETERS;
525 arg->ret_origin = TEE_ORIGIN_TEE;
526 }
527 }
528 #endif /*CFG_CORE_DYN_SHM*/
529 #endif
530
lend_protmem(struct optee_msg_arg * arg,uint32_t num_params)531 static void __maybe_unused lend_protmem(struct optee_msg_arg *arg,
532 uint32_t num_params)
533 {
534 TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
535 struct optee_msg_param_tmem *tmem = NULL;
536 struct mobj *mobj = NULL;
537 uint64_t use_case = 0;
538 uint64_t cookie = 0;
539 paddr_size_t sz = 0;
540 paddr_t pa = 0;
541
542 if (num_params != 2 ||
543 READ_ONCE(arg->params[0].attr) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT ||
544 READ_ONCE(arg->params[1].attr) != OPTEE_MSG_ATTR_TYPE_TMEM_INPUT)
545 goto out;
546
547 use_case = READ_ONCE(arg->params[0].u.value.a);
548 tmem = &arg->params[1].u.tmem;
549 cookie = READ_ONCE(tmem->shm_ref);
550 pa = READ_ONCE(tmem->buf_ptr);
551 sz = READ_ONCE(tmem->size);
552
553 switch (use_case) {
554 case MOBJ_USE_CASE_SEC_VIDEO_PLAY:
555 case MOBJ_USE_CASE_TRUSED_UI:
556 break;
557 default:
558 goto out;
559 }
560 mobj = mobj_protmem_alloc(pa, sz, cookie, use_case);
561 if (mobj)
562 res = TEE_SUCCESS;
563 out:
564 arg->ret = res;
565 }
566
assign_protmem(struct optee_msg_arg * arg,uint32_t num_params)567 static void __maybe_unused assign_protmem(struct optee_msg_arg *arg,
568 uint32_t num_params)
569 {
570 TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
571 uint64_t use_case = 0;
572 uint64_t cookie = 0;
573
574 if (num_params != 1 ||
575 READ_ONCE(arg->params[0].attr) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
576 goto out;
577
578 cookie = READ_ONCE(arg->params[0].u.value.a);
579 use_case = READ_ONCE(arg->params[0].u.value.b);
580 res = mobj_ffa_assign_protmem(cookie, use_case);
581 out:
582 arg->ret = res;
583 }
584
reclaim_protmem(struct optee_msg_arg * arg,uint32_t num_params)585 static void __maybe_unused reclaim_protmem(struct optee_msg_arg *arg,
586 uint32_t num_params)
587 {
588 if (num_params == 1 &&
589 READ_ONCE(arg->params[0].attr) == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT) {
590 uint64_t cookie = READ_ONCE(arg->params[0].u.rmem.shm_ref);
591 TEE_Result res = mobj_protmem_release_by_cookie(cookie);
592
593 if (res)
594 EMSG("Can't find mapping with cookie %#"PRIx64,
595 cookie);
596 arg->ret = res;
597 } else {
598 arg->ret = TEE_ERROR_BAD_PARAMETERS;
599 arg->ret_origin = TEE_ORIGIN_TEE;
600 }
601 }
602
get_protmem_config(struct optee_msg_arg * arg,uint32_t num_params)603 static void __maybe_unused get_protmem_config(struct optee_msg_arg *arg,
604 uint32_t num_params)
605 {
606 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT,
607 TEE_PARAM_TYPE_MEMREF_OUTPUT,
608 TEE_PARAM_TYPE_NONE,
609 TEE_PARAM_TYPE_NONE);
610 uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
611 TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
612 struct tee_ta_param param = { 0 };
613 size_t min_mem_align = 0;
614 size_t min_mem_sz = 0;
615 uint64_t use_case = 0;
616 void *buf = NULL;
617 size_t sz = 0;
618
619 arg->ret_origin = TEE_ORIGIN_TEE;
620
621 if (num_params != 2)
622 goto out;
623 res = copy_in_params(arg->params, num_params, ¶m, saved_attr);
624 if (res)
625 goto out;
626 if (param.types != exp_pt) {
627 res = TEE_ERROR_BAD_PARAMETERS;
628 goto out_cleanup;
629 }
630
631 use_case = param.u[0].val.a;
632 /* Check that it's not truncated when passed as an enum */
633 if (use_case >= INT_MAX) {
634 res = TEE_ERROR_BAD_PARAMETERS;
635 goto out_cleanup;
636 }
637 sz = param.u[1].mem.size;
638 if (param.u[1].mem.mobj) {
639 res = mobj_inc_map(param.u[1].mem.mobj);
640 if (res)
641 goto out_cleanup;
642 buf = mobj_get_va(param.u[1].mem.mobj, param.u[1].mem.offs, sz);
643 if (!buf) {
644 res = TEE_ERROR_BAD_PARAMETERS;
645 goto out_dec_map;
646 }
647 }
648
649 if (IS_ENABLED(CFG_CORE_FFA)) {
650 #ifdef CFG_CORE_FFA
651 res = thread_spmc_get_protmem_config(use_case, buf, &sz,
652 &min_mem_sz,
653 &min_mem_align);
654 #else
655 res = TEE_ERROR_NOT_SUPPORTED;
656 #endif
657 } else {
658 res = plat_get_protmem_config(use_case, &min_mem_sz,
659 &min_mem_align);
660 }
661 if (!res || res == TEE_ERROR_SHORT_BUFFER) {
662 param.u[1].mem.size = sz;
663 param.u[0].val.a = min_mem_sz;
664 param.u[0].val.b = min_mem_align;
665 }
666 copy_out_param(¶m, num_params, arg->params, saved_attr);
667 arg->params[0].u.value.c = sizeof(long) * 8;
668
669 out_dec_map:
670 mobj_dec_map(param.u[1].mem.mobj);
671 out_cleanup:
672 cleanup_shm_refs(saved_attr, ¶m, num_params);
673 out:
674 arg->ret = res;
675 }
676
nsec_sessions_list_head(struct tee_ta_session_head ** open_sessions)677 void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions)
678 {
679 *open_sessions = &tee_open_sessions;
680 }
681
682 /* Note: this function is weak to let platforms add special handling */
tee_entry_std(struct optee_msg_arg * arg,uint32_t num_params)683 TEE_Result __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
684 {
685 return __tee_entry_std(arg, num_params);
686 }
687
688 /*
689 * If tee_entry_std() is overridden, it's still supposed to call this
690 * function.
691 */
__tee_entry_std(struct optee_msg_arg * arg,uint32_t num_params)692 TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
693 {
694 TEE_Result res = TEE_SUCCESS;
695
696 /* Enable foreign interrupts for STD calls */
697 thread_set_foreign_intr(true);
698 switch (arg->cmd) {
699 case OPTEE_MSG_CMD_OPEN_SESSION:
700 entry_open_session(arg, num_params);
701 break;
702 case OPTEE_MSG_CMD_CLOSE_SESSION:
703 entry_close_session(arg, num_params);
704 break;
705 case OPTEE_MSG_CMD_INVOKE_COMMAND:
706 entry_invoke_command(arg, num_params);
707 break;
708 case OPTEE_MSG_CMD_CANCEL:
709 entry_cancel(arg, num_params);
710 break;
711 #if defined(CFG_CORE_DYN_SHM) && !defined(CFG_CORE_FFA)
712 case OPTEE_MSG_CMD_REGISTER_SHM:
713 register_shm(arg, num_params);
714 break;
715 case OPTEE_MSG_CMD_UNREGISTER_SHM:
716 unregister_shm(arg, num_params);
717 break;
718 #endif
719 case OPTEE_MSG_CMD_DO_BOTTOM_HALF:
720 if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
721 notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF);
722 else
723 goto err;
724 break;
725 case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF:
726 if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
727 notif_deliver_event(NOTIF_EVENT_STOPPED);
728 else
729 goto err;
730 break;
731 #ifdef CFG_CORE_DYN_PROTMEM
732 case OPTEE_MSG_CMD_GET_PROTMEM_CONFIG:
733 get_protmem_config(arg, num_params);
734 break;
735 #ifdef CFG_CORE_FFA
736 case OPTEE_MSG_CMD_ASSIGN_PROTMEM:
737 assign_protmem(arg, num_params);
738 break;
739 #else
740 case OPTEE_MSG_CMD_LEND_PROTMEM:
741 lend_protmem(arg, num_params);
742 break;
743 case OPTEE_MSG_CMD_RECLAIM_PROTMEM:
744 reclaim_protmem(arg, num_params);
745 break;
746 #endif /*!CFG_CORE_FFA*/
747 #endif /*CFG_CORE_DYN_PROTMEM*/
748 default:
749 err:
750 EMSG("Unknown cmd 0x%x", arg->cmd);
751 res = TEE_ERROR_NOT_IMPLEMENTED;
752 }
753
754 return res;
755 }
756
default_mobj_init(void)757 static TEE_Result default_mobj_init(void)
758 {
759 #ifdef CFG_CORE_RESERVED_SHM
760 shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr,
761 default_nsec_shm_size, SHM_CACHE_ATTRS,
762 CORE_MEM_NSEC_SHM);
763 if (!shm_mobj)
764 panic("Failed to register shared memory");
765 #endif
766
767 #ifdef CFG_SECURE_DATA_PATH
768 sdp_mem_mobjs = core_sdp_mem_create_mobjs();
769 if (!sdp_mem_mobjs)
770 panic("Failed to register SDP memory");
771 #endif
772
773 return TEE_SUCCESS;
774 }
775
776 driver_init_late(default_mobj_init);
777