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; 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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