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