From 91117d70d89fbef4d7cac2d57854fa613716ca4d Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 30 Jul 2024 20:33:21 +0200 Subject: ArmPlatformPkg: Clone PrePiUniCore into PeilessSec PrePiUniCore was already spectacularly mis-named but now that the UniCore bit has become redundant too, let's rename it in a way that conveys its purpose a bit better: PeilessSec. A straight rename would break all out-of-tree users, so clone it into a new module with a fresh GUID, giving users some time to update. Signed-off-by: Ard Biesheuvel --- ArmPlatformPkg/ArmPlatformPkg.dsc | 1 + ArmPlatformPkg/PeilessSec/AArch64/ArchPeilessSec.c | 37 ++++ .../PeilessSec/AArch64/ModuleEntryPoint.S | 89 +++++++++ ArmPlatformPkg/PeilessSec/Arm/ArchPeilessSec.c | 25 +++ ArmPlatformPkg/PeilessSec/Arm/ModuleEntryPoint.S | 96 ++++++++++ ArmPlatformPkg/PeilessSec/PeilessSec.c | 205 +++++++++++++++++++++ ArmPlatformPkg/PeilessSec/PeilessSec.h | 76 ++++++++ ArmPlatformPkg/PeilessSec/PeilessSec.inf | 78 ++++++++ 8 files changed, 607 insertions(+) create mode 100644 ArmPlatformPkg/PeilessSec/AArch64/ArchPeilessSec.c create mode 100644 ArmPlatformPkg/PeilessSec/AArch64/ModuleEntryPoint.S create mode 100644 ArmPlatformPkg/PeilessSec/Arm/ArchPeilessSec.c create mode 100644 ArmPlatformPkg/PeilessSec/Arm/ModuleEntryPoint.S create mode 100644 ArmPlatformPkg/PeilessSec/PeilessSec.c create mode 100644 ArmPlatformPkg/PeilessSec/PeilessSec.h create mode 100644 ArmPlatformPkg/PeilessSec/PeilessSec.inf (limited to 'ArmPlatformPkg') diff --git a/ArmPlatformPkg/ArmPlatformPkg.dsc b/ArmPlatformPkg/ArmPlatformPkg.dsc index bc4160d931..d73c5741f6 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dsc +++ b/ArmPlatformPkg/ArmPlatformPkg.dsc @@ -123,5 +123,6 @@ ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf ArmPlatformPkg/PrePi/PeiUniCore.inf + ArmPlatformPkg/PeilessSec/PeilessSec.inf ArmPlatformPkg/Library/ArmMaliDp/ArmMaliDp.inf diff --git a/ArmPlatformPkg/PeilessSec/AArch64/ArchPeilessSec.c b/ArmPlatformPkg/PeilessSec/AArch64/ArchPeilessSec.c new file mode 100644 index 0000000000..ccc9cde6d1 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/AArch64/ArchPeilessSec.c @@ -0,0 +1,37 @@ +/** @file + + Copyright (c) 2011-2017, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeilessSec.h" + +#include + +/** + Architecture specific initialization routine. +**/ +VOID +ArchInitialize ( + VOID + ) +{ + // Enable Floating Point + if (FixedPcdGet32 (PcdVFPEnabled)) { + ArmEnableVFP (); + } + + if (ArmReadCurrentEL () == AARCH64_EL2) { + // Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2 + ArmWriteHcr (ARM_HCR_TGE); + + /* Enable Timer access for non-secure EL1 and EL0 + The cnthctl_el2 register bits are architecturally + UNKNOWN on reset. + Disable event stream as it is not in use at this stage + */ + ArmWriteCntHctl (CNTHCTL_EL2_EL1PCTEN | CNTHCTL_EL2_EL1PCEN); + } +} diff --git a/ArmPlatformPkg/PeilessSec/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/PeilessSec/AArch64/ModuleEntryPoint.S new file mode 100644 index 0000000000..efb6c5ade9 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/AArch64/ModuleEntryPoint.S @@ -0,0 +1,89 @@ +// +// Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +#include + +ASM_FUNC(_ModuleEntryPoint) + // Do early platform specific actions + bl ASM_PFX(ArmPlatformPeiBootAction) + +_SetSVCMode: +// Check if we can install the stack at the top of the System Memory or if we need +// to install the stacks at the bottom of the Firmware Device (case the FD is located +// at the top of the DRAM) +_SystemMemoryEndInit: + ldr x1, mSystemMemoryEnd + +_SetupStackPosition: + // r1 = SystemMemoryTop + + // Calculate Top of the Firmware Device + MOV64 (x2, FixedPcdGet64(PcdFdBaseAddress)) + MOV32 (x3, FixedPcdGet32(PcdFdSize) - 1) + sub x3, x3, #1 + add x3, x3, x2 // x3 = FdTop = PcdFdBaseAddress + PcdFdSize + + // UEFI Memory Size (stacks are allocated in this region) + MOV32 (x4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize)) + + // + // Reserve the memory for the UEFI region (contain stacks on its top) + // + + // Calculate how much space there is between the top of the Firmware and the Top of the System Memory + subs x0, x1, x3 // x0 = SystemMemoryTop - FdTop + b.mi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when SEC is in XIP memory outside of the DRAM + cmp x0, x4 + b.ge _SetupStack + + // Case the top of stacks is the FdBaseAddress + mov x1, x2 + +_SetupStack: + // x1 contains the top of the stack (and the UEFI Memory) + + // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment + // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the + // top of the memory space) + adds x11, x1, #1 + b.cs _SetupOverflowStack + +_SetupAlignedStack: + mov x1, x11 + b _GetBaseUefiMemory + +_SetupOverflowStack: + // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE + // aligned (4KB) + and x1, x1, ~EFI_PAGE_MASK + +_GetBaseUefiMemory: + // Calculate the Base of the UEFI Memory + sub x0, x1, x4 + +_GetStackBase: + // r1 = The top of the stack + mov sp, x1 + + // Stack for the primary core = PrimaryCoreStack + MOV32 (x2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)) + sub x1, x1, x2 + + // Move sec startup address into a data register + // Ensure we're jumping to FV version of the code (not boot remapped alias) + ldr x4, =ASM_PFX(CEntryPoint) + + // Set the frame pointer to NULL so any backtraces terminate here + mov x29, xzr + + // Jump to SEC C code + // x0 = UefiMemoryBase + // x1 = StacksBase + blr x4 + +_NeverReturn: + b _NeverReturn diff --git a/ArmPlatformPkg/PeilessSec/Arm/ArchPeilessSec.c b/ArmPlatformPkg/PeilessSec/Arm/ArchPeilessSec.c new file mode 100644 index 0000000000..3c3cef6925 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/Arm/ArchPeilessSec.c @@ -0,0 +1,25 @@ +/** @file + + Copyright (c) 2011 - 2013, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeilessSec.h" + +/** + Architecture specific initialization routine. +**/ +VOID +ArchInitialize ( + VOID + ) +{ + // Enable program flow prediction, if supported. + ArmEnableBranchPrediction (); + + if (FixedPcdGet32 (PcdVFPEnabled)) { + ArmEnableVFP (); + } +} diff --git a/ArmPlatformPkg/PeilessSec/Arm/ModuleEntryPoint.S b/ArmPlatformPkg/PeilessSec/Arm/ModuleEntryPoint.S new file mode 100644 index 0000000000..ab5b023fa9 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/Arm/ModuleEntryPoint.S @@ -0,0 +1,96 @@ +// +// Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// + +#include + +#include + +ASM_FUNC(_ModuleEntryPoint) + // Do early platform specific actions + bl ASM_PFX(ArmPlatformPeiBootAction) + +_SetSVCMode: + // Enter SVC mode, Disable FIQ and IRQ + mov r1, #(CPSR_MODE_SVC | CPSR_IRQ | CPSR_FIQ) + msr CPSR_c, r1 + +// Check if we can install the stack at the top of the System Memory or if we need +// to install the stacks at the bottom of the Firmware Device (case the FD is located +// at the top of the DRAM) +_SystemMemoryEndInit: + ADRL (r1, mSystemMemoryEnd) + ldrd r2, r3, [r1] + teq r3, #0 + moveq r1, r2 + mvnne r1, #0 + +_SetupStackPosition: + // r1 = SystemMemoryTop + + // Calculate Top of the Firmware Device + MOV32 (r2, FixedPcdGet32(PcdFdBaseAddress)) + MOV32 (r3, FixedPcdGet32(PcdFdSize) - 1) + add r3, r3, r2 // r3 = FdTop = PcdFdBaseAddress + PcdFdSize + + // UEFI Memory Size (stacks are allocated in this region) + MOV32 (r4, FixedPcdGet32(PcdSystemMemoryUefiRegionSize)) + + // + // Reserve the memory for the UEFI region (contain stacks on its top) + // + + // Calculate how much space there is between the top of the Firmware and the Top of the System Memory + subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop + bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when SEC is in XIP memory outside of the DRAM + cmp r0, r4 + bge _SetupStack + + // Case the top of stacks is the FdBaseAddress + mov r1, r2 + +_SetupStack: + // r1 contains the top of the stack (and the UEFI Memory) + + // Because the 'push' instruction is equivalent to 'stmdb' (decrement before), we need to increment + // one to the top of the stack. We check if incrementing one does not overflow (case of DRAM at the + // top of the memory space) + adds r9, r1, #1 + bcs _SetupOverflowStack + +_SetupAlignedStack: + mov r1, r9 + b _GetBaseUefiMemory + +_SetupOverflowStack: + // Case memory at the top of the address space. Ensure the top of the stack is EFI_PAGE_SIZE + // aligned (4KB) + MOV32 (r9, ~EFI_PAGE_MASK & 0xFFFFFFFF) + and r1, r1, r9 + +_GetBaseUefiMemory: + // Calculate the Base of the UEFI Memory + sub r0, r1, r4 + +_GetStackBase: + // r1 = The top of the stack + mov sp, r1 + + // Stack for the primary core = PrimaryCoreStack + MOV32 (r2, FixedPcdGet32(PcdCPUCorePrimaryStackSize)) + sub r1, r1, r2 + + // Move sec startup address into a data register + // Ensure we're jumping to FV version of the code (not boot remapped alias) + ldr r4, =ASM_PFX(CEntryPoint) + + // Jump to SEC C code + // r0 = UefiMemoryBase + // r1 = StacksBase + blx r4 + +_NeverReturn: + b _NeverReturn diff --git a/ArmPlatformPkg/PeilessSec/PeilessSec.c b/ArmPlatformPkg/PeilessSec/PeilessSec.c new file mode 100644 index 0000000000..639c3744c9 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/PeilessSec.c @@ -0,0 +1,205 @@ +/** @file + + Copyright (c) 2011-2017, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeilessSec.h" + +#define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) ||\ + ((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= FixedPcdGet64 (PcdSystemMemoryBase))) + +UINT64 mSystemMemoryEnd = FixedPcdGet64 (PcdSystemMemoryBase) + + FixedPcdGet64 (PcdSystemMemorySize) - 1; + +/** + Obtain a PPI from the list of PPIs provided by the platform code. + + @param[in] PpiGuid GUID of the PPI to obtain + @param[out] Ppi Address of GUID pointer to return the PPI + + @return Whether the PPI was obtained successfully +**/ +STATIC +EFI_STATUS +GetPlatformPpi ( + IN EFI_GUID *PpiGuid, + OUT VOID **Ppi + ) +{ + UINTN PpiListSize; + UINTN PpiListCount; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + UINTN Index; + + PpiListSize = 0; + ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList); + PpiListCount = PpiListSize / sizeof (EFI_PEI_PPI_DESCRIPTOR); + for (Index = 0; Index < PpiListCount; Index++, PpiList++) { + if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) { + *Ppi = PpiList->Ppi; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + SEC main routine. + + @param[in] UefiMemoryBase Start of the PI/UEFI memory region + @param[in] StackBase Start of the stack + @param[in] StartTimeStamp Timer value at start of execution +**/ +STATIC +VOID +SecMain ( + IN UINTN UefiMemoryBase, + IN UINTN StackBase, + IN UINT64 StartTimeStamp + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HobList; + ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi; + UINTN ArmCoreCount; + ARM_CORE_INFO *ArmCoreInfoTable; + EFI_STATUS Status; + CHAR8 Buffer[100]; + UINTN CharCount; + UINTN StacksSize; + FIRMWARE_SEC_PERFORMANCE Performance; + + // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP) + ASSERT ( + IS_XIP () || + ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) && + ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd)) + ); + + // Initialize the architecture specific bits + ArchInitialize (); + + // Initialize the Serial Port + SerialPortInitialize (); + CharCount = AsciiSPrint ( + Buffer, + sizeof (Buffer), + "UEFI firmware (version %s built at %a on %a)\n\r", + (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString), + __TIME__, + __DATE__ + ); + SerialPortWrite ((UINT8 *)Buffer, CharCount); + + // Initialize the Debug Agent for Source Level Debugging + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL); + SaveAndSetDebugTimerInterrupt (TRUE); + + // Declare the PI/UEFI memory region + HobList = HobConstructor ( + (VOID *)UefiMemoryBase, + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize), + (VOID *)UefiMemoryBase, + (VOID *)StackBase // The top of the UEFI Memory is reserved for the stack + ); + PrePeiSetHobList (HobList); + + // Initialize MMU and Memory HOBs (Resource Descriptor HOBs) + Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)); + ASSERT_EFI_ERROR (Status); + + // Create the Stacks HOB + StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize); + BuildStackHob (StackBase, StacksSize); + + // TODO: Call CpuPei as a library + BuildCpuHob (ArmGetPhysicalAddressBits (), PcdGet8 (PcdPrePiCpuIoSize)); + + if (ArmIsMpCore ()) { + // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid + Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID **)&ArmMpCoreInfoPpi); + + // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid) + ASSERT_EFI_ERROR (Status); + + // Build the MP Core Info Table + ArmCoreCount = 0; + Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable); + if (!EFI_ERROR (Status) && (ArmCoreCount > 0)) { + // Build MPCore Info HOB + BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount); + } + } + + // Store timer value logged at the beginning of firmware image execution + Performance.ResetEnd = GetTimeInNanoSecond (StartTimeStamp); + + // Build SEC Performance Data Hob + BuildGuidDataHob (&gEfiFirmwarePerformanceGuid, &Performance, sizeof (Performance)); + + // Set the Boot Mode + SetBootMode (ArmPlatformGetBootMode ()); + + // Initialize Platform HOBs (CpuHob and FvHob) + Status = PlatformPeim (); + ASSERT_EFI_ERROR (Status); + + // Now, the HOB List has been initialized, we can register performance information + PERF_START (NULL, "PEI", NULL, StartTimeStamp); + + // SEC phase needs to run library constructors by hand. + ProcessLibraryConstructorList (); + + // Assume the FV that contains the SEC (our code) also contains a compressed FV. + Status = DecompressFirstFv (); + ASSERT_EFI_ERROR (Status); + + // Load the DXE Core and transfer control to it + Status = LoadDxeCoreFromFv (NULL, 0); + ASSERT_EFI_ERROR (Status); +} + +/** + C entrypoint into the SEC driver. + + @param[in] UefiMemoryBase Start of the PI/UEFI memory region + @param[in] StackBase Start of the stack +**/ +VOID +CEntryPoint ( + IN UINTN UefiMemoryBase, + IN UINTN StackBase + ) +{ + UINT64 StartTimeStamp; + + // Initialize the platform specific controllers + ArmPlatformInitialize (ArmReadMpidr ()); + + if (PerformanceMeasurementEnabled ()) { + // We cannot call yet the PerformanceLib because the HOB List has not been initialized + StartTimeStamp = GetPerformanceCounter (); + } else { + StartTimeStamp = 0; + } + + // Data Cache enabled on Primary core when MMU is enabled. + ArmDisableDataCache (); + // Invalidate instruction cache + ArmInvalidateInstructionCache (); + // Enable Instruction Caches on all cores. + ArmEnableInstructionCache (); + + InvalidateDataCacheRange ( + (VOID *)UefiMemoryBase, + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize) + ); + + SecMain (UefiMemoryBase, StackBase, StartTimeStamp); + + // DXE Core should always load and never return + ASSERT (FALSE); +} diff --git a/ArmPlatformPkg/PeilessSec/PeilessSec.h b/ArmPlatformPkg/PeilessSec/PeilessSec.h new file mode 100644 index 0000000000..70d78cafb0 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/PeilessSec.h @@ -0,0 +1,76 @@ +/** @file + + Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PEILESSSEC_H_ +#define PEILESSSEC_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern UINT64 mSystemMemoryEnd; + +/** + Entrypoint of the memory PEIM driver. + + @param[in] UefiMemoryBase The base of the PI/UEFI memory region + @param[in[ UefiMemorySize The size of the PI/UEFI memory region + + @return Whether the memory PEIM driver executed successfully +**/ +EFI_STATUS +EFIAPI +MemoryPeim ( + IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, + IN UINT64 UefiMemorySize + ); + +/** + Entrypoint of platform PEIM driver. + + @return Whether the platform PEIM driver executed successfully +**/ +EFI_STATUS +EFIAPI +PlatformPeim ( + VOID + ); + +/** + Populate and install the memory type information HOB. +**/ +VOID +BuildMemoryTypeInformationHob ( + VOID + ); + +/** + Architecture specific initialization routine. +**/ +VOID +ArchInitialize ( + VOID + ); + +#endif /* PEILESSSEC_H_ */ diff --git a/ArmPlatformPkg/PeilessSec/PeilessSec.inf b/ArmPlatformPkg/PeilessSec/PeilessSec.inf new file mode 100644 index 0000000000..7ceeb74f69 --- /dev/null +++ b/ArmPlatformPkg/PeilessSec/PeilessSec.inf @@ -0,0 +1,78 @@ +## @file +# SEC driver for PEI-less ARM platforms. +# +# Copyright (C) 2015 Hewlett-Packard Development Company, L.P.
+# Copyright (c) 2011-2017, ARM Ltd. All rights reserved.
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = PeilessSec + FILE_GUID = d90b03a8-2df5-4174-9ec1-c6e5b12b334b + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +[Sources] + PeilessSec.h + PeilessSec.c + +[Sources.ARM] + Arm/ArchPeilessSec.c + Arm/ModuleEntryPoint.S + +[Sources.AArch64] + AArch64/ArchPeilessSec.c + AArch64/ModuleEntryPoint.S + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + ArmPlatformLib + BaseMemoryLib + CacheMaintenanceLib + DebugAgentLib + DebugLib + HobLib + MemoryInitPeiLib + PerformanceLib + PlatformPeiLib + PrePiHobListPointerLib + PrePiLib + PrintLib + SerialPortLib + TimerLib + +[Ppis] + gArmMpCoreInfoPpiGuid + +[Guids] + gArmMpCoreInfoGuid + gEfiFirmwarePerformanceGuid + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob + +[FixedPcd] + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdFvBaseAddress + gArmTokenSpaceGuid.PcdFvSize + gArmTokenSpaceGuid.PcdVFPEnabled + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize + +[Pcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString -- cgit