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