xref: /rk3399_ARM-atf/services/std_svc/rmmd/trp/trp_main.c (revision 8b3a89faddca3a955324adc4b48c864781e4c802)
150a3056aSZelalem Aweke /*
2*8b3a89faSSona Mathew  * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
350a3056aSZelalem Aweke  *
450a3056aSZelalem Aweke  * SPDX-License-Identifier: BSD-3-Clause
550a3056aSZelalem Aweke  */
650a3056aSZelalem Aweke 
7758ccb80SChris Kay #include <common/build_message.h>
850a3056aSZelalem Aweke #include <common/debug.h>
950a3056aSZelalem Aweke #include <plat/common/platform.h>
101d0ca40eSJavier Almansa Sobrino #include <services/rmm_core_manifest.h>
11319fb084SSoby Mathew #include <services/rmmd_svc.h>
1250a3056aSZelalem Aweke #include <services/trp/platform_trp.h>
131d0ca40eSJavier Almansa Sobrino #include <trp_helpers.h>
141d0ca40eSJavier Almansa Sobrino #include "trp_private.h"
1550a3056aSZelalem Aweke 
1650a3056aSZelalem Aweke #include <platform_def.h>
1750a3056aSZelalem Aweke 
18*8b3a89faSSona Mathew #define RMI_ERROR_REALM			2U
19*8b3a89faSSona Mathew #define RMI_ERROR_NOT_SUPPORTED		6U
20*8b3a89faSSona Mathew 
21*8b3a89faSSona Mathew #define DIR_BIT_SHIFT			0x8
22*8b3a89faSSona Mathew #define KEYSET_SHIFT			0xC
23*8b3a89faSSona Mathew #define	STREAM_ID_MASK			0xFF
24*8b3a89faSSona Mathew #define STREAM_ID_SHIFT			0x0
25*8b3a89faSSona Mathew #define SUBSTREAM_MASK			0x7
26*8b3a89faSSona Mathew #define SUBSTREAM_SHIFT			0x8
27*8b3a89faSSona Mathew 
28*8b3a89faSSona Mathew #define KEY_SET				0x0
29*8b3a89faSSona Mathew #define	DIR_VAL				0x0
30*8b3a89faSSona Mathew #define	SUBSTREAM_VAL			0x1
31*8b3a89faSSona Mathew #define	STREAM_ID			0x1
32*8b3a89faSSona Mathew 
33*8b3a89faSSona Mathew #define ENCODE_STREAM_INFO(key, dir, substream, stream_id)			\
34*8b3a89faSSona Mathew 		(((key & 0x1) << KEYSET_SHIFT) |				\
35*8b3a89faSSona Mathew 		((dir & 0x1) << DIR_BIT_SHIFT) |				\
36*8b3a89faSSona Mathew 		((substream && SUBSTREAM_MASK) << SUBSTREAM_SHIFT) |		\
37*8b3a89faSSona Mathew 		((stream_id && STREAM_ID_MASK) << STREAM_ID_SHIFT))
38*8b3a89faSSona Mathew 
398c980a4aSJavier Almansa Sobrino /* Parameters received from the previous image */
408c980a4aSJavier Almansa Sobrino static unsigned int trp_boot_abi_version;
418c980a4aSJavier Almansa Sobrino static uintptr_t trp_shared_region_start;
428c980a4aSJavier Almansa Sobrino 
431d0ca40eSJavier Almansa Sobrino /* Parameters received from boot manifest */
441d0ca40eSJavier Almansa Sobrino uint32_t trp_boot_manifest_version;
458c980a4aSJavier Almansa Sobrino 
4650a3056aSZelalem Aweke /*******************************************************************************
4750a3056aSZelalem Aweke  * Setup function for TRP.
4850a3056aSZelalem Aweke  ******************************************************************************/
498c980a4aSJavier Almansa Sobrino void trp_setup(uint64_t x0,
508c980a4aSJavier Almansa Sobrino 	       uint64_t x1,
518c980a4aSJavier Almansa Sobrino 	       uint64_t x2,
528c980a4aSJavier Almansa Sobrino 	       uint64_t x3)
5350a3056aSZelalem Aweke {
548c980a4aSJavier Almansa Sobrino 	/*
55b96253dbSAlexeiFedorov 	 * Validate boot parameters
568c980a4aSJavier Almansa Sobrino 	 *
57b96253dbSAlexeiFedorov 	 * According to the Boot Interface ABI v.0.1,
58b96253dbSAlexeiFedorov 	 * the parameters received from EL3 are:
59b96253dbSAlexeiFedorov 	 * x0: CPUID (verified earlier, so not used)
608c980a4aSJavier Almansa Sobrino 	 * x1: Boot Interface version
618c980a4aSJavier Almansa Sobrino 	 * x2: PLATFORM_CORE_COUNT
628c980a4aSJavier Almansa Sobrino 	 * x3: Pointer to the shared memory area.
638c980a4aSJavier Almansa Sobrino 	 */
648c980a4aSJavier Almansa Sobrino 
658c980a4aSJavier Almansa Sobrino 	(void)x0;
668c980a4aSJavier Almansa Sobrino 
678c980a4aSJavier Almansa Sobrino 	if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
688c980a4aSJavier Almansa Sobrino 		trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
698c980a4aSJavier Almansa Sobrino 	}
708c980a4aSJavier Almansa Sobrino 
718c980a4aSJavier Almansa Sobrino 	if ((void *)x3 == NULL) {
728c980a4aSJavier Almansa Sobrino 		trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
738c980a4aSJavier Almansa Sobrino 	}
748c980a4aSJavier Almansa Sobrino 
758c980a4aSJavier Almansa Sobrino 	if (x2 > TRP_PLATFORM_CORE_COUNT) {
768c980a4aSJavier Almansa Sobrino 		trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
778c980a4aSJavier Almansa Sobrino 	}
788c980a4aSJavier Almansa Sobrino 
798c980a4aSJavier Almansa Sobrino 	trp_boot_abi_version = x1;
808c980a4aSJavier Almansa Sobrino 	trp_shared_region_start = x3;
818c980a4aSJavier Almansa Sobrino 	flush_dcache_range((uintptr_t)&trp_boot_abi_version,
828c980a4aSJavier Almansa Sobrino 			   sizeof(trp_boot_abi_version));
838c980a4aSJavier Almansa Sobrino 	flush_dcache_range((uintptr_t)&trp_shared_region_start,
848c980a4aSJavier Almansa Sobrino 			   sizeof(trp_shared_region_start));
858c980a4aSJavier Almansa Sobrino 
8650a3056aSZelalem Aweke 	/* Perform early platform-specific setup */
87a97bfa5fSAlexeiFedorov 	trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start);
8850a3056aSZelalem Aweke }
8950a3056aSZelalem Aweke 
90dc0ca64eSJavier Almansa Sobrino int trp_validate_warmboot_args(uint64_t x0, uint64_t x1,
91dc0ca64eSJavier Almansa Sobrino 			       uint64_t x2, uint64_t x3)
92dc0ca64eSJavier Almansa Sobrino {
93dc0ca64eSJavier Almansa Sobrino 	/*
94dc0ca64eSJavier Almansa Sobrino 	 * Validate boot parameters for warm boot
95dc0ca64eSJavier Almansa Sobrino 	 *
96dc0ca64eSJavier Almansa Sobrino 	 * According to the Boot Interface ABI v.0.1, the parameters
97dc0ca64eSJavier Almansa Sobrino 	 * received from EL3 during warm boot are:
98dc0ca64eSJavier Almansa Sobrino 	 *
99dc0ca64eSJavier Almansa Sobrino 	 * x0: CPUID (verified earlier so not used here)
100dc0ca64eSJavier Almansa Sobrino 	 * [x1:x3]: RES0
101dc0ca64eSJavier Almansa Sobrino 	 */
102dc0ca64eSJavier Almansa Sobrino 
103dc0ca64eSJavier Almansa Sobrino 	(void)x0;
104dc0ca64eSJavier Almansa Sobrino 
105dc0ca64eSJavier Almansa Sobrino 	return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN;
106dc0ca64eSJavier Almansa Sobrino }
107dc0ca64eSJavier Almansa Sobrino 
10850a3056aSZelalem Aweke /* Main function for TRP */
10950a3056aSZelalem Aweke void trp_main(void)
11050a3056aSZelalem Aweke {
111758ccb80SChris Kay 	NOTICE("TRP: %s\n", build_version_string);
11250a3056aSZelalem Aweke 	NOTICE("TRP: %s\n", build_message);
1138c980a4aSJavier Almansa Sobrino 	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
1148c980a4aSJavier Almansa Sobrino 		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
1151d0ca40eSJavier Almansa Sobrino 	NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
1161d0ca40eSJavier Almansa Sobrino 		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
1171d0ca40eSJavier Almansa Sobrino 		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
11850a3056aSZelalem Aweke 	INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
119b96253dbSAlexeiFedorov 	INFO("TRP: Shared region base address: 0x%lx\n",
1208c980a4aSJavier Almansa Sobrino 			(unsigned long)trp_shared_region_start);
121b96253dbSAlexeiFedorov 	INFO("TRP: Total size: 0x%lx bytes\n",
122b96253dbSAlexeiFedorov 			(unsigned long)(RMM_END - RMM_BASE));
1238c980a4aSJavier Almansa Sobrino 	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
1248c980a4aSJavier Almansa Sobrino 		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
1258c980a4aSJavier Almansa Sobrino 		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
12650a3056aSZelalem Aweke }
12750a3056aSZelalem Aweke 
12850a3056aSZelalem Aweke /*******************************************************************************
12950a3056aSZelalem Aweke  * Returning RMI version back to Normal World
13050a3056aSZelalem Aweke  ******************************************************************************/
131ade6000fSShruti Gupta static void trp_ret_rmi_version(unsigned long long rmi_version,
132ade6000fSShruti Gupta 				struct trp_smc_result *smc_ret)
13350a3056aSZelalem Aweke {
134ade6000fSShruti Gupta 	if (rmi_version != RMI_ABI_VERSION) {
135ade6000fSShruti Gupta 		smc_ret->x[0] = RMI_ERROR_INPUT;
136ade6000fSShruti Gupta 	} else {
137ade6000fSShruti Gupta 		smc_ret->x[0] = RMI_SUCCESS;
138ade6000fSShruti Gupta 	}
13950a3056aSZelalem Aweke 	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
14050a3056aSZelalem Aweke 					  RMI_ABI_VERSION_MINOR);
141ade6000fSShruti Gupta 	smc_ret->x[1] = RMI_ABI_VERSION;
142ade6000fSShruti Gupta 	smc_ret->x[2] = RMI_ABI_VERSION;
14350a3056aSZelalem Aweke }
14450a3056aSZelalem Aweke 
14550a3056aSZelalem Aweke /*******************************************************************************
14650a3056aSZelalem Aweke  * Transitioning granule of NON-SECURE type to REALM type
14750a3056aSZelalem Aweke  ******************************************************************************/
148b96253dbSAlexeiFedorov static void trp_asc_mark_realm(unsigned long long x1,
149b96253dbSAlexeiFedorov 				struct trp_smc_result *smc_ret)
15050a3056aSZelalem Aweke {
15150a3056aSZelalem Aweke 	VERBOSE("Delegating granule 0x%llx\n", x1);
152b96253dbSAlexeiFedorov 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
153*8b3a89faSSona Mathew 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
15450a3056aSZelalem Aweke 
155b96253dbSAlexeiFedorov 	if (smc_ret->x[0] != 0ULL) {
15650a3056aSZelalem Aweke 		ERROR("Granule transition from NON-SECURE type to REALM type "
157b96253dbSAlexeiFedorov 			"failed 0x%llx\n", smc_ret->x[0]);
15850a3056aSZelalem Aweke 	}
15950a3056aSZelalem Aweke }
16050a3056aSZelalem Aweke 
16150a3056aSZelalem Aweke /*******************************************************************************
16250a3056aSZelalem Aweke  * Transitioning granule of REALM type to NON-SECURE type
16350a3056aSZelalem Aweke  ******************************************************************************/
164b96253dbSAlexeiFedorov static void trp_asc_mark_nonsecure(unsigned long long x1,
165b96253dbSAlexeiFedorov 				   struct trp_smc_result *smc_ret)
16650a3056aSZelalem Aweke {
16750a3056aSZelalem Aweke 	VERBOSE("Undelegating granule 0x%llx\n", x1);
168b96253dbSAlexeiFedorov 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
169*8b3a89faSSona Mathew 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
17050a3056aSZelalem Aweke 
171b96253dbSAlexeiFedorov 	if (smc_ret->x[0] != 0ULL) {
17250a3056aSZelalem Aweke 		ERROR("Granule transition from REALM type to NON-SECURE type "
173b96253dbSAlexeiFedorov 			"failed 0x%llx\n", smc_ret->x[0]);
17450a3056aSZelalem Aweke 	}
17550a3056aSZelalem Aweke }
17650a3056aSZelalem Aweke 
17750a3056aSZelalem Aweke /*******************************************************************************
178*8b3a89faSSona Mathew  * Test the IDE Key management interface
179*8b3a89faSSona Mathew  ******************************************************************************/
180*8b3a89faSSona Mathew static void trp_ide_keymgmt_interface_fn(unsigned long long x1, unsigned long long x2,
181*8b3a89faSSona Mathew 					struct trp_smc_result *smc_ret)
182*8b3a89faSSona Mathew {
183*8b3a89faSSona Mathew 	uint64_t ecam_address = 0U, rp_id = 0U, ide_stream_info;
184*8b3a89faSSona Mathew 	uint64_t keyqw0, keyqw1, keyqw2, keyqw3;
185*8b3a89faSSona Mathew 	uint64_t ifvqw0, ifvqw1;
186*8b3a89faSSona Mathew 	int return_value;
187*8b3a89faSSona Mathew 
188*8b3a89faSSona Mathew #if RMMD_ENABLE_IDE_KEY_PROG
189*8b3a89faSSona Mathew 	trp_get_test_rootport(&ecam_address, &rp_id);
190*8b3a89faSSona Mathew #endif /* RMMD_ENABLE_IDE_KEY_PROG */
191*8b3a89faSSona Mathew 	/*
192*8b3a89faSSona Mathew 	 * Dummy values for testing:
193*8b3a89faSSona Mathew 	 * Key set = 0x0
194*8b3a89faSSona Mathew 	 * Dir = 0x0
195*8b3a89faSSona Mathew 	 * Substream = 0x1
196*8b3a89faSSona Mathew 	 * Stream ID = 0x1
197*8b3a89faSSona Mathew 	 */
198*8b3a89faSSona Mathew 	ide_stream_info  = ENCODE_STREAM_INFO(KEY_SET, DIR_VAL, SUBSTREAM_VAL, STREAM_ID);
199*8b3a89faSSona Mathew 
200*8b3a89faSSona Mathew 	/* Dummy key and IV values for testing */
201*8b3a89faSSona Mathew 	keyqw0 = 0xA1B2C3D4E5F60708;
202*8b3a89faSSona Mathew 	keyqw1 = 0x1122334455667788;
203*8b3a89faSSona Mathew 	keyqw2 = 0xDEADBEEFCAFEBABE;
204*8b3a89faSSona Mathew 	keyqw3 = 0x1234567890ABCDEF;
205*8b3a89faSSona Mathew 	ifvqw0 = 0xABCDEF0123456789;
206*8b3a89faSSona Mathew 	ifvqw1 = 0x9876543210FEDCBA;
207*8b3a89faSSona Mathew 
208*8b3a89faSSona Mathew 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_PROG, ecam_address, rp_id,
209*8b3a89faSSona Mathew 				ide_stream_info, keyqw0, keyqw1, keyqw2, keyqw3, ifvqw0,
210*8b3a89faSSona Mathew 				ifvqw1, 0UL, 0UL));
211*8b3a89faSSona Mathew 
212*8b3a89faSSona Mathew 	INFO("return value from RMM_IDE_KEY_PROG = %d\n", return_value);
213*8b3a89faSSona Mathew 
214*8b3a89faSSona Mathew 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_GO, ecam_address, rp_id,
215*8b3a89faSSona Mathew 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
216*8b3a89faSSona Mathew 
217*8b3a89faSSona Mathew 	INFO("return value from RMM_IDE_KEY_SET_GO = %d\n", return_value);
218*8b3a89faSSona Mathew 
219*8b3a89faSSona Mathew 	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_STOP, ecam_address, rp_id,
220*8b3a89faSSona Mathew 				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
221*8b3a89faSSona Mathew 
222*8b3a89faSSona Mathew 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
223*8b3a89faSSona Mathew 
224*8b3a89faSSona Mathew 	return_value = trp_smc(set_smc_args(RMM_IDE_KM_PULL_RESPONSE, ecam_address, rp_id,
225*8b3a89faSSona Mathew 				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
226*8b3a89faSSona Mathew 
227*8b3a89faSSona Mathew 	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
228*8b3a89faSSona Mathew 
229*8b3a89faSSona Mathew 	smc_ret->x[0] = RMI_ERROR_NOT_SUPPORTED;
230*8b3a89faSSona Mathew 
231*8b3a89faSSona Mathew }
232*8b3a89faSSona Mathew 
233*8b3a89faSSona Mathew /*******************************************************************************
23450a3056aSZelalem Aweke  * Main RMI SMC handler function
23550a3056aSZelalem Aweke  ******************************************************************************/
236b96253dbSAlexeiFedorov void trp_rmi_handler(unsigned long fid,
237b96253dbSAlexeiFedorov 		     unsigned long long x1, unsigned long long x2,
238b96253dbSAlexeiFedorov 		     unsigned long long x3, unsigned long long x4,
239b96253dbSAlexeiFedorov 		     unsigned long long x5, unsigned long long x6,
240b96253dbSAlexeiFedorov 		     struct trp_smc_result *smc_ret)
24150a3056aSZelalem Aweke {
242b96253dbSAlexeiFedorov 	/* Not used in the current implementation */
243b96253dbSAlexeiFedorov 	(void)x2;
244b96253dbSAlexeiFedorov 	(void)x3;
245b96253dbSAlexeiFedorov 	(void)x4;
246b96253dbSAlexeiFedorov 	(void)x5;
247b96253dbSAlexeiFedorov 	(void)x6;
248b96253dbSAlexeiFedorov 
24950a3056aSZelalem Aweke 	switch (fid) {
25050a3056aSZelalem Aweke 	case RMI_RMM_REQ_VERSION:
251ade6000fSShruti Gupta 		trp_ret_rmi_version(x1, smc_ret);
252b96253dbSAlexeiFedorov 		break;
25350a3056aSZelalem Aweke 	case RMI_RMM_GRANULE_DELEGATE:
254b96253dbSAlexeiFedorov 		trp_asc_mark_realm(x1, smc_ret);
255b96253dbSAlexeiFedorov 		break;
25650a3056aSZelalem Aweke 	case RMI_RMM_GRANULE_UNDELEGATE:
257b96253dbSAlexeiFedorov 		trp_asc_mark_nonsecure(x1, smc_ret);
258b96253dbSAlexeiFedorov 		break;
259*8b3a89faSSona Mathew 	case RMI_RMM_PDEV_CREATE:
260*8b3a89faSSona Mathew 		trp_ide_keymgmt_interface_fn(x1, x2, smc_ret);
261*8b3a89faSSona Mathew 		break;
26250a3056aSZelalem Aweke 	default:
263b96253dbSAlexeiFedorov 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
264b96253dbSAlexeiFedorov 		smc_ret->x[0] = SMC_UNK;
26550a3056aSZelalem Aweke 	}
26650a3056aSZelalem Aweke }
267