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 ******************************************************************************/ 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 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 */ 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 ******************************************************************************/ 109 static void trp_ret_rmi_version(struct trp_smc_result *smc_ret) 110 { 111 VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 112 RMI_ABI_VERSION_MINOR); 113 smc_ret->x[0] = RMI_ABI_VERSION; 114 } 115 116 /******************************************************************************* 117 * Transitioning granule of NON-SECURE type to REALM type 118 ******************************************************************************/ 119 static void trp_asc_mark_realm(unsigned long long x1, 120 struct trp_smc_result *smc_ret) 121 { 122 VERBOSE("Delegating granule 0x%llx\n", x1); 123 smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 124 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 125 126 if (smc_ret->x[0] != 0ULL) { 127 ERROR("Granule transition from NON-SECURE type to REALM type " 128 "failed 0x%llx\n", smc_ret->x[0]); 129 } 130 } 131 132 /******************************************************************************* 133 * Transitioning granule of REALM type to NON-SECURE type 134 ******************************************************************************/ 135 static void trp_asc_mark_nonsecure(unsigned long long x1, 136 struct trp_smc_result *smc_ret) 137 { 138 VERBOSE("Undelegating granule 0x%llx\n", x1); 139 smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 140 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 141 142 if (smc_ret->x[0] != 0ULL) { 143 ERROR("Granule transition from REALM type to NON-SECURE type " 144 "failed 0x%llx\n", smc_ret->x[0]); 145 } 146 } 147 148 /******************************************************************************* 149 * Main RMI SMC handler function 150 ******************************************************************************/ 151 void trp_rmi_handler(unsigned long fid, 152 unsigned long long x1, unsigned long long x2, 153 unsigned long long x3, unsigned long long x4, 154 unsigned long long x5, unsigned long long x6, 155 struct trp_smc_result *smc_ret) 156 { 157 /* Not used in the current implementation */ 158 (void)x2; 159 (void)x3; 160 (void)x4; 161 (void)x5; 162 (void)x6; 163 164 switch (fid) { 165 case RMI_RMM_REQ_VERSION: 166 trp_ret_rmi_version(smc_ret); 167 break; 168 case RMI_RMM_GRANULE_DELEGATE: 169 trp_asc_mark_realm(x1, smc_ret); 170 break; 171 case RMI_RMM_GRANULE_UNDELEGATE: 172 trp_asc_mark_nonsecure(x1, smc_ret); 173 break; 174 default: 175 ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid); 176 smc_ret->x[0] = SMC_UNK; 177 } 178 } 179