150a3056aSZelalem Aweke /* 2*758ccb80SChris Kay * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. 350a3056aSZelalem Aweke * 450a3056aSZelalem Aweke * SPDX-License-Identifier: BSD-3-Clause 550a3056aSZelalem Aweke */ 650a3056aSZelalem Aweke 7*758ccb80SChris Kay #include <common/build_message.h> 850a3056aSZelalem Aweke #include <common/debug.h> 950a3056aSZelalem Aweke #include <plat/common/platform.h> 101d0ca40eSJavier Almansa Sobrino #include <services/rmm_core_manifest.h> 11319fb084SSoby Mathew #include <services/rmmd_svc.h> 1250a3056aSZelalem Aweke #include <services/trp/platform_trp.h> 131d0ca40eSJavier Almansa Sobrino #include <trp_helpers.h> 141d0ca40eSJavier Almansa Sobrino #include "trp_private.h" 1550a3056aSZelalem Aweke 1650a3056aSZelalem Aweke #include <platform_def.h> 1750a3056aSZelalem Aweke 188c980a4aSJavier Almansa Sobrino /* Parameters received from the previous image */ 198c980a4aSJavier Almansa Sobrino static unsigned int trp_boot_abi_version; 208c980a4aSJavier Almansa Sobrino static uintptr_t trp_shared_region_start; 218c980a4aSJavier Almansa Sobrino 221d0ca40eSJavier Almansa Sobrino /* Parameters received from boot manifest */ 231d0ca40eSJavier Almansa Sobrino uint32_t trp_boot_manifest_version; 248c980a4aSJavier Almansa Sobrino 2550a3056aSZelalem Aweke /******************************************************************************* 2650a3056aSZelalem Aweke * Setup function for TRP. 2750a3056aSZelalem Aweke ******************************************************************************/ 288c980a4aSJavier Almansa Sobrino void trp_setup(uint64_t x0, 298c980a4aSJavier Almansa Sobrino uint64_t x1, 308c980a4aSJavier Almansa Sobrino uint64_t x2, 318c980a4aSJavier Almansa Sobrino uint64_t x3) 3250a3056aSZelalem Aweke { 338c980a4aSJavier Almansa Sobrino /* 34b96253dbSAlexeiFedorov * Validate boot parameters 358c980a4aSJavier Almansa Sobrino * 36b96253dbSAlexeiFedorov * According to the Boot Interface ABI v.0.1, 37b96253dbSAlexeiFedorov * the parameters received from EL3 are: 38b96253dbSAlexeiFedorov * x0: CPUID (verified earlier, so not used) 398c980a4aSJavier Almansa Sobrino * x1: Boot Interface version 408c980a4aSJavier Almansa Sobrino * x2: PLATFORM_CORE_COUNT 418c980a4aSJavier Almansa Sobrino * x3: Pointer to the shared memory area. 428c980a4aSJavier Almansa Sobrino */ 438c980a4aSJavier Almansa Sobrino 448c980a4aSJavier Almansa Sobrino (void)x0; 458c980a4aSJavier Almansa Sobrino 468c980a4aSJavier Almansa Sobrino if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) { 478c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH); 488c980a4aSJavier Almansa Sobrino } 498c980a4aSJavier Almansa Sobrino 508c980a4aSJavier Almansa Sobrino if ((void *)x3 == NULL) { 518c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER); 528c980a4aSJavier Almansa Sobrino } 538c980a4aSJavier Almansa Sobrino 548c980a4aSJavier Almansa Sobrino if (x2 > TRP_PLATFORM_CORE_COUNT) { 558c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE); 568c980a4aSJavier Almansa Sobrino } 578c980a4aSJavier Almansa Sobrino 588c980a4aSJavier Almansa Sobrino trp_boot_abi_version = x1; 598c980a4aSJavier Almansa Sobrino trp_shared_region_start = x3; 608c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_boot_abi_version, 618c980a4aSJavier Almansa Sobrino sizeof(trp_boot_abi_version)); 628c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_shared_region_start, 638c980a4aSJavier Almansa Sobrino sizeof(trp_shared_region_start)); 648c980a4aSJavier Almansa Sobrino 6550a3056aSZelalem Aweke /* Perform early platform-specific setup */ 66a97bfa5fSAlexeiFedorov trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start); 6750a3056aSZelalem Aweke } 6850a3056aSZelalem Aweke 69dc0ca64eSJavier Almansa Sobrino int trp_validate_warmboot_args(uint64_t x0, uint64_t x1, 70dc0ca64eSJavier Almansa Sobrino uint64_t x2, uint64_t x3) 71dc0ca64eSJavier Almansa Sobrino { 72dc0ca64eSJavier Almansa Sobrino /* 73dc0ca64eSJavier Almansa Sobrino * Validate boot parameters for warm boot 74dc0ca64eSJavier Almansa Sobrino * 75dc0ca64eSJavier Almansa Sobrino * According to the Boot Interface ABI v.0.1, the parameters 76dc0ca64eSJavier Almansa Sobrino * received from EL3 during warm boot are: 77dc0ca64eSJavier Almansa Sobrino * 78dc0ca64eSJavier Almansa Sobrino * x0: CPUID (verified earlier so not used here) 79dc0ca64eSJavier Almansa Sobrino * [x1:x3]: RES0 80dc0ca64eSJavier Almansa Sobrino */ 81dc0ca64eSJavier Almansa Sobrino 82dc0ca64eSJavier Almansa Sobrino (void)x0; 83dc0ca64eSJavier Almansa Sobrino 84dc0ca64eSJavier Almansa Sobrino return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN; 85dc0ca64eSJavier Almansa Sobrino } 86dc0ca64eSJavier Almansa Sobrino 8750a3056aSZelalem Aweke /* Main function for TRP */ 8850a3056aSZelalem Aweke void trp_main(void) 8950a3056aSZelalem Aweke { 90*758ccb80SChris Kay NOTICE("TRP: %s\n", build_version_string); 9150a3056aSZelalem Aweke NOTICE("TRP: %s\n", build_message); 928c980a4aSJavier Almansa Sobrino NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n", 938c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR); 941d0ca40eSJavier Almansa Sobrino NOTICE("TRP: Boot Manifest Version: v.%u.%u\n", 951d0ca40eSJavier Almansa Sobrino RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version), 961d0ca40eSJavier Almansa Sobrino RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version)); 9750a3056aSZelalem Aweke INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE); 98b96253dbSAlexeiFedorov INFO("TRP: Shared region base address: 0x%lx\n", 998c980a4aSJavier Almansa Sobrino (unsigned long)trp_shared_region_start); 100b96253dbSAlexeiFedorov INFO("TRP: Total size: 0x%lx bytes\n", 101b96253dbSAlexeiFedorov (unsigned long)(RMM_END - RMM_BASE)); 1028c980a4aSJavier Almansa Sobrino INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n", 1038c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version), 1048c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version)); 10550a3056aSZelalem Aweke } 10650a3056aSZelalem Aweke 10750a3056aSZelalem Aweke /******************************************************************************* 10850a3056aSZelalem Aweke * Returning RMI version back to Normal World 10950a3056aSZelalem Aweke ******************************************************************************/ 110ade6000fSShruti Gupta static void trp_ret_rmi_version(unsigned long long rmi_version, 111ade6000fSShruti Gupta struct trp_smc_result *smc_ret) 11250a3056aSZelalem Aweke { 113ade6000fSShruti Gupta if (rmi_version != RMI_ABI_VERSION) { 114ade6000fSShruti Gupta smc_ret->x[0] = RMI_ERROR_INPUT; 115ade6000fSShruti Gupta } else { 116ade6000fSShruti Gupta smc_ret->x[0] = RMI_SUCCESS; 117ade6000fSShruti Gupta } 11850a3056aSZelalem Aweke VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 11950a3056aSZelalem Aweke RMI_ABI_VERSION_MINOR); 120ade6000fSShruti Gupta smc_ret->x[1] = RMI_ABI_VERSION; 121ade6000fSShruti Gupta smc_ret->x[2] = RMI_ABI_VERSION; 12250a3056aSZelalem Aweke } 12350a3056aSZelalem Aweke 12450a3056aSZelalem Aweke /******************************************************************************* 12550a3056aSZelalem Aweke * Transitioning granule of NON-SECURE type to REALM type 12650a3056aSZelalem Aweke ******************************************************************************/ 127b96253dbSAlexeiFedorov static void trp_asc_mark_realm(unsigned long long x1, 128b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 12950a3056aSZelalem Aweke { 13050a3056aSZelalem Aweke VERBOSE("Delegating granule 0x%llx\n", x1); 131b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 132b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 13350a3056aSZelalem Aweke 134b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 13550a3056aSZelalem Aweke ERROR("Granule transition from NON-SECURE type to REALM type " 136b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 13750a3056aSZelalem Aweke } 13850a3056aSZelalem Aweke } 13950a3056aSZelalem Aweke 14050a3056aSZelalem Aweke /******************************************************************************* 14150a3056aSZelalem Aweke * Transitioning granule of REALM type to NON-SECURE type 14250a3056aSZelalem Aweke ******************************************************************************/ 143b96253dbSAlexeiFedorov static void trp_asc_mark_nonsecure(unsigned long long x1, 144b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 14550a3056aSZelalem Aweke { 14650a3056aSZelalem Aweke VERBOSE("Undelegating granule 0x%llx\n", x1); 147b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 148b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 14950a3056aSZelalem Aweke 150b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 15150a3056aSZelalem Aweke ERROR("Granule transition from REALM type to NON-SECURE type " 152b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 15350a3056aSZelalem Aweke } 15450a3056aSZelalem Aweke } 15550a3056aSZelalem Aweke 15650a3056aSZelalem Aweke /******************************************************************************* 15750a3056aSZelalem Aweke * Main RMI SMC handler function 15850a3056aSZelalem Aweke ******************************************************************************/ 159b96253dbSAlexeiFedorov void trp_rmi_handler(unsigned long fid, 160b96253dbSAlexeiFedorov unsigned long long x1, unsigned long long x2, 161b96253dbSAlexeiFedorov unsigned long long x3, unsigned long long x4, 162b96253dbSAlexeiFedorov unsigned long long x5, unsigned long long x6, 163b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 16450a3056aSZelalem Aweke { 165b96253dbSAlexeiFedorov /* Not used in the current implementation */ 166b96253dbSAlexeiFedorov (void)x2; 167b96253dbSAlexeiFedorov (void)x3; 168b96253dbSAlexeiFedorov (void)x4; 169b96253dbSAlexeiFedorov (void)x5; 170b96253dbSAlexeiFedorov (void)x6; 171b96253dbSAlexeiFedorov 17250a3056aSZelalem Aweke switch (fid) { 17350a3056aSZelalem Aweke case RMI_RMM_REQ_VERSION: 174ade6000fSShruti Gupta trp_ret_rmi_version(x1, smc_ret); 175b96253dbSAlexeiFedorov break; 17650a3056aSZelalem Aweke case RMI_RMM_GRANULE_DELEGATE: 177b96253dbSAlexeiFedorov trp_asc_mark_realm(x1, smc_ret); 178b96253dbSAlexeiFedorov break; 17950a3056aSZelalem Aweke case RMI_RMM_GRANULE_UNDELEGATE: 180b96253dbSAlexeiFedorov trp_asc_mark_nonsecure(x1, smc_ret); 181b96253dbSAlexeiFedorov break; 18250a3056aSZelalem Aweke default: 183b96253dbSAlexeiFedorov ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid); 184b96253dbSAlexeiFedorov smc_ret->x[0] = SMC_UNK; 18550a3056aSZelalem Aweke } 18650a3056aSZelalem Aweke } 187