From e85e29309e602a4e61870829ba965bad8f5da30f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 31 Jul 2024 12:05:49 +0200 Subject: [PATCH] ArmPlatformPkg: Clone PrePeiUniCore into Sec PrePeiUniCore was already named rather awkwardly, but now that the UniCore bit has become redundant too, let's rename it in a way that conveys its purpose a bit better: Sec. This also matches what other architectures and platforms tend to provide. 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/Sec/AArch64/ArchSec.c | 49 ++++ ArmPlatformPkg/Sec/AArch64/Exception.S | 116 +++++++++ ArmPlatformPkg/Sec/AArch64/Helper.S | 42 +++ ArmPlatformPkg/Sec/AArch64/ModuleEntryPoint.S | 60 +++++ ArmPlatformPkg/Sec/AArch64/SwitchStack.S | 32 +++ ArmPlatformPkg/Sec/Arm/ArchSec.c | 60 +++++ ArmPlatformPkg/Sec/Arm/Exception.S | 96 +++++++ ArmPlatformPkg/Sec/Arm/ModuleEntryPoint.S | 40 +++ ArmPlatformPkg/Sec/Arm/SwitchStack.S | 32 +++ ArmPlatformPkg/Sec/Sec.c | 245 ++++++++++++++++++ ArmPlatformPkg/Sec/Sec.h | 54 ++++ ArmPlatformPkg/Sec/Sec.inf | 65 +++++ 13 files changed, 892 insertions(+) create mode 100644 ArmPlatformPkg/Sec/AArch64/ArchSec.c create mode 100644 ArmPlatformPkg/Sec/AArch64/Exception.S create mode 100644 ArmPlatformPkg/Sec/AArch64/Helper.S create mode 100644 ArmPlatformPkg/Sec/AArch64/ModuleEntryPoint.S create mode 100644 ArmPlatformPkg/Sec/AArch64/SwitchStack.S create mode 100644 ArmPlatformPkg/Sec/Arm/ArchSec.c create mode 100644 ArmPlatformPkg/Sec/Arm/Exception.S create mode 100644 ArmPlatformPkg/Sec/Arm/ModuleEntryPoint.S create mode 100644 ArmPlatformPkg/Sec/Arm/SwitchStack.S create mode 100644 ArmPlatformPkg/Sec/Sec.c create mode 100644 ArmPlatformPkg/Sec/Sec.h create mode 100644 ArmPlatformPkg/Sec/Sec.inf diff --git a/ArmPlatformPkg/ArmPlatformPkg.dsc b/ArmPlatformPkg/ArmPlatformPkg.dsc index d73c5741f6..bc6f2b5ede 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dsc +++ b/ArmPlatformPkg/ArmPlatformPkg.dsc @@ -121,6 +121,7 @@ ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf + ArmPlatformPkg/Sec/Sec.inf ArmPlatformPkg/PrePi/PeiUniCore.inf ArmPlatformPkg/PeilessSec/PeilessSec.inf diff --git a/ArmPlatformPkg/Sec/AArch64/ArchSec.c b/ArmPlatformPkg/Sec/AArch64/ArchSec.c new file mode 100644 index 0000000000..371f2b9e3c --- /dev/null +++ b/ArmPlatformPkg/Sec/AArch64/ArchSec.c @@ -0,0 +1,49 @@ +/** @file + Architecture specific handling of CPU exceptions taken while running in PEI. + + Copyright (c) 2012-2013, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Sec.h" + +/** + Minimal high level handling of exceptions occurring in PEI. + + @param[in] Entry Type of exception + @param[in] LR Address of instruction where the exception was taken +**/ +VOID +PeiCommonExceptionEntry ( + IN UINT32 Entry, + IN UINTN LR + ) +{ + CHAR8 Buffer[100]; + UINTN CharCount; + + switch (Entry) { + case EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Synchronous Exception at 0x%X\n\r", LR); + break; + case EXCEPT_AARCH64_IRQ: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "IRQ Exception at 0x%X\n\r", LR); + break; + case EXCEPT_AARCH64_FIQ: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "FIQ Exception at 0x%X\n\r", LR); + break; + case EXCEPT_AARCH64_SERROR: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "SError/Abort Exception at 0x%X\n\r", LR); + break; + default: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Unknown Exception at 0x%X\n\r", LR); + break; + } + + SerialPortWrite ((UINT8 *)Buffer, CharCount); + + while (1) { + } +} diff --git a/ArmPlatformPkg/Sec/AArch64/Exception.S b/ArmPlatformPkg/Sec/AArch64/Exception.S new file mode 100644 index 0000000000..d0d6bc44f7 --- /dev/null +++ b/ArmPlatformPkg/Sec/AArch64/Exception.S @@ -0,0 +1,116 @@ +# +# Copyright (c) 2011-2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# + +#include +#include +#include +#include + +.text + +//============================================================ +//Default Exception Handlers +//============================================================ + +#define TO_HANDLER \ + EL1_OR_EL2(x1) \ +1: mrs x1, elr_el1 /* EL1 Exception Link Register */ ;\ + b 3f ;\ +2: mrs x1, elr_el2 /* EL2 Exception Link Register */ ;\ +3: bl ASM_PFX(PeiCommonExceptionEntry) ; + + +// +// Default Exception handlers: There is no plan to return from any of these exceptions. +// No context saving at all. +// + +VECTOR_BASE(PeiVectorTable) + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_SYNC) +_DefaultSyncExceptHandler_t: + mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_IRQ) +_DefaultIrq_t: + mov x0, #EXCEPT_AARCH64_IRQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_FIQ) +_DefaultFiq_t: + mov x0, #EXCEPT_AARCH64_FIQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SP0_SERR) +_DefaultSError_t: + mov x0, #EXCEPT_AARCH64_SERROR + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPX_SYNC) +_DefaultSyncExceptHandler_h: + mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPX_IRQ) +_DefaultIrq_h: + mov x0, #EXCEPT_AARCH64_IRQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPX_FIQ) +_DefaultFiq_h: + mov x0, #EXCEPT_AARCH64_FIQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_CUR_SPX_SERR) +_DefaultSError_h: + mov x0, #EXCEPT_AARCH64_SERROR + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_SYNC) +_DefaultSyncExceptHandler_LowerA64: + mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_IRQ) +_DefaultIrq_LowerA64: + mov x0, #EXCEPT_AARCH64_IRQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_FIQ) +_DefaultFiq_LowerA64: + mov x0, #EXCEPT_AARCH64_FIQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A64_SERR) +_DefaultSError_LowerA64: + mov x0, #EXCEPT_AARCH64_SERROR + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_SYNC) +_DefaultSyncExceptHandler_LowerA32: + mov x0, #EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_IRQ) +_DefaultIrq_LowerA32: + mov x0, #EXCEPT_AARCH64_IRQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_FIQ) +_DefaultFiq_LowerA32: + mov x0, #EXCEPT_AARCH64_FIQ + TO_HANDLER + +VECTOR_ENTRY(PeiVectorTable, ARM_VECTOR_LOW_A32_SERR) +_DefaultSError_LowerA32: + mov x0, #EXCEPT_AARCH64_SERROR + TO_HANDLER + +VECTOR_END(PeiVectorTable) + +AARCH64_BTI_NOTE() diff --git a/ArmPlatformPkg/Sec/AArch64/Helper.S b/ArmPlatformPkg/Sec/AArch64/Helper.S new file mode 100644 index 0000000000..9b81b96a49 --- /dev/null +++ b/ArmPlatformPkg/Sec/AArch64/Helper.S @@ -0,0 +1,42 @@ +#======================================================================================== +# Copyright (c) 2011-2017, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#======================================================================================= + +#include +#include + +// Setup EL1 while in EL1 +ASM_FUNC(SetupExceptionLevel1) + mov x5, x30 // Save LR + + mov x0, #CPACR_CP_FULL_ACCESS + bl ASM_PFX(ArmWriteCpacr) // Disable copro traps to EL1 + + ret x5 + +// Setup EL2 while in EL2 +ASM_FUNC(SetupExceptionLevel2) + msr sctlr_el2, xzr + mrs x0, hcr_el2 // Read EL2 Hypervisor configuration Register + + // Send all interrupts to their respective Exception levels for EL2 + orr x0, x0, #(1 << 3) // Enable EL2 FIQ + orr x0, x0, #(1 << 4) // Enable EL2 IRQ + orr x0, x0, #(1 << 5) // Enable EL2 SError and Abort + msr hcr_el2, x0 // Write back our settings + + msr cptr_el2, xzr // Disable copro traps to EL2 + + // 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 + mov x0, #(CNTHCTL_EL2_EL1PCTEN | CNTHCTL_EL2_EL1PCEN) + msr cnthctl_el2, x0 + + ret + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPlatformPkg/Sec/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/Sec/AArch64/ModuleEntryPoint.S new file mode 100644 index 0000000000..7addae6cff --- /dev/null +++ b/ArmPlatformPkg/Sec/AArch64/ModuleEntryPoint.S @@ -0,0 +1,60 @@ +// +// Copyright (c) 2011-2014, 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) + +// NOTE: We could be booting from EL3, EL2 or EL1. Need to correctly detect +// and configure the system accordingly. EL2 is default if possible. +// If we started in EL3 we need to switch and run at EL2. +// If we are running at EL2 stay in EL2 +// If we are starting at EL1 stay in EL1. + +// If started at EL3 Sec is run and switches to EL2 before jumping to PEI. +// If started at EL1 or EL2 Sec jumps directly to PEI without making any +// changes. + +// Which EL are we running at? Every EL needs some level of setup... +// We should not run this code in EL3 + EL1_OR_EL2(x0) +1:bl ASM_PFX(SetupExceptionLevel1) + b ASM_PFX(MainEntryPoint) +2:bl ASM_PFX(SetupExceptionLevel2) + b ASM_PFX(MainEntryPoint) + +ASM_PFX(MainEntryPoint): + // Get the top of the primary stacks (and the base of the secondary stacks) + MOV64 (x1, FixedPcdGet64(PcdCPUCoresStackBase) + FixedPcdGet32(PcdCPUCorePrimaryStackSize)) + + // Set up the stack pointer + mov sp, x1 + + // Apply the init value to the entire stack + MOV64 (x8, FixedPcdGet64 (PcdCPUCoresStackBase)) + MOV64 (x9, FixedPcdGet32 (PcdInitValueInTempStack) |\ + FixedPcdGet32 (PcdInitValueInTempStack) << 32) +0:stp x9, x9, [x8], #16 + cmp x8, x1 + b.lt 0b + + // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector + MOV64 (x2, FixedPcdGet64(PcdFvBaseAddress)) + ldr x0, [x2, #8] + + // Move sec startup address into a data register + // Ensure we're jumping to FV version of the code (not boot remapped alias) + ldr x3, =ASM_PFX(CEntryPoint) + + // Set the frame pointer to NULL so any backtraces terminate here + mov x29, xzr + + // Jump to PrePeiCore C code + // x0 = pei_core_address + blr x3 diff --git a/ArmPlatformPkg/Sec/AArch64/SwitchStack.S b/ArmPlatformPkg/Sec/AArch64/SwitchStack.S new file mode 100644 index 0000000000..308b8764fc --- /dev/null +++ b/ArmPlatformPkg/Sec/AArch64/SwitchStack.S @@ -0,0 +1,32 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#include + +#/** +# This allows the caller to switch the stack and return +# +# @param StackDelta Signed amount by which to modify the stack pointer +# +# @return Nothing. Goes to the Entry Point passing in the new parameters +# +#**/ +#VOID +#EFIAPI +#SecSwitchStack ( +# VOID *StackDelta +# )# +# +ASM_FUNC(SecSwitchStack) + mov x1, sp + add x1, x0, x1 + mov sp, x1 + ret + diff --git a/ArmPlatformPkg/Sec/Arm/ArchSec.c b/ArmPlatformPkg/Sec/Arm/ArchSec.c new file mode 100644 index 0000000000..0c1e4998d7 --- /dev/null +++ b/ArmPlatformPkg/Sec/Arm/ArchSec.c @@ -0,0 +1,60 @@ +/** @file + Architecture specific handling of CPU exceptions taken while running in PEI. + + Copyright (c) 2012, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Sec.h" + +/** + Minimal high level handling of exceptions occurring in PEI. + + @param[in] Entry Type of exception + @param[in] LR Address of instruction where the exception was taken +**/ +VOID +PeiCommonExceptionEntry ( + IN UINT32 Entry, + IN UINTN LR + ) +{ + CHAR8 Buffer[100]; + UINTN CharCount; + + switch (Entry) { + case 0: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Reset Exception at 0x%X\n\r", LR); + break; + case 1: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Undefined Exception at 0x%X\n\r", LR); + break; + case 2: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "SWI Exception at 0x%X\n\r", LR); + break; + case 3: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "PrefetchAbort Exception at 0x%X\n\r", LR); + break; + case 4: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "DataAbort Exception at 0x%X\n\r", LR); + break; + case 5: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Reserved Exception at 0x%X\n\r", LR); + break; + case 6: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "IRQ Exception at 0x%X\n\r", LR); + break; + case 7: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "FIQ Exception at 0x%X\n\r", LR); + break; + default: + CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Unknown Exception at 0x%X\n\r", LR); + break; + } + + SerialPortWrite ((UINT8 *)Buffer, CharCount); + while (1) { + } +} diff --git a/ArmPlatformPkg/Sec/Arm/Exception.S b/ArmPlatformPkg/Sec/Arm/Exception.S new file mode 100644 index 0000000000..956ae84714 --- /dev/null +++ b/ArmPlatformPkg/Sec/Arm/Exception.S @@ -0,0 +1,96 @@ +// +// Copyright (c) 2011, ARM Limited. All rights reserved. +// +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# + +#include +#include +#include + +#start of the code section +.text +.align 5 + +# IMPORT +GCC_ASM_IMPORT(PeiCommonExceptionEntry) + +# EXPORT +GCC_ASM_EXPORT(PeiVectorTable) + +//============================================================ +//Default Exception Handlers +//============================================================ + + +ASM_PFX(PeiVectorTable): + b _DefaultResetHandler + b _DefaultUndefined + b _DefaultSWI + b _DefaultPrefetchAbort + b _DefaultDataAbort + b _DefaultReserved + b _DefaultIrq + b _DefaultFiq + +// +// Default Exception handlers: There is no plan to return from any of these exceptions. +// No context saving at all. +// +_DefaultResetHandler: + mov r1, lr + # Switch to SVC for common stack + cps #0x13 + mov r0, #0 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultUndefined: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #1 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultSWI: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #2 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultPrefetchAbort: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #3 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultDataAbort: + sub r1, LR, #8 + # Switch to SVC for common stack + cps #0x13 + mov r0, #4 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultReserved: + mov r1, lr + # Switch to SVC for common stack + cps #0x13 + mov r0, #5 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultIrq: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #6 + blx ASM_PFX(PeiCommonExceptionEntry) + +_DefaultFiq: + sub r1, LR, #4 + # Switch to SVC for common stack + cps #0x13 + mov r0, #7 + blx ASM_PFX(PeiCommonExceptionEntry) + diff --git a/ArmPlatformPkg/Sec/Arm/ModuleEntryPoint.S b/ArmPlatformPkg/Sec/Arm/ModuleEntryPoint.S new file mode 100644 index 0000000000..b3c67234e9 --- /dev/null +++ b/ArmPlatformPkg/Sec/Arm/ModuleEntryPoint.S @@ -0,0 +1,40 @@ +// +// Copyright (c) 2011-2013, 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) + + // Get the top of the primary stacks (and the base of the secondary stacks) + MOV32 (r1, FixedPcdGet64(PcdCPUCoresStackBase) + FixedPcdGet32(PcdCPUCorePrimaryStackSize)) + + // Set up the stack pointer + mov sp, r1 + + // Apply the init value to the entire stack + MOV32 (r8, FixedPcdGet64 (PcdCPUCoresStackBase)) + MOV32 (r9, FixedPcdGet32 (PcdInitValueInTempStack)) + mov r10, r9 + mov r11, r9 + mov r12, r9 +0:stm r8!, {r9-r12} + cmp r8, r1 + blt 0b + + // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector + MOV32 (r2, FixedPcdGet32(PcdFvBaseAddress)) + ldr r0, [r2, #4] + + // Move sec startup address into a data register + // Ensure we're jumping to FV version of the code (not boot remapped alias) + ldr r3, =ASM_PFX(CEntryPoint) + + // Jump to PrePeiCore C code + // r0 = pei_core_address + blx r3 diff --git a/ArmPlatformPkg/Sec/Arm/SwitchStack.S b/ArmPlatformPkg/Sec/Arm/SwitchStack.S new file mode 100644 index 0000000000..d64772b8ed --- /dev/null +++ b/ArmPlatformPkg/Sec/Arm/SwitchStack.S @@ -0,0 +1,32 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#include + +#/** +# This allows the caller to switch the stack and return +# +# @param StackDelta Signed amount by which to modify the stack pointer +# +# @return Nothing. Goes to the Entry Point passing in the new parameters +# +#**/ +#VOID +#EFIAPI +#SecSwitchStack ( +# VOID *StackDelta +# )# +# +ASM_FUNC(SecSwitchStack) + mov R1, R13 + add R1, R0, R1 + mov R13, R1 + bx LR + + + diff --git a/ArmPlatformPkg/Sec/Sec.c b/ArmPlatformPkg/Sec/Sec.c new file mode 100644 index 0000000000..482e68ad42 --- /dev/null +++ b/ArmPlatformPkg/Sec/Sec.c @@ -0,0 +1,245 @@ +/** @file + Generic SEC driver for ARM platforms + + Copyright (c) 2011 - 2022, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Sec.h" + +/** + This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary + RAM into permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which + the SEC or PEIM will copy the Temporary RAM + contents. + @param PermanentMemoryBase Destination Address in permanent memory into + which the SEC or PEIM will copy the Temporary + RAM contents. + @param CopySize Amount of memory to migrate from temporary to + permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > + TemporaryMemoryBase when TemporaryMemoryBase > + PermanentMemoryBase. + +**/ +STATIC +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + VOID *OldHeap; + VOID *NewHeap; + VOID *OldStack; + VOID *NewStack; + UINTN HeapSize; + + HeapSize = ALIGN_VALUE (CopySize / 2, CPU_STACK_ALIGNMENT); + + OldHeap = (VOID *)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize - HeapSize)); + + OldStack = (VOID *)((UINTN)TemporaryMemoryBase + HeapSize); + NewStack = (VOID *)(UINTN)PermanentMemoryBase; + + // + // Migrate the temporary memory stack to permanent memory stack. + // + CopyMem (NewStack, OldStack, CopySize - HeapSize); + + // + // Migrate the temporary memory heap to permanent memory heap. + // + CopyMem (NewHeap, OldHeap, HeapSize); + + SecSwitchStack ((UINTN)NewStack - (UINTN)OldStack); + + return EFI_SUCCESS; +} + +STATIC CONST EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { + SecTemporaryRamSupport +}; + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR gCommonPpiTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiTemporaryRamSupportPpiGuid, + (VOID *)&mTemporaryRamSupportPpi + } +}; + +/** + Construct a PPI list from the PPIs provided in this file and the ones + provided by the platform code. + + @param[out] PpiListSize Size of the PPI list in bytes + @param[out] PpiList Pointer to the constructed PPI list +**/ +STATIC +VOID +CreatePpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + EFI_PEI_PPI_DESCRIPTOR *PlatformPpiList; + UINTN PlatformPpiListSize; + UINTN ListBase; + EFI_PEI_PPI_DESCRIPTOR *LastPpi; + + // Get the Platform PPIs + PlatformPpiListSize = 0; + ArmPlatformGetPlatformPpiList (&PlatformPpiListSize, &PlatformPpiList); + + // Copy the Common and Platform PPis in Temporary Memory + ListBase = PcdGet64 (PcdCPUCoresStackBase); + CopyMem ((VOID *)ListBase, gCommonPpiTable, sizeof (gCommonPpiTable)); + CopyMem ((VOID *)(ListBase + sizeof (gCommonPpiTable)), PlatformPpiList, PlatformPpiListSize); + + // Set the Terminate flag on the last PPI entry + LastPpi = (EFI_PEI_PPI_DESCRIPTOR *)ListBase + + ((sizeof (gCommonPpiTable) + PlatformPpiListSize) / sizeof (EFI_PEI_PPI_DESCRIPTOR)) - 1; + LastPpi->Flags |= EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + + *PpiList = (EFI_PEI_PPI_DESCRIPTOR *)ListBase; + *PpiListSize = sizeof (gCommonPpiTable) + PlatformPpiListSize; +} + +/** + + Prints firmware version and build time to serial console. + +**/ +STATIC +VOID +PrintFirmwareVersion ( + VOID + ) +{ + CHAR8 Buffer[100]; + UINTN CharCount; + + 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); +} + +/** + SEC main routine. + + @param[in] PeiCoreEntryPoint Address in ram of the entrypoint of the PEI + core +**/ +STATIC +VOID +EFIAPI +SecMain ( + IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + UINTN PpiListSize; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + UINTN TemporaryRamBase; + UINTN TemporaryRamSize; + + CreatePpiList (&PpiListSize, &PpiList); + + // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at + // the base of the primary core stack + PpiListSize = ALIGN_VALUE (PpiListSize, CPU_STACK_ALIGNMENT); + TemporaryRamBase = (UINTN)PcdGet64 (PcdCPUCoresStackBase) + PpiListSize; + TemporaryRamSize = (UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize) - PpiListSize; + + // + // Bind this information into the SEC hand-off state + // Note: this must be in sync with the stuff in the asm file + // Note also: HOBs (pei temp ram) MUST be above stack + // + SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); + SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet64 (PcdFvBaseAddress); + SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdFvSize); + SecCoreData.TemporaryRamBase = (VOID *)TemporaryRamBase; // We run on the primary core (and so we use the first stack) + SecCoreData.TemporaryRamSize = TemporaryRamSize; + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = ALIGN_VALUE (SecCoreData.TemporaryRamSize / 2, CPU_STACK_ALIGNMENT); + SecCoreData.StackBase = (VOID *)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize); + SecCoreData.StackSize = (TemporaryRamBase + TemporaryRamSize) - (UINTN)SecCoreData.StackBase; + + // Jump to PEI core entry point + (PeiCoreEntryPoint)(&SecCoreData, PpiList); +} + +/** + Module C entrypoint. + + @param[in] PeiCoreEntryPoint Address in ram of the entrypoint of the PEI + core +**/ +VOID +CEntryPoint ( + IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint + ) +{ + if (!ArmMmuEnabled ()) { + // Data Cache enabled on Primary core when MMU is enabled. + ArmDisableDataCache (); + // Invalidate instruction cache + ArmInvalidateInstructionCache (); + // Enable Instruction Caches on all cores. + ArmEnableInstructionCache (); + + InvalidateDataCacheRange ( + (VOID *)(UINTN)PcdGet64 (PcdCPUCoresStackBase), + PcdGet32 (PcdCPUCorePrimaryStackSize) + ); + } + + // Write VBAR - The Exception Vector table must be aligned to its requirement + // Note: The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure + // 'Align=4K' is defined into your FDF for this module. + ASSERT (((UINTN)PeiVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0); + ArmWriteVBar ((UINTN)PeiVectorTable); + + // Enable Floating Point + if (FixedPcdGet32 (PcdVFPEnabled)) { + ArmEnableVFP (); + } + + // Invoke "ProcessLibraryConstructorList" to have all library constructors + // called. + ProcessLibraryConstructorList (); + + PrintFirmwareVersion (); + + // Initialize the Debug Agent for Source Level Debugging + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL); + SaveAndSetDebugTimerInterrupt (TRUE); + + // Initialize the platform specific controllers + ArmPlatformInitialize (ArmReadMpidr ()); + + // Goto primary Main. + SecMain (PeiCoreEntryPoint); + + // PEI Core should always load and never return + ASSERT (FALSE); +} diff --git a/ArmPlatformPkg/Sec/Sec.h b/ArmPlatformPkg/Sec/Sec.h new file mode 100644 index 0000000000..56d9f352bd --- /dev/null +++ b/ArmPlatformPkg/Sec/Sec.h @@ -0,0 +1,54 @@ +/** @file + Generic SEC driver for ARM platforms + + Copyright (c) 2011 - 2022, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SEC_H_ +#define SEC_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + Helper function to switch to a different stack. Implemented in assembler as + this cannot be done from C code. +**/ +VOID +SecSwitchStack ( + INTN StackDelta + ); + +/** + Vector Table for the PEI Phase. This is executable code but not a callable + function. Implemented in assembler. +**/ +VOID +PeiVectorTable ( + VOID + ); + +/** + Minimal high level handling of exceptions occurring in PEI. +**/ +VOID +PeiCommonExceptionEntry ( + IN UINT32 Entry, + IN UINTN LR + ); + +#endif diff --git a/ArmPlatformPkg/Sec/Sec.inf b/ArmPlatformPkg/Sec/Sec.inf new file mode 100644 index 0000000000..58a566f5f0 --- /dev/null +++ b/ArmPlatformPkg/Sec/Sec.inf @@ -0,0 +1,65 @@ +## @file +# Generic SEC driver for ARM platforms +# +# Copyright (c) 2011, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = Sec + FILE_GUID = 4c97830a-8e18-4aa6-9fd0-837b089910e2 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +[Sources.common] + Sec.h + Sec.c + +[Sources.ARM] + Arm/ArchSec.c + Arm/Exception.S + Arm/ModuleEntryPoint.S + Arm/SwitchStack.S + +[Sources.AARCH64] + AArch64/ArchSec.c + AArch64/Exception.S + AArch64/Helper.S + AArch64/ModuleEntryPoint.S + AArch64/SwitchStack.S + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPkg/ArmPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + ArmPlatformLib + BaseLib + BaseMemoryLib + CacheMaintenanceLib + DebugAgentLib + DebugLib + PrintLib + SerialPortLib + +[Ppis] + gEfiTemporaryRamSupportPpiGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString + +[FixedPcd] + gArmTokenSpaceGuid.PcdFvBaseAddress + gArmTokenSpaceGuid.PcdFvSize + gArmTokenSpaceGuid.PcdVFPEnabled + + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack