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