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