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