Debugging UEFI PEI-to-DXE Handoff Boot Stalls
Troubleshooting boot stalls during the transition from the Pre-EFI Initialization (PEI) phase to the Driver Execution Environment (DXE) phase requires identifying failures that occur as firmware migrates execution from temporary cache to permanent system memory. This guide details the technical mechanisms behind the PEI-to-DXE handoff, outlines common root causes of execution hangs, and provides step-by-step methodologies firmware engineers use to isolate and resolve these issues using hardware and software diagnostics.
The Mechanics of the PEI-to-DXE Transition
The handoff is managed by the DXE Initial Program Loader (DxeIpl) PEI Module (PEIM). To understand where execution freezes, developers monitor these sequential operations:
- Memory Initialization: The system transitions from temporary Cache-as-RAM (CAR) to permanent system memory (DRAM).
- HOB List Finalization: PEI collects platform data, memory maps, and boot status into the Hand-Off Block (HOB) list.
- Firmware Volume (FV) Discovery: The DxeIpl locates the Firmware Volume containing the DXE Foundation (DXE Core).
- Architectural State Transition: If PEI operates in 32-bit mode (IA32) and DXE executes in 64-bit mode (X64), the DxeIpl constructs 64-bit page tables, configures control registers (such as enabling PAE and Long Mode via CR0, CR3, and CR4), and switches processor execution modes.
- Entry Point Invocation: DxeIpl calls the DXE Core entry point, passing the address of the HOB list.
Common Failure Modes
Stalls at this boundary typically stem from hardware state changes or memory structure corruption:
- Stack and Memory Migration Failures: If DRAM initialization succeeds but memory timings, termination resistances, or refresh rates are unstable, tearing down CAR and copying the stack to DRAM causes silent corruption.
- Corrupt or Malformed HOBs: If a PEIM produces an invalid HOB (e.g., miscalculated length, missing terminator HOB, or overlapping memory resource descriptors), the DXE Core will crash or loop infinitely while parsing the list.
- Paging and Mode Switching Errors: When
transitioning to 64-bit long mode, incorrect page table mappings,
unaligned page directories, or mapping execution-disabled (NX/XD)
attributes over the DXE Core code region trigger immediate General
Protection (
#GP) or Page Fault (#PF) exceptions. - Firmware Volume Decompression Errors: If the DXE Firmware Volume is compressed (e.g., using Tiano or LZMA compression) and the decompressor receives corrupted headers or insufficient scratch space, execution deadlocks.
Primary Troubleshooting Methodologies
Firmware engineers employ a combination of hardware instruments, telemetry, and source instrumentation to isolate the stall point.
1. Port 80h Checkpoints
Port 80h POST codes provide the fastest indicator of handoff
progress. Developers monitor POST codes output by
DxeIplPeim and the early DxeMain function. A
freeze between the last PEI status code (such as memory configured) and
the first DXE status code (such as DXE Core loaded) narrows the failure
to the mode switch, relocation, or HOB verification.
2. Early Serial Telemetry
When POST codes are too coarse, developers route debug prints to a low-overhead interface, typically an on-chip UART, LPC debug card, or USB debug port.
Enable high-verbosity logging (
DEBUG_VERBOSEorDEBUG_INFO) inMdeModulePkg/Core/DxeIplPeimandMdeModulePkg/Core/Dxe.Insert explicit raw I/O writes or assembly-level character writes directly before and after the DXE Core invocation:
// Direct serial write inside DxeLoadCore before handoff DebugPrint (DEBUG_INFO, "Handing off to DXE Core at: 0x%p\n", (VOID*)(UINTN)DxeCoreEntryPoint); DxeCoreEntryPoint (HobList);If serial output ceases before the DXE Core header prints, verify whether the serial controller's base address changed or if its clock gating was altered during the transition.
3. Hardware JTAG/ICE Debugging
In-Circuit Emulators (ICE) connected via JTAG/XDP provide non-intrusive visibility when the CPU halts without emitting serial data.
- Halt and Inspect PC/IP: Halt the target immediately
after the stall occurs to observe the Instruction Pointer
(
RIP/EIP). - Inspect Registers: If the core has entered an
exception loop, check the Interrupt Descriptor Table
(
IDTR),CR2(Page Fault Linear Address), andCR3(Page Table Base) to diagnose access violations. - Stack Backtrace: Verify that the stack pointer
(
RSP/ESP) points to valid, accessible DRAM addresses and matches the location assigned during the CAR teardown.
4. Validating the HOB List Structure
If the DXE Core entry point is reached but hangs immediately, the HOB
list is frequently the cause. Developers validate HOB integrity by
implementing a validation routine at the start of
DxeMain:
- Verify the first HOB is
EFI_HOB_TYPE_HANDOFFand contains valid boot modes and memory ranges. - Traverse the list using
GetNextHob()to ensure every block has a valid, non-zero length and ends withEFI_HOB_TYPE_END_OF_HOB_LIST. - Confirm that memory allocation HOBs do not overlap with the DXE Core image relocation target.
5. Page Table and Memory Map Auditing
When switching to Long Mode, developers inspect the identity-mapped page tables created by DxeIpl. Engineers verify that:
- The page directory entries accurately map all physical memory where the DXE Core and stacks reside.
- The Global Descriptor Table (
GDT) registers are loaded with valid 64-bit code and data segment selectors before jumping to the DXE Core.