• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024, 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 /* Parameters received from the previous image */
19 static unsigned int trp_boot_abi_version;
20 static uintptr_t trp_shared_region_start;
21 
22 /* Parameters received from boot manifest */
23 uint32_t trp_boot_manifest_version;
24 
25 /*******************************************************************************
26  * Setup function for TRP.
27  ******************************************************************************/
trp_setup(uint64_t x0,uint64_t x1,uint64_t x2,uint64_t x3)28 void trp_setup(uint64_t x0,
29 	       uint64_t x1,
30 	       uint64_t x2,
31 	       uint64_t x3)
32 {
33 	/*
34 	 * Validate boot parameters
35 	 *
36 	 * According to the Boot Interface ABI v.0.1,
37 	 * the parameters received from EL3 are:
38 	 * x0: CPUID (verified earlier, so not used)
39 	 * x1: Boot Interface version
40 	 * x2: PLATFORM_CORE_COUNT
41 	 * x3: Pointer to the shared memory area.
42 	 */
43 
44 	(void)x0;
45 
46 	if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
47 		trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
48 	}
49 
50 	if ((void *)x3 == NULL) {
51 		trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
52 	}
53 
54 	if (x2 > TRP_PLATFORM_CORE_COUNT) {
55 		trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
56 	}
57 
58 	trp_boot_abi_version = x1;
59 	trp_shared_region_start = x3;
60 	flush_dcache_range((uintptr_t)&trp_boot_abi_version,
61 			   sizeof(trp_boot_abi_version));
62 	flush_dcache_range((uintptr_t)&trp_shared_region_start,
63 			   sizeof(trp_shared_region_start));
64 
65 	/* Perform early platform-specific setup */
66 	trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start);
67 }
68 
trp_validate_warmboot_args(uint64_t x0,uint64_t x1,uint64_t x2,uint64_t x3)69 int trp_validate_warmboot_args(uint64_t x0, uint64_t x1,
70 			       uint64_t x2, uint64_t x3)
71 {
72 	/*
73 	 * Validate boot parameters for warm boot
74 	 *
75 	 * According to the Boot Interface ABI v.0.1, the parameters
76 	 * received from EL3 during warm boot are:
77 	 *
78 	 * x0: CPUID (verified earlier so not used here)
79 	 * [x1:x3]: RES0
80 	 */
81 
82 	(void)x0;
83 
84 	return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN;
85 }
86 
87 /* Main function for TRP */
trp_main(void)88 void trp_main(void)
89 {
90 	NOTICE("TRP: %s\n", build_version_string);
91 	NOTICE("TRP: %s\n", build_message);
92 	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
93 		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
94 	NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
95 		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
96 		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
97 	INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
98 	INFO("TRP: Shared region base address: 0x%lx\n",
99 			(unsigned long)trp_shared_region_start);
100 	INFO("TRP: Total size: 0x%lx bytes\n",
101 			(unsigned long)(RMM_END - RMM_BASE));
102 	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
103 		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
104 		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
105 }
106 
107 /*******************************************************************************
108  * Returning RMI version back to Normal World
109  ******************************************************************************/
trp_ret_rmi_version(unsigned long long rmi_version,struct trp_smc_result * smc_ret)110 static void trp_ret_rmi_version(unsigned long long rmi_version,
111 				struct trp_smc_result *smc_ret)
112 {
113 	if (rmi_version != RMI_ABI_VERSION) {
114 		smc_ret->x[0] = RMI_ERROR_INPUT;
115 	} else {
116 		smc_ret->x[0] = RMI_SUCCESS;
117 	}
118 	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
119 					  RMI_ABI_VERSION_MINOR);
120 	smc_ret->x[1] = RMI_ABI_VERSION;
121 	smc_ret->x[2] = RMI_ABI_VERSION;
122 }
123 
124 /*******************************************************************************
125  * Transitioning granule of NON-SECURE type to REALM type
126  ******************************************************************************/
trp_asc_mark_realm(unsigned long long x1,struct trp_smc_result * smc_ret)127 static void trp_asc_mark_realm(unsigned long long x1,
128 				struct trp_smc_result *smc_ret)
129 {
130 	VERBOSE("Delegating granule 0x%llx\n", x1);
131 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
132 						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
133 
134 	if (smc_ret->x[0] != 0ULL) {
135 		ERROR("Granule transition from NON-SECURE type to REALM type "
136 			"failed 0x%llx\n", smc_ret->x[0]);
137 	}
138 }
139 
140 /*******************************************************************************
141  * Transitioning granule of REALM type to NON-SECURE type
142  ******************************************************************************/
trp_asc_mark_nonsecure(unsigned long long x1,struct trp_smc_result * smc_ret)143 static void trp_asc_mark_nonsecure(unsigned long long x1,
144 				   struct trp_smc_result *smc_ret)
145 {
146 	VERBOSE("Undelegating granule 0x%llx\n", x1);
147 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
148 						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
149 
150 	if (smc_ret->x[0] != 0ULL) {
151 		ERROR("Granule transition from REALM type to NON-SECURE type "
152 			"failed 0x%llx\n", smc_ret->x[0]);
153 	}
154 }
155 
156 /*******************************************************************************
157  * Main RMI SMC handler function
158  ******************************************************************************/
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,struct trp_smc_result * smc_ret)159 void trp_rmi_handler(unsigned long fid,
160 		     unsigned long long x1, unsigned long long x2,
161 		     unsigned long long x3, unsigned long long x4,
162 		     unsigned long long x5, unsigned long long x6,
163 		     struct trp_smc_result *smc_ret)
164 {
165 	/* Not used in the current implementation */
166 	(void)x2;
167 	(void)x3;
168 	(void)x4;
169 	(void)x5;
170 	(void)x6;
171 
172 	switch (fid) {
173 	case RMI_RMM_REQ_VERSION:
174 		trp_ret_rmi_version(x1, smc_ret);
175 		break;
176 	case RMI_RMM_GRANULE_DELEGATE:
177 		trp_asc_mark_realm(x1, smc_ret);
178 		break;
179 	case RMI_RMM_GRANULE_UNDELEGATE:
180 		trp_asc_mark_nonsecure(x1, smc_ret);
181 		break;
182 	default:
183 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
184 		smc_ret->x[0] = SMC_UNK;
185 	}
186 }
187