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 
get_api_table_index(void)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 
__plat_romapi_direct(paddr_t func,uint64_t arg1,uint64_t arg2,uint64_t arg3)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 
plat_call_romapi(paddr_t func,uint64_t arg1,uint64_t arg2,uint64_t arg3)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 
va2pa(void * ptr)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 
plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ],uint8_t * scratch,uint32_t scratch_sz)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 	paddr_t func_addr = romapi_getrndvector[get_api_table_index()];
125 	paddr_t rndbuff_pa = va2pa(rndbuff);
126 	paddr_t scratch_pa = va2pa(scratch);
127 
128 	assert(scratch_sz >= 4096);
129 	assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0);
130 	assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0);
131 
132 	ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, scratch_sz);
133 
134 	/*
135 	 * ROM code is called with MMU turned off, so any accesses to rndbuff
136 	 * are not affected by data cache. This can lead to two problems:
137 	 *
138 	 * 1. Any prior writes can be cached but may not reach memory. So staled
139 	 * values can be flushed to memory later and overwrite new data written
140 	 * by ROM code. This includes stack as well.
141 	 *
142 	 * 2. ROM code will write new data to the buffer, but we may see old,
143 	 * cached values.
144 	 *
145 	 * ROM code wrapper will issue dcache_op_all(DCACHE_OP_CLEAN). This will
146 	 * ensure that all writes reached memory. After the call we need to
147 	 * invalidate the cache to see new data.
148 	 *
149 	 * We are not accessing scratch area, so no need to do cache maintenance
150 	 * for that buffer.
151 	 */
152 	cache_op_inner(DCACHE_AREA_INVALIDATE, rndbuff, PLAT_RND_VECTOR_SZ);
153 
154 	return ret;
155 }
156