xref: /optee_os/core/arch/arm/kernel/stmm_sp.c (revision 997ff82731597ddcf8d6ad0fb3301adca8c0c6a8)
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 = &regs->x0;
841 #endif
842 #ifdef ARM32
843 	uint32_t *a0 = &regs->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