The patch "f07a9df9af60 ArmVirtPkg: Enable stack guard" enabled stack overflow detection for ArmVirtPkg. Following this patch, running UEFI shell command 'dmpstore' resulted in a crash indicating a stack overflow. Invoking 'dmpstore' results in recursive calls to CascadeProcessVariables () which apparently consumes the available stack space and overflows. Normally, SEC and PEI run off the initial stack, and the DxeIpl PEIM is in charge of launching the DxeCore with a full-sized stack and remapping it non-executable as well. PrePi platforms take some shortcuts and the DXE and BDS run off the initial stack which is relatively small. It is therefore desirable to allocate 128 KiB worth of boot services data memory as the stack for the Dxe phase. The PrePiMain () in ArmVirtPkg/PrePi/PrePi.c invokes the LoadDxeCoreFromFv () to load the Dxe core and transfers control. The second parameter to LoadDxeCoreFromFv () is the stack size, which is currently set to 0. LoadDxeCoreFromFv () is implemented in PrePiLib and if the stack size is 0, it continues to use the initial stack. However, if a stack size is specified in the call to LoadDxeCoreFromFv (), memory is allocated for a new stack and the stack is switched to use the newly allocated stack for the Dxe phase. Therefore, specify 128 KiB as the stack size in the call to LoadDxeCoreFromFv () so that a separate stack is allocated and used for the Dxe phase. Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
176 lines
5.1 KiB
C
Executable File
176 lines
5.1 KiB
C
Executable File
/** @file
|
|
*
|
|
* Copyright (c) 2011-2023, Arm Limited. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*
|
|
**/
|
|
|
|
#include <PiPei.h>
|
|
#include <Pi/PiBootMode.h>
|
|
|
|
#include <Library/PeCoffLib.h>
|
|
#include <Library/PrePiLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/PrePiHobListPointerLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/PerformanceLib.h>
|
|
#include <Library/CacheMaintenanceLib.h>
|
|
|
|
#include <Ppi/GuidedSectionExtraction.h>
|
|
#include <Ppi/ArmMpCoreInfo.h>
|
|
|
|
#include "PrePi.h"
|
|
|
|
VOID
|
|
EFIAPI
|
|
ProcessLibraryConstructorList (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
PrePiMain (
|
|
IN UINTN UefiMemoryBase,
|
|
IN UINTN StacksBase,
|
|
IN UINT64 StartTimeStamp
|
|
)
|
|
{
|
|
EFI_HOB_HANDOFF_INFO_TABLE *HobList;
|
|
EFI_STATUS Status;
|
|
CHAR8 Buffer[100];
|
|
UINTN CharCount;
|
|
UINTN StacksSize;
|
|
|
|
// Initialize the architecture specific bits
|
|
ArchInitialize ();
|
|
|
|
// Declare the PI/UEFI memory region
|
|
HobList = HobConstructor (
|
|
(VOID *)UefiMemoryBase,
|
|
FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
|
|
(VOID *)UefiMemoryBase,
|
|
(VOID *)StacksBase // The top of the UEFI Memory is reserved for the stacks
|
|
);
|
|
PrePeiSetHobList (HobList);
|
|
|
|
//
|
|
// Ensure that the loaded image is invalidated in the caches, so that any
|
|
// modifications we made with the caches and MMU off (such as the applied
|
|
// relocations) don't become invisible once we turn them on.
|
|
//
|
|
InvalidateDataCacheRange ((VOID *)(UINTN)PcdGet64 (PcdFdBaseAddress), PcdGet32 (PcdFdSize));
|
|
|
|
// SEC phase needs to run library constructors by hand.
|
|
ProcessLibraryConstructorList ();
|
|
|
|
// Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
|
|
Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
// 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);
|
|
|
|
// Create the Stacks HOB (reserve the memory for all stacks)
|
|
StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
|
|
BuildStackHob (StacksBase, StacksSize);
|
|
|
|
// TODO: Call CpuPei as a library
|
|
BuildCpuHob (ArmGetPhysicalAddressBits (), PcdGet8 (PcdPrePiCpuIoSize));
|
|
|
|
// Set the Boot Mode
|
|
SetBootMode (BOOT_WITH_FULL_CONFIGURATION);
|
|
|
|
// 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);
|
|
|
|
// 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, SIZE_128KB);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
VOID
|
|
CEntryPoint (
|
|
IN UINTN MpId,
|
|
IN UINTN UefiMemoryBase,
|
|
IN UINTN StacksBase
|
|
)
|
|
{
|
|
UINT64 StartTimeStamp;
|
|
|
|
if (PerformanceMeasurementEnabled ()) {
|
|
// Initialize the Timer Library to setup the Timer HW controller
|
|
TimerConstructor ();
|
|
// 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 ();
|
|
|
|
PrePiMain (UefiMemoryBase, StacksBase, StartTimeStamp);
|
|
|
|
// DXE Core should always load and never return
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
VOID
|
|
RelocatePeCoffImage (
|
|
IN EFI_PEI_FV_HANDLE FwVolHeader,
|
|
IN PE_COFF_LOADER_READ_FILE ImageRead
|
|
)
|
|
{
|
|
EFI_PEI_FILE_HANDLE FileHandle;
|
|
VOID *SectionData;
|
|
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
|
EFI_STATUS Status;
|
|
|
|
FileHandle = NULL;
|
|
Status = FfsFindNextFile (
|
|
EFI_FV_FILETYPE_SECURITY_CORE,
|
|
FwVolHeader,
|
|
&FileHandle
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SectionData);
|
|
if (EFI_ERROR (Status)) {
|
|
Status = FfsFindSectionData (EFI_SECTION_TE, FileHandle, &SectionData);
|
|
}
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
ZeroMem (&ImageContext, sizeof ImageContext);
|
|
|
|
ImageContext.Handle = (EFI_HANDLE)SectionData;
|
|
ImageContext.ImageRead = ImageRead;
|
|
PeCoffLoaderGetImageInfo (&ImageContext);
|
|
|
|
if (ImageContext.ImageAddress != (UINTN)SectionData) {
|
|
ImageContext.ImageAddress = (UINTN)SectionData;
|
|
PeCoffLoaderRelocateImage (&ImageContext);
|
|
}
|
|
}
|