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