xref: /optee_os/core/arch/arm/plat-rcar/romapi.c (revision 9f34db38245c9b3a4e6e7e63eb78a75e23ab2da3)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021, EPAM Systems
4  */
5 #include <assert.h>
6 #include <kernel/panic.h>
7 #include <mm/core_memprot.h>
8 #include <mm/core_mmu.h>
9 
10 #include "rcar.h"
11 #include "romapi.h"
12 
13 static int get_api_table_index(void)
14 {
15 	/*
16 	 * Depending on SoC type and version, there are 4 possible addresses
17 	 * for each ROMAPI function
18 	 */
19 	static int index __nex_data = -1;
20 
21 	if (index != -1)
22 		return index;
23 
24 	switch (rcar_prr_value & PRR_PRODUCT_MASK) {
25 	case PRR_PRODUCT_H3:
26 		switch (rcar_prr_value & PRR_CUT_MASK) {
27 		case PRR_CUT_10:	/* H3 ES1.0 */
28 		case PRR_CUT_11:	/* H3 ES1.1 */
29 			index = 0;
30 			break;
31 		case PRR_CUT_20:	/* H3 ES2.0 */
32 			index = 1;
33 			break;
34 		default:	/* Newer H3 versions use unified table */
35 			index = 3;
36 			break;
37 		}
38 		break;
39 	case PRR_PRODUCT_M3W:
40 		switch (rcar_prr_value & PRR_CUT_MASK) {
41 		case PRR_CUT_10:	/* M3 ES1.0 */
42 			index = 2;
43 			break;
44 		default:	/* Newer M3 versions use unified table */
45 			index = 3;
46 			break;
47 		}
48 		break;
49 	default:			/* All other SoCs use unified table */
50 		index = 3;
51 		break;
52 	}
53 
54 	return index;
55 }
56 
57 /* implemented in romapi_call.S */
58 extern uint32_t __plat_romapi_wrapper(paddr_t func, uint64_t arg1,
59 				      uint64_t arg2, uint64_t arg3);
60 
61 static uint32_t __plat_romapi_direct(paddr_t func, uint64_t arg1,
62 				     uint64_t arg2, uint64_t arg3)
63 {
64 	uint32_t (*fptr)(uint64_t arg1, uint64_t arg2, uint64_t arg3) = NULL;
65 
66 	assert(!cpu_mmu_enabled());
67 
68 	fptr = (typeof(fptr))func;
69 
70 	return fptr(arg1, arg2, arg3);
71 }
72 
73 static uint32_t plat_call_romapi(paddr_t func, uint64_t arg1,
74 				 uint64_t arg2, uint64_t arg3)
75 {
76 	uint32_t (*fptr)(paddr_t func, uint64_t arg1, uint64_t arg2,
77 			 uint64_t arg3) = NULL;
78 
79 	/*
80 	 * If MMU is enabled, we need to use trampoline function that will
81 	 * disable MMU and switch stack pointer to physical address. On other
82 	 * hand, if MMU is disabled, we can call the ROM function directly.
83 	 */
84 	if (cpu_mmu_enabled())
85 		/*
86 		 * With ASLR enabled __plat_romapi_wrapper() function will be
87 		 * mapped at two addresses: at random address (with the rest of
88 		 * OP-TEE) and at identity address. We need to map it at
89 		 * identity address and call it at identity address because this
90 		 * function turns off MMU to perform ROM API call. But
91 		 * __plat_romapi_wrapper *symbol* will be relocated by ASLR
92 		 * code. To get identity address of the function we need to use
93 		 * virt_to_phys().
94 		 */
95 		fptr = (void *)virt_to_phys(__plat_romapi_wrapper);
96 	else
97 		/*
98 		 * With MMU disabled we can call ROM code directly.
99 		 */
100 		fptr = __plat_romapi_direct;
101 
102 	return fptr(func, arg1, arg2, arg3);
103 }
104 
105 static paddr_t va2pa(void *ptr)
106 {
107 	if (cpu_mmu_enabled())
108 		return virt_to_phys(ptr);
109 	else
110 		return (paddr_t)ptr;
111 }
112 
113 static const paddr_t romapi_getrndvector[] = {
114 	0xEB10DFC4,	/* H3 1.0/1.1, needs confirmation */
115 	0xEB117134,	/* H3 2.0 */
116 	0xEB11055C,	/* M3 1.0/1.05, needs confirmation */
117 	0xEB100188,	/* H3 3.0, M3 1.1+, M3N, E3, D3, V3M 2.0 */
118 };
119 
120 uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ],
121 			       uint8_t *scratch, uint32_t scratch_sz)
122 {
123 	uint32_t ret = -1;
124 	int try = 0;
125 	paddr_t func_addr = romapi_getrndvector[get_api_table_index()];
126 	paddr_t rndbuff_pa = va2pa(rndbuff);
127 	paddr_t scratch_pa = va2pa(scratch);
128 
129 	assert(scratch_sz >= 4096);
130 	assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0);
131 	assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0);
132 
133 	while (try++ < 3) {
134 		ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa,
135 				       scratch_sz);
136 		if (ret == 0)
137 			break;
138 		IMSG("ROM_GetRndVector() returned "PRIx32, ret);
139 	}
140 
141 	/*
142 	 * ROM code is called with MMU turned off, so any accesses to rndbuff
143 	 * are not affected by data cache. This can lead to two problems:
144 	 *
145 	 * 1. Any prior writes can be cached but may not reach memory. So staled
146 	 * values can be flushed to memory later and overwrite new data written
147 	 * by ROM code. This includes stack as well.
148 	 *
149 	 * 2. ROM code will write new data to the buffer, but we may see old,
150 	 * cached values.
151 	 *
152 	 * ROM code wrapper will issue dcache_op_all(DCACHE_OP_CLEAN). This will
153 	 * ensure that all writes reached memory. After the call we need to
154 	 * invalidate the cache to see new data.
155 	 *
156 	 * We are not accessing scratch area, so no need to do cache maintenance
157 	 * for that buffer.
158 	 */
159 	cache_op_inner(DCACHE_AREA_INVALIDATE, rndbuff, PLAT_RND_VECTOR_SZ);
160 
161 	return ret;
162 }
163