150a3056aSZelalem Aweke /* 2319fb084SSoby Mathew * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. 350a3056aSZelalem Aweke * 450a3056aSZelalem Aweke * SPDX-License-Identifier: BSD-3-Clause 550a3056aSZelalem Aweke */ 650a3056aSZelalem Aweke 750a3056aSZelalem Aweke #include <common/debug.h> 850a3056aSZelalem Aweke #include <plat/common/platform.h> 91d0ca40eSJavier Almansa Sobrino #include <services/rmm_core_manifest.h> 10319fb084SSoby Mathew #include <services/rmmd_svc.h> 1150a3056aSZelalem Aweke #include <services/trp/platform_trp.h> 121d0ca40eSJavier Almansa Sobrino #include <trp_helpers.h> 131d0ca40eSJavier Almansa Sobrino #include "trp_private.h" 1450a3056aSZelalem Aweke 1550a3056aSZelalem Aweke #include <platform_def.h> 1650a3056aSZelalem Aweke 178c980a4aSJavier Almansa Sobrino /* Parameters received from the previous image */ 188c980a4aSJavier Almansa Sobrino static unsigned int trp_boot_abi_version; 198c980a4aSJavier Almansa Sobrino static uintptr_t trp_shared_region_start; 208c980a4aSJavier Almansa Sobrino 211d0ca40eSJavier Almansa Sobrino /* Parameters received from boot manifest */ 221d0ca40eSJavier Almansa Sobrino uint32_t trp_boot_manifest_version; 238c980a4aSJavier Almansa Sobrino 2450a3056aSZelalem Aweke /******************************************************************************* 2550a3056aSZelalem Aweke * Setup function for TRP. 2650a3056aSZelalem Aweke ******************************************************************************/ 278c980a4aSJavier Almansa Sobrino void trp_setup(uint64_t x0, 288c980a4aSJavier Almansa Sobrino uint64_t x1, 298c980a4aSJavier Almansa Sobrino uint64_t x2, 308c980a4aSJavier Almansa Sobrino uint64_t x3) 3150a3056aSZelalem Aweke { 328c980a4aSJavier Almansa Sobrino /* 33b96253dbSAlexeiFedorov * Validate boot parameters 348c980a4aSJavier Almansa Sobrino * 35b96253dbSAlexeiFedorov * According to the Boot Interface ABI v.0.1, 36b96253dbSAlexeiFedorov * the parameters received from EL3 are: 37b96253dbSAlexeiFedorov * x0: CPUID (verified earlier, so not used) 388c980a4aSJavier Almansa Sobrino * x1: Boot Interface version 398c980a4aSJavier Almansa Sobrino * x2: PLATFORM_CORE_COUNT 408c980a4aSJavier Almansa Sobrino * x3: Pointer to the shared memory area. 418c980a4aSJavier Almansa Sobrino */ 428c980a4aSJavier Almansa Sobrino 438c980a4aSJavier Almansa Sobrino (void)x0; 448c980a4aSJavier Almansa Sobrino 458c980a4aSJavier Almansa Sobrino if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) { 468c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH); 478c980a4aSJavier Almansa Sobrino } 488c980a4aSJavier Almansa Sobrino 498c980a4aSJavier Almansa Sobrino if ((void *)x3 == NULL) { 508c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER); 518c980a4aSJavier Almansa Sobrino } 528c980a4aSJavier Almansa Sobrino 538c980a4aSJavier Almansa Sobrino if (x2 > TRP_PLATFORM_CORE_COUNT) { 548c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE); 558c980a4aSJavier Almansa Sobrino } 568c980a4aSJavier Almansa Sobrino 578c980a4aSJavier Almansa Sobrino trp_boot_abi_version = x1; 588c980a4aSJavier Almansa Sobrino trp_shared_region_start = x3; 598c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_boot_abi_version, 608c980a4aSJavier Almansa Sobrino sizeof(trp_boot_abi_version)); 618c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_shared_region_start, 628c980a4aSJavier Almansa Sobrino sizeof(trp_shared_region_start)); 638c980a4aSJavier Almansa Sobrino 6450a3056aSZelalem Aweke /* Perform early platform-specific setup */ 65a97bfa5fSAlexeiFedorov trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start); 6650a3056aSZelalem Aweke } 6750a3056aSZelalem Aweke 68dc0ca64eSJavier Almansa Sobrino int trp_validate_warmboot_args(uint64_t x0, uint64_t x1, 69dc0ca64eSJavier Almansa Sobrino uint64_t x2, uint64_t x3) 70dc0ca64eSJavier Almansa Sobrino { 71dc0ca64eSJavier Almansa Sobrino /* 72dc0ca64eSJavier Almansa Sobrino * Validate boot parameters for warm boot 73dc0ca64eSJavier Almansa Sobrino * 74dc0ca64eSJavier Almansa Sobrino * According to the Boot Interface ABI v.0.1, the parameters 75dc0ca64eSJavier Almansa Sobrino * received from EL3 during warm boot are: 76dc0ca64eSJavier Almansa Sobrino * 77dc0ca64eSJavier Almansa Sobrino * x0: CPUID (verified earlier so not used here) 78dc0ca64eSJavier Almansa Sobrino * [x1:x3]: RES0 79dc0ca64eSJavier Almansa Sobrino */ 80dc0ca64eSJavier Almansa Sobrino 81dc0ca64eSJavier Almansa Sobrino (void)x0; 82dc0ca64eSJavier Almansa Sobrino 83dc0ca64eSJavier Almansa Sobrino return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN; 84dc0ca64eSJavier Almansa Sobrino } 85dc0ca64eSJavier Almansa Sobrino 8650a3056aSZelalem Aweke /* Main function for TRP */ 8750a3056aSZelalem Aweke void trp_main(void) 8850a3056aSZelalem Aweke { 8950a3056aSZelalem Aweke NOTICE("TRP: %s\n", version_string); 9050a3056aSZelalem Aweke NOTICE("TRP: %s\n", build_message); 918c980a4aSJavier Almansa Sobrino NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n", 928c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR); 931d0ca40eSJavier Almansa Sobrino NOTICE("TRP: Boot Manifest Version: v.%u.%u\n", 941d0ca40eSJavier Almansa Sobrino RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version), 951d0ca40eSJavier Almansa Sobrino RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version)); 9650a3056aSZelalem Aweke INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE); 97b96253dbSAlexeiFedorov INFO("TRP: Shared region base address: 0x%lx\n", 988c980a4aSJavier Almansa Sobrino (unsigned long)trp_shared_region_start); 99b96253dbSAlexeiFedorov INFO("TRP: Total size: 0x%lx bytes\n", 100b96253dbSAlexeiFedorov (unsigned long)(RMM_END - RMM_BASE)); 1018c980a4aSJavier Almansa Sobrino INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n", 1028c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version), 1038c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version)); 10450a3056aSZelalem Aweke } 10550a3056aSZelalem Aweke 10650a3056aSZelalem Aweke /******************************************************************************* 10750a3056aSZelalem Aweke * Returning RMI version back to Normal World 10850a3056aSZelalem Aweke ******************************************************************************/ 109*ade6000fSShruti Gupta static void trp_ret_rmi_version(unsigned long long rmi_version, 110*ade6000fSShruti Gupta struct trp_smc_result *smc_ret) 11150a3056aSZelalem Aweke { 112*ade6000fSShruti Gupta if (rmi_version != RMI_ABI_VERSION) { 113*ade6000fSShruti Gupta smc_ret->x[0] = RMI_ERROR_INPUT; 114*ade6000fSShruti Gupta } else { 115*ade6000fSShruti Gupta smc_ret->x[0] = RMI_SUCCESS; 116*ade6000fSShruti Gupta } 11750a3056aSZelalem Aweke VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 11850a3056aSZelalem Aweke RMI_ABI_VERSION_MINOR); 119*ade6000fSShruti Gupta smc_ret->x[1] = RMI_ABI_VERSION; 120*ade6000fSShruti Gupta smc_ret->x[2] = RMI_ABI_VERSION; 12150a3056aSZelalem Aweke } 12250a3056aSZelalem Aweke 12350a3056aSZelalem Aweke /******************************************************************************* 12450a3056aSZelalem Aweke * Transitioning granule of NON-SECURE type to REALM type 12550a3056aSZelalem Aweke ******************************************************************************/ 126b96253dbSAlexeiFedorov static void trp_asc_mark_realm(unsigned long long x1, 127b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 12850a3056aSZelalem Aweke { 12950a3056aSZelalem Aweke VERBOSE("Delegating granule 0x%llx\n", x1); 130b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 131b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 13250a3056aSZelalem Aweke 133b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 13450a3056aSZelalem Aweke ERROR("Granule transition from NON-SECURE type to REALM type " 135b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 13650a3056aSZelalem Aweke } 13750a3056aSZelalem Aweke } 13850a3056aSZelalem Aweke 13950a3056aSZelalem Aweke /******************************************************************************* 14050a3056aSZelalem Aweke * Transitioning granule of REALM type to NON-SECURE type 14150a3056aSZelalem Aweke ******************************************************************************/ 142b96253dbSAlexeiFedorov static void trp_asc_mark_nonsecure(unsigned long long x1, 143b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 14450a3056aSZelalem Aweke { 14550a3056aSZelalem Aweke VERBOSE("Undelegating granule 0x%llx\n", x1); 146b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 147b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 14850a3056aSZelalem Aweke 149b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 15050a3056aSZelalem Aweke ERROR("Granule transition from REALM type to NON-SECURE type " 151b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 15250a3056aSZelalem Aweke } 15350a3056aSZelalem Aweke } 15450a3056aSZelalem Aweke 15550a3056aSZelalem Aweke /******************************************************************************* 15650a3056aSZelalem Aweke * Main RMI SMC handler function 15750a3056aSZelalem Aweke ******************************************************************************/ 158b96253dbSAlexeiFedorov void trp_rmi_handler(unsigned long fid, 159b96253dbSAlexeiFedorov unsigned long long x1, unsigned long long x2, 160b96253dbSAlexeiFedorov unsigned long long x3, unsigned long long x4, 161b96253dbSAlexeiFedorov unsigned long long x5, unsigned long long x6, 162b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 16350a3056aSZelalem Aweke { 164b96253dbSAlexeiFedorov /* Not used in the current implementation */ 165b96253dbSAlexeiFedorov (void)x2; 166b96253dbSAlexeiFedorov (void)x3; 167b96253dbSAlexeiFedorov (void)x4; 168b96253dbSAlexeiFedorov (void)x5; 169b96253dbSAlexeiFedorov (void)x6; 170b96253dbSAlexeiFedorov 17150a3056aSZelalem Aweke switch (fid) { 17250a3056aSZelalem Aweke case RMI_RMM_REQ_VERSION: 173*ade6000fSShruti Gupta trp_ret_rmi_version(x1, smc_ret); 174b96253dbSAlexeiFedorov break; 17550a3056aSZelalem Aweke case RMI_RMM_GRANULE_DELEGATE: 176b96253dbSAlexeiFedorov trp_asc_mark_realm(x1, smc_ret); 177b96253dbSAlexeiFedorov break; 17850a3056aSZelalem Aweke case RMI_RMM_GRANULE_UNDELEGATE: 179b96253dbSAlexeiFedorov trp_asc_mark_nonsecure(x1, smc_ret); 180b96253dbSAlexeiFedorov break; 18150a3056aSZelalem Aweke default: 182b96253dbSAlexeiFedorov ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid); 183b96253dbSAlexeiFedorov smc_ret->x[0] = SMC_UNK; 18450a3056aSZelalem Aweke } 18550a3056aSZelalem Aweke } 186