xref: /rk3399_ARM-atf/services/std_svc/rmmd/trp/trp_main.c (revision 04cf04c72d403e0c057505882fac9002d39d4102)
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 	return ((x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN;
108 }
109 
110 /* Main function for TRP */
111 void trp_main(void)
112 {
113 	NOTICE("TRP: %s\n", build_version_string);
114 	NOTICE("TRP: %s\n", build_message);
115 	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
116 		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
117 	NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
118 		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
119 		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
120 	INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
121 	INFO("TRP: Shared region base address: 0x%lx\n",
122 			(unsigned long)trp_shared_region_start);
123 	INFO("TRP: Total size: 0x%lx bytes\n",
124 			(unsigned long)(RMM_END - RMM_BASE));
125 	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
126 		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
127 		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
128 }
129 
130 /*******************************************************************************
131  * Returning RMI version back to Normal World
132  ******************************************************************************/
133 static void trp_ret_rmi_version(unsigned long long rmi_version,
134 				struct trp_smc_result *smc_ret)
135 {
136 	if (rmi_version != RMI_ABI_VERSION) {
137 		smc_ret->x[0] = RMI_ERROR_INPUT;
138 	} else {
139 		smc_ret->x[0] = RMI_SUCCESS;
140 	}
141 	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
142 					  RMI_ABI_VERSION_MINOR);
143 	smc_ret->x[1] = RMI_ABI_VERSION;
144 	smc_ret->x[2] = RMI_ABI_VERSION;
145 }
146 
147 /*******************************************************************************
148  * Transitioning granule of NON-SECURE type to REALM type
149  ******************************************************************************/
150 static void trp_asc_mark_realm(unsigned long long x1,
151 				struct trp_smc_result *smc_ret)
152 {
153 	VERBOSE("Delegating granule 0x%llx\n", x1);
154 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
155 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
156 
157 	if (smc_ret->x[0] != 0ULL) {
158 		ERROR("Granule transition from NON-SECURE type to REALM type "
159 			"failed 0x%llx\n", smc_ret->x[0]);
160 	}
161 }
162 
163 /*******************************************************************************
164  * Transitioning granule of REALM type to NON-SECURE type
165  ******************************************************************************/
166 static void trp_asc_mark_nonsecure(unsigned long long x1,
167 				   struct trp_smc_result *smc_ret)
168 {
169 	VERBOSE("Undelegating granule 0x%llx\n", x1);
170 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
171 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
172 
173 	if (smc_ret->x[0] != 0ULL) {
174 		ERROR("Granule transition from REALM type to NON-SECURE type "
175 			"failed 0x%llx\n", smc_ret->x[0]);
176 	}
177 }
178 
179 /*******************************************************************************
180  * Test the IDE Key management interface
181  ******************************************************************************/
182 static void trp_ide_keymgmt_interface_fn(unsigned long long x1, unsigned long long x2,
183 					struct trp_smc_result *smc_ret)
184 {
185 	uint64_t ecam_address = 0U, rp_id = 0U, ide_stream_info;
186 	uint64_t keyqw0, keyqw1, keyqw2, keyqw3;
187 	uint64_t ifvqw0, ifvqw1;
188 	int return_value;
189 
190 #if RMMD_ENABLE_IDE_KEY_PROG
191 	trp_get_test_rootport(&ecam_address, &rp_id);
192 #endif /* RMMD_ENABLE_IDE_KEY_PROG */
193 	/*
194 	 * Dummy values for testing:
195 	 * Key set = 0x0
196 	 * Dir = 0x0
197 	 * Substream = 0x1
198 	 * Stream ID = 0x1
199 	 */
200 	ide_stream_info  = ENCODE_STREAM_INFO(KEY_SET, DIR_VAL, SUBSTREAM_VAL, STREAM_ID);
201 
202 	/* Dummy key and IV values for testing */
203 	keyqw0 = 0xA1B2C3D4E5F60708;
204 	keyqw1 = 0x1122334455667788;
205 	keyqw2 = 0xDEADBEEFCAFEBABE;
206 	keyqw3 = 0x1234567890ABCDEF;
207 	ifvqw0 = 0xABCDEF0123456789;
208 	ifvqw1 = 0x9876543210FEDCBA;
209 
210 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_PROG, ecam_address, rp_id,
211 				ide_stream_info, keyqw0, keyqw1, keyqw2, keyqw3, ifvqw0,
212 				ifvqw1, 0UL, 0UL));
213 
214 	INFO("return value from RMM_IDE_KEY_PROG = %d\n", return_value);
215 
216 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_GO, ecam_address, rp_id,
217 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
218 
219 	INFO("return value from RMM_IDE_KEY_SET_GO = %d\n", return_value);
220 
221 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_STOP, ecam_address, rp_id,
222 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
223 
224 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
225 
226 	return_value = trp_smc(set_smc_args(RMM_IDE_KM_PULL_RESPONSE, ecam_address, rp_id,
227 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
228 
229 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
230 
231 	smc_ret->x[0] = RMI_ERROR_NOT_SUPPORTED;
232 
233 }
234 
235 /*******************************************************************************
236  * Main RMI SMC handler function
237  ******************************************************************************/
238 void trp_rmi_handler(unsigned long fid,
239 		     unsigned long long x1, unsigned long long x2,
240 		     unsigned long long x3, unsigned long long x4,
241 		     unsigned long long x5, unsigned long long x6,
242 		     struct trp_smc_result *smc_ret)
243 {
244 	/* Not used in the current implementation */
245 	(void)x2;
246 	(void)x3;
247 	(void)x4;
248 	(void)x5;
249 	(void)x6;
250 
251 	switch (fid) {
252 	case RMI_RMM_REQ_VERSION:
253 		trp_ret_rmi_version(x1, smc_ret);
254 		break;
255 	case RMI_RMM_GRANULE_DELEGATE:
256 		trp_asc_mark_realm(x1, smc_ret);
257 		break;
258 	case RMI_RMM_GRANULE_UNDELEGATE:
259 		trp_asc_mark_nonsecure(x1, smc_ret);
260 		break;
261 	case RMI_RMM_PDEV_CREATE:
262 		trp_ide_keymgmt_interface_fn(x1, x2, smc_ret);
263 		break;
264 	default:
265 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
266 		smc_ret->x[0] = SMC_UNK;
267 	}
268 }
269