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 */ 65*a97bfa5fSAlexeiFedorov 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 ******************************************************************************/ 109b96253dbSAlexeiFedorov static void trp_ret_rmi_version(struct trp_smc_result *smc_ret) 11050a3056aSZelalem Aweke { 11150a3056aSZelalem Aweke VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 11250a3056aSZelalem Aweke RMI_ABI_VERSION_MINOR); 113b96253dbSAlexeiFedorov smc_ret->x[0] = RMI_ABI_VERSION; 11450a3056aSZelalem Aweke } 11550a3056aSZelalem Aweke 11650a3056aSZelalem Aweke /******************************************************************************* 11750a3056aSZelalem Aweke * Transitioning granule of NON-SECURE type to REALM type 11850a3056aSZelalem Aweke ******************************************************************************/ 119b96253dbSAlexeiFedorov static void trp_asc_mark_realm(unsigned long long x1, 120b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 12150a3056aSZelalem Aweke { 12250a3056aSZelalem Aweke VERBOSE("Delegating granule 0x%llx\n", x1); 123b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 124b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 12550a3056aSZelalem Aweke 126b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 12750a3056aSZelalem Aweke ERROR("Granule transition from NON-SECURE type to REALM type " 128b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 12950a3056aSZelalem Aweke } 13050a3056aSZelalem Aweke } 13150a3056aSZelalem Aweke 13250a3056aSZelalem Aweke /******************************************************************************* 13350a3056aSZelalem Aweke * Transitioning granule of REALM type to NON-SECURE type 13450a3056aSZelalem Aweke ******************************************************************************/ 135b96253dbSAlexeiFedorov static void trp_asc_mark_nonsecure(unsigned long long x1, 136b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 13750a3056aSZelalem Aweke { 13850a3056aSZelalem Aweke VERBOSE("Undelegating granule 0x%llx\n", x1); 139b96253dbSAlexeiFedorov smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 140b96253dbSAlexeiFedorov 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); 14150a3056aSZelalem Aweke 142b96253dbSAlexeiFedorov if (smc_ret->x[0] != 0ULL) { 14350a3056aSZelalem Aweke ERROR("Granule transition from REALM type to NON-SECURE type " 144b96253dbSAlexeiFedorov "failed 0x%llx\n", smc_ret->x[0]); 14550a3056aSZelalem Aweke } 14650a3056aSZelalem Aweke } 14750a3056aSZelalem Aweke 14850a3056aSZelalem Aweke /******************************************************************************* 14950a3056aSZelalem Aweke * Main RMI SMC handler function 15050a3056aSZelalem Aweke ******************************************************************************/ 151b96253dbSAlexeiFedorov void trp_rmi_handler(unsigned long fid, 152b96253dbSAlexeiFedorov unsigned long long x1, unsigned long long x2, 153b96253dbSAlexeiFedorov unsigned long long x3, unsigned long long x4, 154b96253dbSAlexeiFedorov unsigned long long x5, unsigned long long x6, 155b96253dbSAlexeiFedorov struct trp_smc_result *smc_ret) 15650a3056aSZelalem Aweke { 157b96253dbSAlexeiFedorov /* Not used in the current implementation */ 158b96253dbSAlexeiFedorov (void)x2; 159b96253dbSAlexeiFedorov (void)x3; 160b96253dbSAlexeiFedorov (void)x4; 161b96253dbSAlexeiFedorov (void)x5; 162b96253dbSAlexeiFedorov (void)x6; 163b96253dbSAlexeiFedorov 16450a3056aSZelalem Aweke switch (fid) { 16550a3056aSZelalem Aweke case RMI_RMM_REQ_VERSION: 166b96253dbSAlexeiFedorov trp_ret_rmi_version(smc_ret); 167b96253dbSAlexeiFedorov break; 16850a3056aSZelalem Aweke case RMI_RMM_GRANULE_DELEGATE: 169b96253dbSAlexeiFedorov trp_asc_mark_realm(x1, smc_ret); 170b96253dbSAlexeiFedorov break; 17150a3056aSZelalem Aweke case RMI_RMM_GRANULE_UNDELEGATE: 172b96253dbSAlexeiFedorov trp_asc_mark_nonsecure(x1, smc_ret); 173b96253dbSAlexeiFedorov break; 17450a3056aSZelalem Aweke default: 175b96253dbSAlexeiFedorov ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid); 176b96253dbSAlexeiFedorov smc_ret->x[0] = SMC_UNK; 17750a3056aSZelalem Aweke } 17850a3056aSZelalem Aweke } 179