xref: /rk3399_ARM-atf/services/std_svc/rmmd/trp/trp_main.c (revision 6e5951c70a1b887e751151a3a49d9a48afad13e9)
1 /*
2  * Copyright (c) 2021-2026, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <common/build_message.h>
7 #include <common/debug.h>
8 #include <lib/gpt_rme/gpt_rme.h>
9 #include <plat/common/platform.h>
10 #include <services/firme_svc.h>
11 #include <services/rmm_core_manifest.h>
12 #include <services/rmmd_svc.h>
13 #include <services/trp/platform_trp.h>
14 #include <trp_helpers.h>
15 #include "trp_private.h"
16 
17 #include <platform_def.h>
18 
19 #define RMI_ERROR_REALM			2U
20 #define RMI_ERROR_NOT_SUPPORTED		6U
21 
22 #define DIR_BIT_SHIFT			0x8
23 #define KEYSET_SHIFT			0xC
24 #define	STREAM_ID_MASK			0xFF
25 #define STREAM_ID_SHIFT			0x0
26 #define SUBSTREAM_MASK			0x7
27 #define SUBSTREAM_SHIFT			0x8
28 
29 #define KEY_SET				0x0
30 #define	DIR_VAL				0x0
31 #define	SUBSTREAM_VAL			0x1
32 #define	STREAM_ID			0x1
33 
34 #define ENCODE_STREAM_INFO(key, dir, substream, stream_id)			\
35 		(((key & 0x1) << KEYSET_SHIFT) |				\
36 		((dir & 0x1) << DIR_BIT_SHIFT) |				\
37 		((substream && SUBSTREAM_MASK) << SUBSTREAM_SHIFT) |		\
38 		((stream_id && STREAM_ID_MASK) << STREAM_ID_SHIFT))
39 
40 /* Parameters received from the previous image */
41 static unsigned int trp_boot_abi_version;
42 static uintptr_t trp_shared_region_start;
43 
44 /* Parameters received from boot manifest */
45 uint32_t trp_boot_manifest_version;
46 
47 /*******************************************************************************
48  * Setup function for TRP.
49  ******************************************************************************/
trp_setup(uint64_t x0,uint64_t x1,uint64_t x2,uint64_t x3)50 void trp_setup(uint64_t x0,
51 	       uint64_t x1,
52 	       uint64_t x2,
53 	       uint64_t x3)
54 {
55 	/*
56 	 * Validate boot parameters
57 	 *
58 	 * According to the Boot Interface ABI v.0.1,
59 	 * the parameters received from EL3 are:
60 	 * x0: CPUID (verified earlier, so not used)
61 	 * x1: Boot Interface version
62 	 * x2: PLATFORM_CORE_COUNT
63 	 * x3: Pointer to the shared memory area.
64 	 */
65 
66 	(void)x0;
67 
68 	if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
69 		trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
70 	}
71 
72 	if ((void *)x3 == NULL) {
73 		trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
74 	}
75 
76 	if (x2 > TRP_PLATFORM_CORE_COUNT) {
77 		trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
78 	}
79 
80 	trp_boot_abi_version = x1;
81 	trp_shared_region_start = x3;
82 	flush_dcache_range((uintptr_t)&trp_boot_abi_version,
83 			   sizeof(trp_boot_abi_version));
84 	flush_dcache_range((uintptr_t)&trp_shared_region_start,
85 			   sizeof(trp_shared_region_start));
86 
87 	/* Perform early platform-specific setup */
88 	trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start);
89 }
90 
trp_validate_warmboot_args(uint64_t x0,uint64_t x1,uint64_t x2,uint64_t x3)91 int trp_validate_warmboot_args(uint64_t x0, uint64_t x1,
92 			       uint64_t x2, uint64_t x3)
93 {
94 	/*
95 	 * Validate boot parameters for warm boot
96 	 *
97 	 * According to the Boot Interface ABI v.0.1, the parameters
98 	 * received from EL3 during warm boot are:
99 	 *
100 	 * x0: CPUID (verified earlier so not used here)
101 	 * x1: activation token (ignored)
102 	 * [x2:x3]: RES0
103 	 */
104 
105 	(void)x0;
106 	(void)x1;
107 
108 	if ((x2 | x3) != 0UL) {
109 		ERROR("TRP: extra warmboot arguments not 0: x2=0x%lx, x3=0x%lx\n",
110 		     x2, x3);
111 		return E_RMM_BOOT_UNKNOWN;
112 	}
113 
114 	return 0;
115 }
116 
117 /* Main function for TRP */
trp_main(void)118 void trp_main(void)
119 {
120 	NOTICE("TRP: %s\n", build_version_string);
121 	NOTICE("TRP: %s\n", build_message);
122 	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
123 		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
124 	NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
125 		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
126 		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
127 	INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
128 	INFO("TRP: Shared region base address: 0x%lx\n",
129 			(unsigned long)trp_shared_region_start);
130 	INFO("TRP: Total size: 0x%lx bytes\n",
131 			(unsigned long)(RMM_END - RMM_BASE));
132 	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
133 		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
134 		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
135 }
136 
137 /*******************************************************************************
138  * Returning RMI version back to Normal World
139  ******************************************************************************/
trp_ret_rmi_version(unsigned long long rmi_version,struct trp_smc_result * smc_ret)140 static void trp_ret_rmi_version(unsigned long long rmi_version,
141 				struct trp_smc_result *smc_ret)
142 {
143 	if (rmi_version != RMI_ABI_VERSION) {
144 		smc_ret->x[0] = RMI_ERROR_INPUT;
145 	} else {
146 		smc_ret->x[0] = RMI_SUCCESS;
147 	}
148 	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
149 					  RMI_ABI_VERSION_MINOR);
150 	smc_ret->x[1] = RMI_ABI_VERSION;
151 	smc_ret->x[2] = RMI_ABI_VERSION;
152 }
153 
154 /*******************************************************************************
155  * Transitioning granule of NON-SECURE type to REALM type
156  ******************************************************************************/
trp_asc_mark_realm(unsigned long long x1,struct trp_smc_result * smc_ret)157 static void trp_asc_mark_realm(unsigned long long x1,
158 				struct trp_smc_result *smc_ret)
159 {
160 	VERBOSE("Delegating granule 0x%llx\n", x1);
161 
162 #if FIRME_SUPPORT
163 	smc_ret->x[0] = trp_smc(set_smc_args(FIRME_GM_GPI_SET_FID, x1, 1UL,
164 					     GPT_GPI_REALM, 0UL, 0UL, 0UL, 0UL,
165 					     0UL, 0UL, 0UL, 0UL));
166 #else
167 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
168 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
169 #endif
170 
171 	if (smc_ret->x[0] != 0ULL) {
172 		ERROR("Granule transition from NON-SECURE type to REALM type "
173 			"failed 0x%llx\n", smc_ret->x[0]);
174 
175 		/*
176 		 * x[1] is not a return parameter for GRANULE_DELEGATE,
177 		 * but populating it is harmless and simplifies the implementation.
178 		 */
179 		smc_ret->x[1] = x1;
180 		return;
181 	}
182 	smc_ret->x[1] = x1 + PAGE_SIZE_4KB;
183 }
184 
185 /*******************************************************************************
186  * Transitioning granule of REALM type to NON-SECURE type
187  ******************************************************************************/
trp_asc_mark_nonsecure(unsigned long long x1,struct trp_smc_result * smc_ret)188 static void trp_asc_mark_nonsecure(unsigned long long x1,
189 				   struct trp_smc_result *smc_ret)
190 {
191 	VERBOSE("Undelegating granule 0x%llx\n", x1);
192 
193 #if FIRME_SUPPORT
194 	smc_ret->x[0] =
195 		trp_smc(set_smc_args(FIRME_GM_GPI_SET_FID, x1, 1UL, GPT_GPI_NS,
196 				     0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
197 #else
198 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
199 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
200 #endif
201 
202 	if (smc_ret->x[0] != 0ULL) {
203 		ERROR("Granule transition from REALM type to NON-SECURE type "
204 			"failed 0x%llx\n", smc_ret->x[0]);
205 
206 		/*
207 		 * x[1] is not a return parameter for GRANULE_UNDELEGATE,
208 		 * but populating it is harmless and simplifies the implementation.
209 		 */
210 		smc_ret->x[1] = x1;
211 		return;
212 	}
213 	smc_ret->x[1] = x1 + PAGE_SIZE_4KB;
214 }
215 
216 /*******************************************************************************
217  * Test the IDE Key management interface
218  ******************************************************************************/
trp_ide_keymgmt_interface_fn(unsigned long long x1,unsigned long long x2,struct trp_smc_result * smc_ret)219 static void trp_ide_keymgmt_interface_fn(unsigned long long x1, unsigned long long x2,
220 					struct trp_smc_result *smc_ret)
221 {
222 	uint64_t ecam_address = 0U, rp_id = 0U, ide_stream_info;
223 	uint64_t keyqw0, keyqw1, keyqw2, keyqw3;
224 	uint64_t ifvqw0, ifvqw1;
225 	int return_value;
226 
227 #if RMMD_ENABLE_IDE_KEY_PROG
228 	trp_get_test_rootport(&ecam_address, &rp_id);
229 #endif /* RMMD_ENABLE_IDE_KEY_PROG */
230 	/*
231 	 * Dummy values for testing:
232 	 * Key set = 0x0
233 	 * Dir = 0x0
234 	 * Substream = 0x1
235 	 * Stream ID = 0x1
236 	 */
237 	ide_stream_info  = ENCODE_STREAM_INFO(KEY_SET, DIR_VAL, SUBSTREAM_VAL, STREAM_ID);
238 
239 	/* Dummy key and IV values for testing */
240 	keyqw0 = 0xA1B2C3D4E5F60708;
241 	keyqw1 = 0x1122334455667788;
242 	keyqw2 = 0xDEADBEEFCAFEBABE;
243 	keyqw3 = 0x1234567890ABCDEF;
244 	ifvqw0 = 0xABCDEF0123456789;
245 	ifvqw1 = 0x9876543210FEDCBA;
246 
247 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_PROG, ecam_address, rp_id,
248 				ide_stream_info, keyqw0, keyqw1, keyqw2, keyqw3, ifvqw0,
249 				ifvqw1, 0UL, 0UL));
250 
251 	INFO("return value from RMM_IDE_KEY_PROG = %d\n", return_value);
252 
253 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_GO, ecam_address, rp_id,
254 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
255 
256 	INFO("return value from RMM_IDE_KEY_SET_GO = %d\n", return_value);
257 
258 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_STOP, ecam_address, rp_id,
259 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
260 
261 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
262 
263 	return_value = trp_smc(set_smc_args(RMM_IDE_KM_PULL_RESPONSE, ecam_address, rp_id,
264 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
265 
266 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
267 
268 	smc_ret->x[0] = RMI_ERROR_NOT_SUPPORTED;
269 
270 }
271 
272 /*******************************************************************************
273  * Main RMI SMC handler function
274  ******************************************************************************/
trp_rmi_handler(unsigned long fid,unsigned long long x1,unsigned long long x2,unsigned long long x3,unsigned long long x4,unsigned long long x5,unsigned long long x6,unsigned long long x7,struct trp_smc_result * smc_ret)275 void trp_rmi_handler(unsigned long fid,
276 		     unsigned long long x1, unsigned long long x2,
277 		     unsigned long long x3, unsigned long long x4,
278 		     unsigned long long x5, unsigned long long x6,
279 		     unsigned long long x7,
280 		     struct trp_smc_result *smc_ret)
281 {
282 	/* Not used in the current implementation */
283 	(void)x2;
284 	(void)x3;
285 	(void)x4;
286 	(void)x5;
287 	(void)x6;
288 	(void)x7;
289 
290 	switch (fid) {
291 	case RMI_RMM_REQ_VERSION:
292 		trp_ret_rmi_version(x1, smc_ret);
293 		break;
294 	case RMI_RMM_ACTIVATE:
295 		smc_ret->x[0] = RMI_SUCCESS;
296 		break;
297 	case RMI_RMM_GRANULE_DELEGATE:
298 		trp_asc_mark_realm(x1, smc_ret);
299 		break;
300 	case RMI_RMM_GRANULE_UNDELEGATE:
301 		trp_asc_mark_nonsecure(x1, smc_ret);
302 		break;
303 	case RMI_RMM_GRANULE_RANGE_DELEGATE:
304 		trp_asc_mark_realm(x1, smc_ret);
305 		break;
306 	case RMI_RMM_GRANULE_RANGE_UNDELEGATE:
307 		trp_asc_mark_nonsecure(x1, smc_ret);
308 		break;
309 	case RMI_RMM_PDEV_CREATE:
310 		trp_ide_keymgmt_interface_fn(x1, x2, smc_ret);
311 		break;
312 	case RMI_RMM_CONFIG_SET:
313 	case RMI_RMM_CONFIG_GET:
314 		smc_ret->x[0] = RMI_SUCCESS;
315 		break;
316 	default:
317 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
318 		smc_ret->x[0] = SMC_UNK;
319 	}
320 }
321