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