1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, Linaro Limited 4 * Copyright (c) 2020, Arm Limited. 5 */ 6 7 #include <crypto/crypto.h> 8 #include <ffa.h> 9 #include <keep.h> 10 #include <kernel/abort.h> 11 #include <kernel/stmm_sp.h> 12 #include <kernel/thread_private.h> 13 #include <kernel/user_mode_ctx.h> 14 #include <mm/fobj.h> 15 #include <mm/mobj.h> 16 #include <mm/vm.h> 17 #include <pta_stmm.h> 18 #include <tee_api_defines_extensions.h> 19 #include <tee/tee_pobj.h> 20 #include <tee/tee_svc.h> 21 #include <tee/tee_svc_storage.h> 22 #include <zlib.h> 23 24 #ifdef ARM64 25 #define SVC_REGS_A0(_regs) ((_regs)->x0) 26 #define SVC_REGS_A1(_regs) ((_regs)->x1) 27 #define SVC_REGS_A2(_regs) ((_regs)->x2) 28 #define SVC_REGS_A3(_regs) ((_regs)->x3) 29 #define SVC_REGS_A4(_regs) ((_regs)->x4) 30 #define SVC_REGS_A5(_regs) ((_regs)->x5) 31 #define SVC_REGS_A6(_regs) ((_regs)->x6) 32 #define SVC_REGS_A7(_regs) ((_regs)->x7) 33 #define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ 34 #define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE 35 #define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_64 36 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_64 37 #define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_64 38 #define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_64 39 #endif 40 #ifdef ARM32 41 #define SVC_REGS_A0(_regs) ((_regs)->r0) 42 #define SVC_REGS_A1(_regs) ((_regs)->r1) 43 #define SVC_REGS_A2(_regs) ((_regs)->r2) 44 #define SVC_REGS_A3(_regs) ((_regs)->r3) 45 #define SVC_REGS_A4(_regs) ((_regs)->r4) 46 #define SVC_REGS_A5(_regs) ((_regs)->r5) 47 #define SVC_REGS_A6(_regs) ((_regs)->r6) 48 #define SVC_REGS_A7(_regs) ((_regs)->r7) 49 #define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ_32 50 #define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE_32 51 #define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_32 52 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_32 53 #define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_32 54 #define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_32 55 #endif 56 57 static const TEE_UUID stmm_uuid = PTA_STMM_UUID; 58 59 /* 60 * Once a complete FFA spec is added, these will become discoverable. 61 * Until then these are considered part of the internal ABI between 62 * OP-TEE and StMM. 63 */ 64 static const uint16_t stmm_id = 1U; 65 static const uint16_t stmm_pta_id = 2U; 66 static const uint16_t mem_mgr_id = 3U; 67 static const uint16_t ffa_storage_id = 4U; 68 69 static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE; 70 static const unsigned int stmm_heap_size = 398 * SMALL_PAGE_SIZE; 71 static const unsigned int stmm_sec_buf_size = 4 * SMALL_PAGE_SIZE; 72 static const unsigned int stmm_ns_comm_buf_size = 4 * SMALL_PAGE_SIZE; 73 74 extern unsigned char stmm_image[]; 75 extern const unsigned int stmm_image_size; 76 extern const unsigned int stmm_image_uncompressed_size; 77 78 static struct stmm_ctx *stmm_alloc_ctx(const TEE_UUID *uuid) 79 { 80 TEE_Result res = TEE_SUCCESS; 81 struct stmm_ctx *spc = NULL; 82 83 spc = calloc(1, sizeof(*spc)); 84 if (!spc) 85 return NULL; 86 87 spc->ta_ctx.ts_ctx.ops = &stmm_sp_ops; 88 spc->ta_ctx.ts_ctx.uuid = *uuid; 89 spc->ta_ctx.flags = TA_FLAG_SINGLE_INSTANCE | 90 TA_FLAG_INSTANCE_KEEP_ALIVE; 91 spc->uctx.ts_ctx = &spc->ta_ctx.ts_ctx; 92 93 res = vm_info_init(&spc->uctx); 94 if (res) { 95 free(spc); 96 return NULL; 97 } 98 99 spc->ta_ctx.ref_count = 1; 100 condvar_init(&spc->ta_ctx.busy_cv); 101 102 return spc; 103 } 104 105 static TEE_Result stmm_enter_user_mode(struct stmm_ctx *spc) 106 { 107 uint32_t exceptions = 0; 108 uint32_t panic_code = 0; 109 uint32_t panicked = 0; 110 uint64_t cntkctl = 0; 111 112 exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); 113 cntkctl = read_cntkctl(); 114 write_cntkctl(cntkctl | CNTKCTL_PL0PCTEN); 115 __thread_enter_user_mode(&spc->regs, &panicked, &panic_code); 116 write_cntkctl(cntkctl); 117 thread_unmask_exceptions(exceptions); 118 119 thread_user_clear_vfp(&spc->uctx); 120 121 if (panicked) { 122 abort_print_current_ts(); 123 DMSG("stmm panicked with code %#"PRIx32, panic_code); 124 return TEE_ERROR_TARGET_DEAD; 125 } 126 127 return TEE_SUCCESS; 128 } 129 130 #ifdef ARM64 131 static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, 132 unsigned long a1, unsigned long sp, unsigned long pc) 133 { 134 spc->regs.x[0] = a0; 135 spc->regs.x[1] = a1; 136 spc->regs.sp = sp; 137 spc->regs.pc = pc; 138 } 139 #endif 140 141 #ifdef ARM32 142 static uint32_t __maybe_unused get_spsr(void) 143 { 144 uint32_t s = 0; 145 146 s = read_cpsr(); 147 s &= ~(CPSR_MODE_MASK | CPSR_T | ARM32_CPSR_IT_MASK); 148 s |= CPSR_MODE_USR; 149 150 return s; 151 } 152 153 static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, 154 unsigned long a1, unsigned long sp, unsigned long pc) 155 { 156 spc->regs.r0 = a0; 157 spc->regs.r1 = a1; 158 spc->regs.usr_sp = sp; 159 spc->regs.cpsr = get_spsr(); 160 spc->regs.pc = pc; 161 } 162 #endif 163 164 static TEE_Result alloc_and_map_sp_fobj(struct stmm_ctx *spc, size_t sz, 165 uint32_t prot, vaddr_t *va) 166 { 167 size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; 168 struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); 169 struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL); 170 TEE_Result res = TEE_SUCCESS; 171 172 fobj_put(fobj); 173 if (!mobj) 174 return TEE_ERROR_OUT_OF_MEMORY; 175 176 res = vm_map(&spc->uctx, va, num_pgs * SMALL_PAGE_SIZE, 177 prot, 0, mobj, 0); 178 if (res) 179 mobj_put(mobj); 180 181 return TEE_SUCCESS; 182 } 183 184 static void *zalloc(void *opaque __unused, unsigned int items, 185 unsigned int size) 186 { 187 return malloc(items * size); 188 } 189 190 static void zfree(void *opaque __unused, void *address) 191 { 192 free(address); 193 } 194 195 static void uncompress_image(void *dst, size_t dst_size, void *src, 196 size_t src_size) 197 { 198 z_stream strm = { 199 .next_in = src, 200 .avail_in = src_size, 201 .next_out = dst, 202 .avail_out = dst_size, 203 .zalloc = zalloc, 204 .zfree = zfree, 205 }; 206 207 if (inflateInit(&strm) != Z_OK) 208 panic("inflateInit"); 209 210 if (inflate(&strm, Z_SYNC_FLUSH) != Z_STREAM_END) 211 panic("inflate"); 212 213 if (inflateEnd(&strm) != Z_OK) 214 panic("inflateEnd"); 215 } 216 217 static TEE_Result load_stmm(struct stmm_ctx *spc) 218 { 219 struct stmm_boot_info *boot_info = NULL; 220 struct stmm_mp_info *mp_info = NULL; 221 TEE_Result res = TEE_SUCCESS; 222 vaddr_t sp_addr = 0; 223 vaddr_t image_addr = 0; 224 vaddr_t heap_addr = 0; 225 vaddr_t stack_addr = 0; 226 vaddr_t sec_buf_addr = 0; 227 vaddr_t comm_buf_addr = 0; 228 unsigned int sp_size = 0; 229 unsigned int uncompressed_size_roundup = 0; 230 231 uncompressed_size_roundup = ROUNDUP(stmm_image_uncompressed_size, 232 SMALL_PAGE_SIZE); 233 sp_size = uncompressed_size_roundup + stmm_stack_size + 234 stmm_heap_size + stmm_sec_buf_size; 235 res = alloc_and_map_sp_fobj(spc, sp_size, 236 TEE_MATTR_PRW, &sp_addr); 237 if (res) 238 return res; 239 240 res = alloc_and_map_sp_fobj(spc, stmm_ns_comm_buf_size, 241 TEE_MATTR_URW | TEE_MATTR_PRW, 242 &comm_buf_addr); 243 /* 244 * We don't need to free the previous instance here, they'll all be 245 * handled during the destruction call (stmm_ctx_destroy()) 246 */ 247 if (res) 248 return res; 249 250 image_addr = sp_addr; 251 heap_addr = image_addr + uncompressed_size_roundup; 252 stack_addr = heap_addr + stmm_heap_size; 253 sec_buf_addr = stack_addr + stmm_stack_size; 254 255 vm_set_ctx(&spc->ta_ctx.ts_ctx); 256 uncompress_image((void *)image_addr, stmm_image_uncompressed_size, 257 stmm_image, stmm_image_size); 258 259 res = vm_set_prot(&spc->uctx, image_addr, uncompressed_size_roundup, 260 TEE_MATTR_URX | TEE_MATTR_PR); 261 if (res) 262 return res; 263 264 res = vm_set_prot(&spc->uctx, heap_addr, stmm_heap_size, 265 TEE_MATTR_URW | TEE_MATTR_PRW); 266 if (res) 267 return res; 268 269 res = vm_set_prot(&spc->uctx, stack_addr, stmm_stack_size, 270 TEE_MATTR_URW | TEE_MATTR_PRW); 271 if (res) 272 return res; 273 274 res = vm_set_prot(&spc->uctx, sec_buf_addr, stmm_sec_buf_size, 275 TEE_MATTR_URW | TEE_MATTR_PRW); 276 if (res) 277 return res; 278 279 DMSG("stmm load address %#"PRIxVA, image_addr); 280 281 boot_info = (struct stmm_boot_info *)sec_buf_addr; 282 mp_info = (struct stmm_mp_info *)(boot_info + 1); 283 *boot_info = (struct stmm_boot_info){ 284 .h.type = STMM_PARAM_SP_IMAGE_BOOT_INFO, 285 .h.version = STMM_PARAM_VERSION_1, 286 .h.size = sizeof(struct stmm_boot_info), 287 .h.attr = 0, 288 .sp_mem_base = sp_addr, 289 .sp_mem_limit = sp_addr + sp_size, 290 .sp_image_base = image_addr, 291 .sp_stack_base = stack_addr, 292 .sp_heap_base = heap_addr, 293 .sp_ns_comm_buf_base = comm_buf_addr, 294 .sp_shared_buf_base = sec_buf_addr, 295 .sp_image_size = stmm_image_size, 296 .sp_pcpu_stack_size = stmm_stack_size, 297 .sp_heap_size = stmm_heap_size, 298 .sp_ns_comm_buf_size = stmm_ns_comm_buf_size, 299 .sp_shared_buf_size = stmm_sec_buf_size, 300 .num_sp_mem_regions = 6, 301 .num_cpus = 1, 302 .mp_info = mp_info, 303 }; 304 mp_info->mpidr = read_mpidr(); 305 mp_info->linear_id = 0; 306 mp_info->flags = MP_INFO_FLAG_PRIMARY_CPU; 307 spc->ns_comm_buf_addr = comm_buf_addr; 308 spc->ns_comm_buf_size = stmm_ns_comm_buf_size; 309 310 init_stmm_regs(spc, sec_buf_addr, 311 (vaddr_t)(mp_info + 1) - sec_buf_addr, 312 stack_addr + stmm_stack_size, image_addr); 313 314 return stmm_enter_user_mode(spc); 315 } 316 317 TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess) 318 { 319 struct stmm_ctx *spc = NULL; 320 TEE_Result res = TEE_SUCCESS; 321 322 if (memcmp(uuid, &stmm_uuid, sizeof(*uuid))) 323 return TEE_ERROR_ITEM_NOT_FOUND; 324 325 spc = stmm_alloc_ctx(uuid); 326 if (!spc) 327 return TEE_ERROR_OUT_OF_MEMORY; 328 329 spc->is_initializing = true; 330 331 mutex_lock(&tee_ta_mutex); 332 sess->ts_sess.ctx = &spc->ta_ctx.ts_ctx; 333 sess->ts_sess.handle_svc = sess->ts_sess.ctx->ops->handle_svc; 334 mutex_unlock(&tee_ta_mutex); 335 336 ts_push_current_session(&sess->ts_sess); 337 res = load_stmm(spc); 338 ts_pop_current_session(); 339 vm_set_ctx(NULL); 340 if (res) { 341 sess->ts_sess.ctx = NULL; 342 spc->ta_ctx.ts_ctx.ops->destroy(&spc->ta_ctx.ts_ctx); 343 344 return res; 345 } 346 347 mutex_lock(&tee_ta_mutex); 348 spc->is_initializing = false; 349 TAILQ_INSERT_TAIL(&tee_ctxes, &spc->ta_ctx, link); 350 mutex_unlock(&tee_ta_mutex); 351 352 return TEE_SUCCESS; 353 } 354 355 static TEE_Result stmm_enter_open_session(struct ts_session *s) 356 { 357 struct stmm_ctx *spc = to_stmm_ctx(s->ctx); 358 struct tee_ta_session *ta_sess = to_ta_session(s); 359 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, 360 TEE_PARAM_TYPE_NONE, 361 TEE_PARAM_TYPE_NONE, 362 TEE_PARAM_TYPE_NONE); 363 364 if (ta_sess->param->types != exp_pt) 365 return TEE_ERROR_BAD_PARAMETERS; 366 367 if (spc->is_initializing) { 368 /* StMM is initialized in stmm_init_session() */ 369 ta_sess->err_origin = TEE_ORIGIN_TEE; 370 return TEE_ERROR_BAD_STATE; 371 } 372 373 return TEE_SUCCESS; 374 } 375 376 static TEE_Result stmm_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) 377 { 378 struct stmm_ctx *spc = to_stmm_ctx(s->ctx); 379 struct tee_ta_session *ta_sess = to_ta_session(s); 380 TEE_Result res = TEE_SUCCESS; 381 TEE_Result __maybe_unused tmp_res = TEE_SUCCESS; 382 unsigned int ns_buf_size = 0; 383 struct param_mem *mem = NULL; 384 void *va = NULL; 385 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 386 TEE_PARAM_TYPE_VALUE_OUTPUT, 387 TEE_PARAM_TYPE_NONE, 388 TEE_PARAM_TYPE_NONE); 389 390 if (cmd != PTA_STMM_CMD_COMMUNICATE) 391 return TEE_ERROR_BAD_PARAMETERS; 392 393 if (ta_sess->param->types != exp_pt) 394 return TEE_ERROR_BAD_PARAMETERS; 395 396 mem = &ta_sess->param->u[0].mem; 397 ns_buf_size = mem->size; 398 if (ns_buf_size > spc->ns_comm_buf_size) { 399 mem->size = spc->ns_comm_buf_size; 400 return TEE_ERROR_EXCESS_DATA; 401 } 402 403 res = mobj_inc_map(mem->mobj); 404 if (res) 405 return res; 406 407 va = mobj_get_va(mem->mobj, mem->offs, mem->size); 408 if (!va) { 409 EMSG("Can't get a valid VA for NS buffer"); 410 res = TEE_ERROR_BAD_PARAMETERS; 411 goto out_va; 412 } 413 414 #ifdef ARM64 415 spc->regs.x[0] = __FFA_MSG_SEND_DIRECT_REQ; 416 spc->regs.x[1] = (stmm_pta_id << 16) | stmm_id; 417 spc->regs.x[2] = FFA_PARAM_MBZ; 418 spc->regs.x[3] = spc->ns_comm_buf_addr; 419 spc->regs.x[4] = ns_buf_size; 420 spc->regs.x[5] = 0; 421 spc->regs.x[6] = 0; 422 spc->regs.x[7] = 0; 423 #endif 424 #ifdef ARM32 425 spc->regs.r0 = __FFA_MSG_SEND_DIRECT_REQ; 426 spc->regs.r1 = (stmm_pta_id << 16) | stmm_id; 427 spc->regs.r2 = FFA_PARAM_MBZ; 428 spc->regs.r3 = spc->ns_comm_buf_addr; 429 spc->regs.r4 = ns_buf_size; 430 spc->regs.r5 = 0; 431 spc->regs.r6 = 0; 432 spc->regs.r7 = 0; 433 #endif 434 435 ts_push_current_session(s); 436 437 memcpy((void *)spc->ns_comm_buf_addr, va, ns_buf_size); 438 439 res = stmm_enter_user_mode(spc); 440 if (res) 441 goto out_session; 442 /* 443 * Copy the SPM response from secure partition back to the non-secure 444 * buffer of the client that called us. 445 */ 446 #ifdef ARM64 447 ta_sess->param->u[1].val.a = spc->regs.x[4]; 448 #endif 449 #ifdef ARM32 450 ta_sess->param->u[1].val.a = spc->regs.r4; 451 #endif 452 453 memcpy(va, (void *)spc->ns_comm_buf_addr, ns_buf_size); 454 455 out_session: 456 ts_pop_current_session(); 457 out_va: 458 tmp_res = mobj_dec_map(mem->mobj); 459 assert(!tmp_res); 460 461 return res; 462 } 463 464 static void stmm_enter_close_session(struct ts_session *s __unused) 465 { 466 } 467 468 static void stmm_dump_state(struct ts_ctx *ctx) 469 { 470 user_mode_ctx_print_mappings(to_user_mode_ctx(ctx)); 471 } 472 DECLARE_KEEP_PAGER(stmm_dump_state); 473 474 static uint32_t stmm_get_instance_id(struct ts_ctx *ctx) 475 { 476 return to_stmm_ctx(ctx)->uctx.vm_info.asid; 477 } 478 479 static void stmm_ctx_destroy(struct ts_ctx *ctx) 480 { 481 struct stmm_ctx *spc = to_stmm_ctx(ctx); 482 483 tee_pager_rem_um_regions(&spc->uctx); 484 vm_info_final(&spc->uctx); 485 free(spc); 486 } 487 488 static uint32_t sp_svc_get_mem_attr(vaddr_t va) 489 { 490 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 491 struct ts_session *sess = NULL; 492 struct stmm_ctx *spc = NULL; 493 uint16_t attrs = 0; 494 uint16_t perm = 0; 495 496 if (!va) 497 goto err; 498 499 sess = ts_get_current_session(); 500 spc = to_stmm_ctx(sess->ctx); 501 502 res = vm_get_prot(&spc->uctx, va, SMALL_PAGE_SIZE, &attrs); 503 if (res) 504 goto err; 505 506 if (attrs & TEE_MATTR_UR) 507 perm |= STMM_MEM_ATTR_ACCESS_RO; 508 else if (attrs & TEE_MATTR_UW) 509 perm |= STMM_MEM_ATTR_ACCESS_RW; 510 511 if (attrs & TEE_MATTR_UX) 512 perm |= STMM_MEM_ATTR_EXEC; 513 514 return perm; 515 err: 516 return STMM_RET_DENIED; 517 } 518 519 static int sp_svc_set_mem_attr(vaddr_t va, unsigned int nr_pages, uint32_t perm) 520 { 521 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 522 struct ts_session *sess = NULL; 523 struct stmm_ctx *spc = NULL; 524 size_t sz = 0; 525 uint32_t prot = 0; 526 527 if (!va || !nr_pages || MUL_OVERFLOW(nr_pages, SMALL_PAGE_SIZE, &sz)) 528 return STMM_RET_INVALID_PARAM; 529 530 if (perm & ~STMM_MEM_ATTR_ALL) 531 return STMM_RET_INVALID_PARAM; 532 533 sess = ts_get_current_session(); 534 spc = to_stmm_ctx(sess->ctx); 535 536 if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RO) 537 prot |= TEE_MATTR_UR; 538 else if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RW) 539 prot |= TEE_MATTR_URW; 540 541 if ((perm & STMM_MEM_ATTR_EXEC_NEVER) == STMM_MEM_ATTR_EXEC) 542 prot |= TEE_MATTR_UX; 543 544 res = vm_set_prot(&spc->uctx, va, sz, prot); 545 if (res) 546 return STMM_RET_DENIED; 547 548 return STMM_RET_SUCCESS; 549 } 550 551 #ifdef ARM64 552 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_svc_regs *svc_regs) 553 { 554 size_t n = 0; 555 556 /* Save the return values from StMM */ 557 for (n = 0; n <= 7; n++) 558 spc->regs.x[n] = *(&svc_regs->x0 + n); 559 560 spc->regs.sp = svc_regs->sp_el0; 561 spc->regs.pc = svc_regs->elr; 562 spc->regs.cpsr = svc_regs->spsr; 563 } 564 #endif 565 566 #ifdef ARM32 567 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_svc_regs *svc_regs) 568 { 569 spc->regs.r0 = svc_regs->r0; 570 spc->regs.r1 = svc_regs->r1; 571 spc->regs.r2 = svc_regs->r2; 572 spc->regs.r3 = svc_regs->r3; 573 spc->regs.r4 = svc_regs->r4; 574 spc->regs.r5 = svc_regs->r5; 575 spc->regs.r6 = svc_regs->r6; 576 spc->regs.r7 = svc_regs->r7; 577 spc->regs.pc = svc_regs->lr; 578 spc->regs.cpsr = svc_regs->spsr; 579 spc->regs.usr_sp = thread_get_usr_sp(); 580 } 581 #endif 582 583 static void return_from_sp_helper(bool panic, uint32_t panic_code, 584 struct thread_svc_regs *svc_regs) 585 { 586 struct ts_session *sess = ts_get_current_session(); 587 struct stmm_ctx *spc = to_stmm_ctx(sess->ctx); 588 589 if (panic) 590 spc->ta_ctx.panicked = true; 591 else 592 save_sp_ctx(spc, svc_regs); 593 594 SVC_REGS_A0(svc_regs) = 0; 595 SVC_REGS_A1(svc_regs) = panic; 596 SVC_REGS_A2(svc_regs) = panic_code; 597 } 598 599 static void service_compose_direct_resp(struct thread_svc_regs *regs, 600 uint32_t ret_val) 601 { 602 uint16_t src_id = 0; 603 uint16_t dst_id = 0; 604 605 /* extract from request */ 606 src_id = (SVC_REGS_A1(regs) >> 16) & UINT16_MAX; 607 dst_id = SVC_REGS_A1(regs) & UINT16_MAX; 608 609 /* compose message */ 610 SVC_REGS_A0(regs) = __FFA_MSG_SEND_DIRECT_RESP; 611 /* swap endpoint ids */ 612 SVC_REGS_A1(regs) = SHIFT_U32(dst_id, 16) | src_id; 613 SVC_REGS_A2(regs) = FFA_PARAM_MBZ; 614 SVC_REGS_A3(regs) = ret_val; 615 SVC_REGS_A4(regs) = 0; 616 SVC_REGS_A5(regs) = 0; 617 SVC_REGS_A6(regs) = 0; 618 SVC_REGS_A7(regs) = 0; 619 } 620 621 /* 622 * Combined read from secure partition, this will open, read and 623 * close the file object. 624 */ 625 static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id, 626 unsigned long obj_id_len, void *data, 627 unsigned long len, unsigned long offset, 628 unsigned long flags) 629 { 630 const struct tee_file_operations *fops = NULL; 631 TEE_Result res = TEE_ERROR_BAD_STATE; 632 struct ts_session *sess = NULL; 633 struct tee_file_handle *fh = NULL; 634 struct stmm_ctx *spc = NULL; 635 struct tee_pobj *po = NULL; 636 size_t file_size = 0; 637 size_t read_len = 0; 638 639 fops = tee_svc_storage_file_ops(storage_id); 640 if (!fops) 641 return TEE_ERROR_ITEM_NOT_FOUND; 642 643 if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) 644 return TEE_ERROR_BAD_PARAMETERS; 645 646 sess = ts_get_current_session(); 647 spc = to_stmm_ctx(sess->ctx); 648 res = vm_check_access_rights(&spc->uctx, 649 TEE_MEMORY_ACCESS_WRITE | 650 TEE_MEMORY_ACCESS_ANY_OWNER, 651 (uaddr_t)data, len); 652 if (res != TEE_SUCCESS) 653 return res; 654 655 res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, 656 false, fops, &po); 657 if (res != TEE_SUCCESS) 658 return res; 659 660 res = po->fops->open(po, &file_size, &fh); 661 if (res != TEE_SUCCESS) 662 goto out; 663 664 read_len = len; 665 res = po->fops->read(fh, offset, data, &read_len); 666 if (res == TEE_ERROR_CORRUPT_OBJECT) { 667 EMSG("Object corrupt"); 668 po->fops->remove(po); 669 } else if (res == TEE_SUCCESS && len != read_len) { 670 res = TEE_ERROR_CORRUPT_OBJECT; 671 } 672 673 po->fops->close(&fh); 674 675 out: 676 tee_pobj_release(po); 677 678 return res; 679 } 680 681 /* 682 * Combined write from secure partition, this will create/open, write and 683 * close the file object. 684 */ 685 static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id, 686 unsigned long obj_id_len, void *data, 687 unsigned long len, unsigned long offset, 688 unsigned long flags) 689 690 { 691 const struct tee_file_operations *fops = NULL; 692 struct ts_session *sess = NULL; 693 struct tee_file_handle *fh = NULL; 694 struct stmm_ctx *spc = NULL; 695 TEE_Result res = TEE_SUCCESS; 696 struct tee_pobj *po = NULL; 697 698 fops = tee_svc_storage_file_ops(storage_id); 699 if (!fops) 700 return TEE_ERROR_ITEM_NOT_FOUND; 701 702 if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) 703 return TEE_ERROR_BAD_PARAMETERS; 704 705 sess = ts_get_current_session(); 706 spc = to_stmm_ctx(sess->ctx); 707 res = vm_check_access_rights(&spc->uctx, 708 TEE_MEMORY_ACCESS_READ | 709 TEE_MEMORY_ACCESS_ANY_OWNER, 710 (uaddr_t)data, len); 711 if (res != TEE_SUCCESS) 712 return res; 713 714 res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, 715 false, fops, &po); 716 if (res != TEE_SUCCESS) 717 return res; 718 719 res = po->fops->open(po, NULL, &fh); 720 if (res == TEE_ERROR_ITEM_NOT_FOUND) 721 res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, 0, 722 &fh); 723 if (res == TEE_SUCCESS) { 724 res = po->fops->write(fh, offset, data, len); 725 po->fops->close(&fh); 726 } 727 728 tee_pobj_release(po); 729 730 return res; 731 } 732 733 static void stmm_handle_mem_mgr_service(struct thread_svc_regs *regs) 734 { 735 uint32_t action = SVC_REGS_A3(regs); 736 uintptr_t va = SVC_REGS_A4(regs); 737 uint32_t nr_pages = SVC_REGS_A5(regs); 738 uint32_t perm = SVC_REGS_A6(regs); 739 740 switch (action) { 741 case __FFA_SVC_MEMORY_ATTRIBUTES_GET: 742 service_compose_direct_resp(regs, sp_svc_get_mem_attr(va)); 743 break; 744 case __FFA_SVC_MEMORY_ATTRIBUTES_SET: 745 service_compose_direct_resp(regs, 746 sp_svc_set_mem_attr(va, nr_pages, 747 perm)); 748 break; 749 default: 750 EMSG("Undefined service id %#"PRIx32, action); 751 service_compose_direct_resp(regs, STMM_RET_INVALID_PARAM); 752 break; 753 } 754 } 755 756 static uint32_t tee2stmm_ret_val(TEE_Result res) 757 { 758 switch (res) { 759 case TEE_SUCCESS: 760 return STMM_RET_SUCCESS; 761 case TEE_ERROR_NOT_SUPPORTED: 762 return STMM_RET_NOT_SUPPORTED; 763 case TEE_ERROR_ACCESS_DENIED: 764 return STMM_RET_DENIED; 765 case TEE_ERROR_OUT_OF_MEMORY: 766 return STMM_RET_NO_MEM; 767 case TEE_ERROR_BAD_PARAMETERS: 768 default: 769 return STMM_RET_INVALID_PARAM; 770 } 771 } 772 773 #define FILENAME "EFI_VARS" 774 static void stmm_handle_storage_service(struct thread_svc_regs *regs) 775 { 776 uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | 777 TEE_DATA_FLAG_ACCESS_WRITE | 778 TEE_DATA_FLAG_SHARE_READ | 779 TEE_DATA_FLAG_SHARE_WRITE; 780 uint32_t action = SVC_REGS_A3(regs); 781 void *va = (void *)SVC_REGS_A4(regs); 782 unsigned long len = SVC_REGS_A5(regs); 783 unsigned long offset = SVC_REGS_A6(regs); 784 char obj_id[] = FILENAME; 785 size_t obj_id_len = strlen(obj_id); 786 TEE_Result res = TEE_SUCCESS; 787 uint32_t stmm_rc = STMM_RET_INVALID_PARAM; 788 789 switch (action) { 790 case __FFA_SVC_RPMB_READ: 791 DMSG("RPMB read"); 792 res = sec_storage_obj_read(TEE_STORAGE_PRIVATE_RPMB, obj_id, 793 obj_id_len, va, len, offset, flags); 794 stmm_rc = tee2stmm_ret_val(res); 795 break; 796 case __FFA_SVC_RPMB_WRITE: 797 DMSG("RPMB write"); 798 res = sec_storage_obj_write(TEE_STORAGE_PRIVATE_RPMB, obj_id, 799 obj_id_len, va, len, offset, flags); 800 stmm_rc = tee2stmm_ret_val(res); 801 break; 802 default: 803 EMSG("Undefined service id %#"PRIx32, action); 804 break; 805 } 806 807 service_compose_direct_resp(regs, stmm_rc); 808 } 809 810 static void spm_eret_error(int32_t error_code, struct thread_svc_regs *regs) 811 { 812 SVC_REGS_A0(regs) = FFA_ERROR; 813 SVC_REGS_A1(regs) = FFA_PARAM_MBZ; 814 SVC_REGS_A2(regs) = error_code; 815 SVC_REGS_A3(regs) = FFA_PARAM_MBZ; 816 SVC_REGS_A4(regs) = FFA_PARAM_MBZ; 817 SVC_REGS_A5(regs) = FFA_PARAM_MBZ; 818 SVC_REGS_A6(regs) = FFA_PARAM_MBZ; 819 SVC_REGS_A7(regs) = FFA_PARAM_MBZ; 820 } 821 822 static void spm_handle_direct_req(struct thread_svc_regs *regs) 823 { 824 uint16_t dst_id = SVC_REGS_A1(regs) & UINT16_MAX; 825 826 if (dst_id == mem_mgr_id) { 827 stmm_handle_mem_mgr_service(regs); 828 } else if (dst_id == ffa_storage_id) { 829 stmm_handle_storage_service(regs); 830 } else { 831 EMSG("Undefined endpoint id %#"PRIx16, dst_id); 832 spm_eret_error(STMM_RET_INVALID_PARAM, regs); 833 } 834 } 835 836 /* Return true if returning to SP, false if returning to caller */ 837 static bool spm_handle_svc(struct thread_svc_regs *regs) 838 { 839 #ifdef ARM64 840 uint64_t *a0 = ®s->x0; 841 #endif 842 #ifdef ARM32 843 uint32_t *a0 = ®s->r0; 844 #endif 845 846 switch (*a0) { 847 case FFA_VERSION: 848 DMSG("Received FFA version"); 849 *a0 = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); 850 return true; 851 case __FFA_MSG_SEND_DIRECT_RESP: 852 DMSG("Received FFA direct response"); 853 return_from_sp_helper(false, 0, regs); 854 return false; 855 case __FFA_MSG_SEND_DIRECT_REQ: 856 DMSG("Received FFA direct request"); 857 spm_handle_direct_req(regs); 858 return true; 859 default: 860 EMSG("Undefined syscall %#"PRIx32, (uint32_t)*a0); 861 return_from_sp_helper(true /*panic*/, 0xabcd, regs); 862 return false; 863 } 864 } 865 866 /* 867 * Note: this variable is weak just to ease breaking its dependency chain 868 * when added to the unpaged area. 869 */ 870 const struct ts_ops stmm_sp_ops __weak __rodata_unpaged("stmm_sp_ops") = { 871 .enter_open_session = stmm_enter_open_session, 872 .enter_invoke_cmd = stmm_enter_invoke_cmd, 873 .enter_close_session = stmm_enter_close_session, 874 .dump_state = stmm_dump_state, 875 .destroy = stmm_ctx_destroy, 876 .get_instance_id = stmm_get_instance_id, 877 .handle_svc = spm_handle_svc, 878 }; 879