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