xref: /optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c (revision 5ab6717dfa872443e948944f0e4fb5a9017c5427)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2020, Linaro Limited
4  */
5 
6 #include <console.h>
7 #include <io.h>
8 #include <kernel/tee_misc.h>
9 #include <mm/core_memprot.h>
10 #include <sm/optee_smc.h>
11 #include <sm/sm.h>
12 
13 #include "rzn1_regauth.h"
14 
15 #define RZN1_OEM_CONSOLE_PUTC		0x01
16 #define RZN1_OEM_SYSREG_AUTH		0x10
17 
18 static const struct regauth_t regauth_pass = {.rmask = ~0U, .wmask = ~0U};
19 
get_regauth(unsigned long paddr)20 static const struct regauth_t *get_regauth(unsigned long paddr)
21 {
22 	unsigned int idx = 0;
23 	unsigned int len = ARRAY_SIZE(regauth);
24 
25 	while (idx < len) {
26 		if (core_is_buffer_inside(paddr, sizeof(uint32_t),
27 					  regauth[idx].paddr,
28 					  regauth[idx].size))
29 			return &regauth[idx];
30 		idx++;
31 	}
32 
33 	return NULL;
34 }
35 
oem_sysreg(uint32_t addr,uint32_t mask,uint32_t * pvalue)36 static uint32_t oem_sysreg(uint32_t addr, uint32_t mask, uint32_t *pvalue)
37 {
38 	vaddr_t reg = 0;
39 	const struct regauth_t *auth = get_regauth(addr);
40 
41 	/* Allow operations on registers not in the list */
42 	if (!auth)
43 		auth = &regauth_pass;
44 
45 	reg = core_mmu_get_va(addr, MEM_AREA_IO_SEC, sizeof(uint32_t));
46 
47 	if (mask) {
48 		/* Write operation */
49 		mask &= auth->wmask;
50 		if (!reg || !mask)
51 			DMSG("Blocking write of 0x%"PRIx32" to register 0x%"
52 			     PRIx32" (0x%"PRIxVA")", *pvalue, addr, reg);
53 		else if (mask == ~0UL)
54 			io_write32(reg, *pvalue);
55 		else
56 			io_mask32(reg, *pvalue, mask);
57 	} else {
58 		/* Read operation */
59 		if (!reg || !auth->rmask)
60 			DMSG("Blocking read of register 0x%"PRIx32" (0x%"
61 			     PRIxVA")", addr, reg);
62 		else
63 			*pvalue = io_read32(reg) & auth->rmask;
64 	}
65 
66 	return 0;
67 }
68 
oem_service(struct sm_ctx * ctx __unused,struct thread_smc_args * args)69 static enum sm_handler_ret oem_service(struct sm_ctx *ctx __unused,
70 				       struct thread_smc_args *args)
71 {
72 	switch (OPTEE_SMC_FUNC_NUM(args->a0)) {
73 	case RZN1_OEM_SYSREG_AUTH:
74 		args->a0 = oem_sysreg(args->a1, args->a2, &args->a3);
75 		args->a1 = args->a3;
76 		break;
77 	case RZN1_OEM_CONSOLE_PUTC:
78 		console_putc(args->a1);
79 		break;
80 	default:
81 		return SM_HANDLER_PENDING_SMC;
82 	}
83 
84 	return SM_HANDLER_SMC_HANDLED;
85 }
86 
sm_platform_handler(struct sm_ctx * ctx)87 enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx)
88 {
89 	struct thread_smc_args *args = (void *)&ctx->nsec.r0;
90 
91 	if (!OPTEE_SMC_IS_FAST_CALL(args->a0))
92 		return SM_HANDLER_PENDING_SMC;
93 
94 	switch (OPTEE_SMC_OWNER_NUM(args->a0)) {
95 	case OPTEE_SMC_OWNER_OEM:
96 		return oem_service(ctx, args);
97 	default:
98 		return SM_HANDLER_PENDING_SMC;
99 	}
100 }
101