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