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 = &regs->x0;
842 #endif
843 #ifdef ARM32
844 	uint32_t *a0 = &regs->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