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