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