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 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 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 */ 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 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 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 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 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 */ 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 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 uint32_t sess_id = 0; 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, &sess_id, &tee_open_sessions, 386 &uuid, &clnt_id, TEE_TIMEOUT_INFINITE, 387 ¶m); 388 if (res) 389 sess_id = 0; 390 copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, 391 saved_attr); 392 393 /* 394 * The occurrence of open/close session command is usually 395 * un-predictable, using this property to increase randomness 396 * of prng 397 */ 398 plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 399 &session_pnum); 400 401 cleanup_shm_refs: 402 cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); 403 404 out: 405 arg->session = sess_id; 406 arg->ret = res; 407 arg->ret_origin = err_orig; 408 } 409 410 static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params) 411 { 412 TEE_Result res = TEE_SUCCESS; 413 414 if (num_params) { 415 res = TEE_ERROR_BAD_PARAMETERS; 416 goto out; 417 } 418 419 plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, 420 &session_pnum); 421 422 res = tee_ta_close_session(arg->session, &tee_open_sessions, 423 NSAPP_IDENTITY); 424 out: 425 arg->ret = res; 426 arg->ret_origin = TEE_ORIGIN_TEE; 427 } 428 429 static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params) 430 { 431 TEE_Result res; 432 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 433 struct tee_ta_session *s; 434 struct tee_ta_param param = { 0 }; 435 uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 436 437 res = copy_in_params(arg->params, num_params, ¶m, saved_attr); 438 if (res != TEE_SUCCESS) 439 goto out; 440 441 s = tee_ta_get_session(arg->session, true, &tee_open_sessions); 442 if (!s) { 443 res = TEE_ERROR_BAD_PARAMETERS; 444 goto out; 445 } 446 447 res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, 448 TEE_TIMEOUT_INFINITE, arg->func, ¶m); 449 450 tee_ta_put_session(s); 451 452 copy_out_param(¶m, num_params, arg->params, saved_attr); 453 454 out: 455 cleanup_shm_refs(saved_attr, ¶m, num_params); 456 457 arg->ret = res; 458 arg->ret_origin = err_orig; 459 } 460 461 static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params) 462 { 463 TEE_Result res; 464 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; 465 struct tee_ta_session *s; 466 467 if (num_params) { 468 res = TEE_ERROR_BAD_PARAMETERS; 469 goto out; 470 } 471 472 s = tee_ta_get_session(arg->session, false, &tee_open_sessions); 473 if (!s) { 474 res = TEE_ERROR_BAD_PARAMETERS; 475 goto out; 476 } 477 478 res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY); 479 tee_ta_put_session(s); 480 481 out: 482 arg->ret = res; 483 arg->ret_origin = err_orig; 484 } 485 486 #ifndef CFG_CORE_FFA 487 #ifdef CFG_CORE_DYN_SHM 488 static void register_shm(struct optee_msg_arg *arg, uint32_t num_params) 489 { 490 struct optee_msg_param_tmem *tmem = NULL; 491 struct mobj *mobj = NULL; 492 493 arg->ret = TEE_ERROR_BAD_PARAMETERS; 494 495 if (num_params != 1 || 496 (arg->params[0].attr != 497 (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) 498 return; 499 500 tmem = &arg->params[0].u.tmem; 501 mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size, 502 tmem->shm_ref, false); 503 504 if (!mobj) 505 return; 506 507 mobj_reg_shm_unguard(mobj); 508 arg->ret = TEE_SUCCESS; 509 } 510 511 static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params) 512 { 513 if (num_params == 1) { 514 uint64_t cookie = arg->params[0].u.rmem.shm_ref; 515 TEE_Result res = mobj_reg_shm_release_by_cookie(cookie); 516 517 if (res) 518 EMSG("Can't find mapping with given cookie"); 519 arg->ret = res; 520 } else { 521 arg->ret = TEE_ERROR_BAD_PARAMETERS; 522 arg->ret_origin = TEE_ORIGIN_TEE; 523 } 524 } 525 #endif /*CFG_CORE_DYN_SHM*/ 526 #endif 527 528 static void __maybe_unused lend_protmem(struct optee_msg_arg *arg, 529 uint32_t num_params) 530 { 531 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 532 struct optee_msg_param_tmem *tmem = NULL; 533 struct mobj *mobj = NULL; 534 uint64_t use_case = 0; 535 uint64_t cookie = 0; 536 paddr_size_t sz = 0; 537 paddr_t pa = 0; 538 539 if (num_params != 2 || 540 READ_ONCE(arg->params[0].attr) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT || 541 READ_ONCE(arg->params[1].attr) != OPTEE_MSG_ATTR_TYPE_TMEM_INPUT) 542 goto out; 543 544 use_case = READ_ONCE(arg->params[0].u.value.a); 545 tmem = &arg->params[1].u.tmem; 546 cookie = READ_ONCE(tmem->shm_ref); 547 pa = READ_ONCE(tmem->buf_ptr); 548 sz = READ_ONCE(tmem->size); 549 550 switch (use_case) { 551 case MOBJ_USE_CASE_SEC_VIDEO_PLAY: 552 case MOBJ_USE_CASE_TRUSED_UI: 553 break; 554 default: 555 goto out; 556 } 557 mobj = mobj_protmem_alloc(pa, sz, cookie, use_case); 558 if (mobj) 559 res = TEE_SUCCESS; 560 out: 561 arg->ret = res; 562 } 563 564 static void __maybe_unused assign_protmem(struct optee_msg_arg *arg, 565 uint32_t num_params) 566 { 567 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 568 uint64_t use_case = 0; 569 uint64_t cookie = 0; 570 571 if (num_params != 1 || 572 READ_ONCE(arg->params[0].attr) != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) 573 goto out; 574 575 cookie = READ_ONCE(arg->params[0].u.value.a); 576 use_case = READ_ONCE(arg->params[0].u.value.b); 577 res = mobj_ffa_assign_protmem(cookie, use_case); 578 out: 579 arg->ret = res; 580 } 581 582 static void __maybe_unused reclaim_protmem(struct optee_msg_arg *arg, 583 uint32_t num_params) 584 { 585 if (num_params == 1 && 586 READ_ONCE(arg->params[0].attr) == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT) { 587 uint64_t cookie = READ_ONCE(arg->params[0].u.rmem.shm_ref); 588 TEE_Result res = mobj_protmem_release_by_cookie(cookie); 589 590 if (res) 591 EMSG("Can't find mapping with cookie %#"PRIx64, 592 cookie); 593 arg->ret = res; 594 } else { 595 arg->ret = TEE_ERROR_BAD_PARAMETERS; 596 arg->ret_origin = TEE_ORIGIN_TEE; 597 } 598 } 599 600 static void __maybe_unused get_protmem_config(struct optee_msg_arg *arg, 601 uint32_t num_params) 602 { 603 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, 604 TEE_PARAM_TYPE_MEMREF_OUTPUT, 605 TEE_PARAM_TYPE_NONE, 606 TEE_PARAM_TYPE_NONE); 607 uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; 608 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 609 struct tee_ta_param param = { 0 }; 610 size_t min_mem_align = 0; 611 size_t min_mem_sz = 0; 612 uint64_t use_case = 0; 613 void *buf = NULL; 614 size_t sz = 0; 615 616 arg->ret_origin = TEE_ORIGIN_TEE; 617 618 if (num_params != 2) 619 goto out; 620 res = copy_in_params(arg->params, num_params, ¶m, saved_attr); 621 if (res) 622 goto out; 623 if (param.types != exp_pt) { 624 res = TEE_ERROR_BAD_PARAMETERS; 625 goto out_cleanup; 626 } 627 628 use_case = param.u[0].val.a; 629 /* Check that it's not truncated when passed as an enum */ 630 if (use_case >= INT_MAX) { 631 res = TEE_ERROR_BAD_PARAMETERS; 632 goto out_cleanup; 633 } 634 sz = param.u[1].mem.size; 635 if (param.u[1].mem.mobj) { 636 res = mobj_inc_map(param.u[1].mem.mobj); 637 if (res) 638 goto out_cleanup; 639 buf = mobj_get_va(param.u[1].mem.mobj, param.u[1].mem.offs, sz); 640 if (!buf) { 641 res = TEE_ERROR_BAD_PARAMETERS; 642 goto out_dec_map; 643 } 644 } 645 646 if (IS_ENABLED(CFG_CORE_FFA)) { 647 #ifdef CFG_CORE_FFA 648 res = thread_spmc_get_protmem_config(use_case, buf, &sz, 649 &min_mem_sz, 650 &min_mem_align); 651 #else 652 res = TEE_ERROR_NOT_SUPPORTED; 653 #endif 654 } else { 655 res = plat_get_protmem_config(use_case, &min_mem_sz, 656 &min_mem_align); 657 } 658 if (!res || res == TEE_ERROR_SHORT_BUFFER) { 659 param.u[1].mem.size = sz; 660 param.u[0].val.a = min_mem_sz; 661 param.u[0].val.b = min_mem_align; 662 } 663 copy_out_param(¶m, num_params, arg->params, saved_attr); 664 arg->params[0].u.value.c = sizeof(long) * 8; 665 666 out_dec_map: 667 mobj_dec_map(param.u[1].mem.mobj); 668 out_cleanup: 669 cleanup_shm_refs(saved_attr, ¶m, num_params); 670 out: 671 arg->ret = res; 672 } 673 674 void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions) 675 { 676 *open_sessions = &tee_open_sessions; 677 } 678 679 /* Note: this function is weak to let platforms add special handling */ 680 TEE_Result __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 681 { 682 return __tee_entry_std(arg, num_params); 683 } 684 685 /* 686 * If tee_entry_std() is overridden, it's still supposed to call this 687 * function. 688 */ 689 TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) 690 { 691 TEE_Result res = TEE_SUCCESS; 692 693 /* Enable foreign interrupts for STD calls */ 694 thread_set_foreign_intr(true); 695 switch (arg->cmd) { 696 case OPTEE_MSG_CMD_OPEN_SESSION: 697 entry_open_session(arg, num_params); 698 break; 699 case OPTEE_MSG_CMD_CLOSE_SESSION: 700 entry_close_session(arg, num_params); 701 break; 702 case OPTEE_MSG_CMD_INVOKE_COMMAND: 703 entry_invoke_command(arg, num_params); 704 break; 705 case OPTEE_MSG_CMD_CANCEL: 706 entry_cancel(arg, num_params); 707 break; 708 #if defined(CFG_CORE_DYN_SHM) && !defined(CFG_CORE_FFA) 709 case OPTEE_MSG_CMD_REGISTER_SHM: 710 register_shm(arg, num_params); 711 break; 712 case OPTEE_MSG_CMD_UNREGISTER_SHM: 713 unregister_shm(arg, num_params); 714 break; 715 #endif 716 case OPTEE_MSG_CMD_DO_BOTTOM_HALF: 717 if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) 718 notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF); 719 else 720 goto err; 721 break; 722 case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF: 723 if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) 724 notif_deliver_event(NOTIF_EVENT_STOPPED); 725 else 726 goto err; 727 break; 728 #ifdef CFG_CORE_DYN_PROTMEM 729 case OPTEE_MSG_CMD_GET_PROTMEM_CONFIG: 730 get_protmem_config(arg, num_params); 731 break; 732 #ifdef CFG_CORE_FFA 733 case OPTEE_MSG_CMD_ASSIGN_PROTMEM: 734 assign_protmem(arg, num_params); 735 break; 736 #else 737 case OPTEE_MSG_CMD_LEND_PROTMEM: 738 lend_protmem(arg, num_params); 739 break; 740 case OPTEE_MSG_CMD_RECLAIM_PROTMEM: 741 reclaim_protmem(arg, num_params); 742 break; 743 #endif /*!CFG_CORE_FFA*/ 744 #endif /*CFG_CORE_DYN_PROTMEM*/ 745 default: 746 err: 747 EMSG("Unknown cmd 0x%x", arg->cmd); 748 res = TEE_ERROR_NOT_IMPLEMENTED; 749 } 750 751 return res; 752 } 753 754 static TEE_Result default_mobj_init(void) 755 { 756 #ifdef CFG_CORE_RESERVED_SHM 757 shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr, 758 default_nsec_shm_size, SHM_CACHE_ATTRS, 759 CORE_MEM_NSEC_SHM); 760 if (!shm_mobj) 761 panic("Failed to register shared memory"); 762 #endif 763 764 #ifdef CFG_SECURE_DATA_PATH 765 sdp_mem_mobjs = core_sdp_mem_create_mobjs(); 766 if (!sdp_mem_mobjs) 767 panic("Failed to register SDP memory"); 768 #endif 769 770 return TEE_SUCCESS; 771 } 772 773 driver_init_late(default_mobj_init); 774