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