Understanding the PEI Core migration from Flash to RAM
The three memory regions involved in the PEI phase
Step-by-step walkthrough of the PEI Shadow process
Understanding post-shadow address translation
NewPtr = OldPtr + (DRAM_Base - Flash_Base)
Core PEI Shadow implementation in EDK2 source
// MdeModulePkg/Core/Pei/Memory/MemoryServices.c
EFI_STATUS
EFIAPI
PeiInstallPeiMemory (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
IN UINT64 MemoryLength
)
{
// Record permanent memory range
PrivateData->PhysicalMemoryBegin = MemoryBegin;
PrivateData->PhysicalMemoryLength = MemoryLength;
PrivateData->FreePhysicalMemoryTop =
MemoryBegin + MemoryLength;
// Install the Memory Discovered PPI
// -> triggers shadow process
Status = PeiInstallPpi (
PeiServices,
&mMemoryDiscoveredPpi
);
return Status;
}
// MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
VOID
EFIAPI
PeiCore (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
IN VOID *Data
)
{
// ... initialization ...
if (PrivateData.PeiMemoryInstalled &&
!PrivateData.PeimDispatcherReenter) {
//
// Shadow PEI Core into permanent memory
// so it runs faster than XIP from flash
//
PrivateData.ShadowedPeiCore = ShadowPeiCore (
&PrivateData
);
//
// Switch stack from CAR to permanent memory
// and re-enter PEI Core from DRAM
//
SwitchStack (
(SWITCH_STACK_ENTRY_POINT)(UINTN)
PrivateData.ShadowedPeiCore,
(VOID *)SecCoreData,
NULL,
(VOID *)(UINTN)NewStackTop
);
// -- never returns here --
}
}
// Conceptual: migrate stack from CAR to DRAM
//
// 1. Allocate new stack in permanent memory
NewStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
// 2. Copy CAR stack contents to new location
CopyMem (
(VOID *)NewStack,
(VOID *)OldStackBase,
StackSize
);
// 3. Calculate the fixup delta
Delta = (INTN)NewStack - (INTN)OldStackBase;
// 4. Adjust saved frame pointers & return addresses
// that point within the old stack range
for (Ptr = NewStack; Ptr < NewStack + StackSize; Ptr++) {
if (*Ptr >= OldStackBase && *Ptr < OldStackTop) {
*Ptr += Delta;
}
}
// 5. Switch ESP / RSP to new stack
SwitchStack (EntryPoint, Arg, NULL, NewStackTop);
Resources for deeper learning about PEI Shadow