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