// Module: DxeMain - DXE Foundation Core Initialization
// Source: MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
// Binary: DxeCore.efi - UEFI Driver eXecution Environment Core
//
// This file contains the cleaned-up decompilation of all functions
// from the DxeCore DXE Foundation phase.
// Disassembled from HR650X BIOS Build (VS2015, X64)
//
// This module encompasses code compiled from the following source files:
// DxeMain/DxeMain.c, DxeMain/DxeProtocolNotify.c
// Gcd/Gcd.c, Hand/Handle.c, Hand/DriverSupport.c, Hand/Locate.c, Hand/Notify.c
// Mem/Page.c, Mem/Pool.c
// Image/Image.c
// Event/Event.c, Event/Timer.c, Event/Tpl.c
// Dispatcher/Dispatcher.c, Dispatcher/Dependency.c
// FwVolBlock/FwVolBlock.c, FwVol/FwVol.c, FwVol/FwVolAttrib.c, FwVol/FwVolRead.c
// SectionExtraction/CoreSectionExtraction.c
// Misc/PropertiesTable.c, Misc/MemoryAttributesTable.c, Misc/MemoryProtection.c
// Misc/DebugImageInfo.c
// Library/Library.c
//
// Each function is annotated with:
// - Original address in the binary
// - Source file it originates from
// - Description of functionality
#include "../uefi_headers/Uefi.h"
//=====================================================================
// Forward declarations of UEFI Core internal structures
//=====================================================================
//
// Protocol database structures
//
typedef struct _PROTOCOL_ENTRY PROTOCOL_ENTRY;
typedef struct _PROTOCOL_INTERFACE PROTOCOL_INTERFACE;
typedef struct _HANDLE_ENTRY HANDLE_ENTRY;
struct _PROTOCOL_ENTRY {
UINTN Signature;
EFI_GUID ProtocolID;
LIST_ENTRY AllEntries; // All interfaces
LIST_ENTRY NotifyEntry; // Registered notification events
PROTOCOL_ENTRY *Link;
};
struct _PROTOCOL_INTERFACE {
UINTN Signature;
PROTOCOL_ENTRY *Protocol;
HANDLE_ENTRY *Handle;
VOID *Interface;
LIST_ENTRY ByProtocol;
LIST_ENTRY OpenList;
UINTN OpenCount;
};
struct _HANDLE_ENTRY {
UINTN Signature;
EFI_HANDLE Handle;
LIST_ENTRY Protocols;
UINTN Type;
};
//
// Memory map entry
//
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
EFI_PHYSICAL_ADDRESS Start;
UINT64 NumberOfPages;
UINT32 Type;
// ... additional fields
} MEMORY_MAP_ENTRY;
//
// GCD (Global Coherency Domain) structures
//
typedef struct {
UINT64 BaseAddress;
UINT64 Length;
UINT64 Capabilities;
UINT64 Attributes;
UINTN GcdMemoryType;
UINTN GcdIoType;
UINTN Status;
LIST_ENTRY Link;
} GCD_MAP_ENTRY;
//
// Global variables (referenced from decompilation)
//
extern EFI_HANDLE gImageHandle;
extern EFI_SYSTEM_TABLE *gST;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
extern LIST_ENTRY gHandleList;
extern LIST_ENTRY gProtocolList;
extern LIST_ENTRY gMemoryMap;
extern LIST_ENTRY gEventQueue;
//=====================================================================
// _ModuleEntryPoint @ 0xa30
// Source: MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c
//=====================================================================
//
// UEFI DXE Core entry point. Called by the SEC/PEI phase after the DXE
// core is loaded into memory. Stores the image handle globally, invokes
// CoreInitialize() to set up all DXE services, then enters an infinite
// loop (execution never returns -- platform firmware handles events via
// the interrupt/timer subsystem).
//
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
// Store ImageHandle in global for later use
gImageHandle = ImageHandle;
// Main DXE initialization -- sets up memory, protocols, events, dispatcher
CoreInitialize(ImageHandle, SystemTable);
// Should never reach here -- CpuDeadLoop()
while (TRUE)
;
// return EFI_SUCCESS; // unreachable
}
//=====================================================================
// CoreInitialize @ 0x1078 (3325 bytes, 602 lines pseudocode)
// Source: MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
//=====================================================================
//
// CORE INITIALIZATION FUNCTION
// This is the main initialization routine for the DXE phase. Called from
// _ModuleEntryPoint, it performs the following steps in order:
//
// 1. Reads HOB list to discover DXE core's boot mode and system configuration
// 2. Initializes CPU exception handlers
// 3. Stores gST (System Table) and gRT (Runtime Services) pointers
// 4. Initializes the GCD (Global Coherency Domain) memory and I/O maps
// 5. Calls CoreInitializeMemoryServices() to set up page allocation
// 6. Initializes FV (Firmware Volume) support (FwVolBlock)
// 7. Initializes the section extraction protocol
// 8. Processes DXE core image information (PE/COFF headers)
// 9. Installs protocol notification infrastructure
// 10. Initializes handle database (gHandleList, gProtocolList)
// 11. Registers timer and event callbacks
// 12. Initializes memory protection and properties table
// 13. Registers ACPI/other architecture protocol GUID requirements
// 14. Enumerates FVs in HOBs and dispatches drivers
// 15. Enters the driver dispatcher loop
// 16. After dispatch, verifies all arch protocols are installed
// 17. Enters final idle loop
//
// NOTE: The decompiler output shows 126 basic blocks with cyclomatic
// complexity 63, reflecting the many conditional paths in initialization.
// The function body is exceptionally long (3325 bytes) as it handles all
// pre-dispatcher setup.
//
EFI_STATUS
EFIAPI
CoreInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN BootMode;
VOID *HobList;
VOID *CpuHob;
EFI_PHYSICAL_ADDRESS MemoryBaseAddress;
UINT64 MemoryLength;
UINT64 MinimalMemorySizeNeeded;
UINTN NumberOfHandles;
UINTN Index;
VOID *FwVolBase;
UINTN FwVolSize;
UINT32 FwVolAttributes;
//
// Phase 1: Get HOB list and extract boot mode
// The first HOB must be HANDOFF_INFO_TABLE (type 1)
//
HobList = GetSystemConfigurationTable(&gEfiHobListGuid);
if (HobList == NULL) {
HobList = SystemTable->BootServices->LocateHob(
EFI_HOB_TYPE_HANDOFF,
0,
&SystemTable->BootServices
);
}
BootMode = *(UINT32 *)HobList; // PHIT HOB
//
// Phase 2: Initialize CPU exception handlers
//
InitializeCpuExceptionHandlers();
//
// Phase 3: Store system table and runtime services globally
//
gST = SystemTable;
gRT = SystemTable->RuntimeServices;
//
// Phase 4: Initialize GCD (Global Coherency Domain) subsystem
// This manages the CPU's view of memory and I/O resources
//
Status = CoreInitializeGcdServices(HobList, &MemoryBaseAddress, &MemoryLength);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "Failed to initialize GCD services: %r\n", Status));
ASSERT_EFI_ERROR(Status);
}
//
// Phase 5: Initialize memory services (page allocator, pool)
// Discovers physical memory from HOBs and sets up the page manager
//
Status = CoreInitializeMemoryServices(
&HobList,
&MemoryBaseAddress,
&MemoryLength
);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "Failed to initialize memory services: %r\n", Status));
ASSERT_EFI_ERROR(Status);
}
//
// Phase 6: Initialize section extraction protocol
// Needed to decompress and extract firmware volumes
//
Status = CoreInitializeSectionExtraction(&HobList);
if (EFI_ERROR(Status)) {
ASSERT_EFI_ERROR(Status);
}
//
// Phase 7: Process DXE core's own image and install protocol
//
CoreProcessDxeCoreImage();
//
// Phase 8: Log phase transitions
//
DEBUG((EFI_D_INFO, "PEI\n"));
DEBUG((EFI_D_INFO, "DXE\n"));
DEBUG((EFI_D_INFO, "DxeMainInit\n"));
//
// Phase 9: Initialize firmware volume block protocol
// Required to read FVs from flash
//
Status = CoreInitializeFvBlockProtocol();
if (EFI_ERROR(Status)) {
ASSERT_EFI_ERROR(Status);
}
//
// Phase 10: Register protocol notification events
// Sets up the protocol database and notification infrastructure
//
CoreInitializeProtocolNotify();
//
// Phase 11: Register event callbacks for timer and TPL
//
CoreRegisterTimerAndTplCallbacks();
//
// Phase 12: Register ACPI and other arch protocol requirements
//
CoreRegisterArchProtocolRequirements();
//
// Phase 13: Process firmware volumes from HOB list
//
CoreProcessFirmwareVolumes(HobList);
//
// Phase 14: Initialize memory protection attributes table
//
CoreInitializeMemoryProtection();
//
// Phase 15: Initialize properties table
//
CoreInitializePropertiesTable();
//
// Phase 16: Initialize memory attributes table
//
CoreInitializeMemoryAttributesTable();
//
// Phase 17: Notify DXE phase start
//
CoreNotifyPhase(EFI_INITIALIZE_DXE);
//
// Phase 18: Enter driver dispatcher loop
// Loads and starts DXE drivers, processes dependency expressions
//
DEBUG((EFI_D_INFO, "CoreInitializeDispatcher\n"));
DEBUG((EFI_D_INFO, "CoreDispatcher\n"));
CoreDispatcher();
//
// Phase 19: Verify all architectural protocols are present
//
CoreVerifyArchProtocols();
//
// Phase 20: Check for orphaned/discovered-but-not-loaded drivers
//
CoreCheckOrphanedDrivers();
//
// Phase 21: Signal DXE phase end
//
CoreNotifyPhase(EFI_INITIALIZE_END);
//
// Phase 22: Enter idle loop -- firmware is now running
//
while (TRUE)
;
// NOT_REACHED
return EFI_SUCCESS;
}
//=====================================================================
// CoreInitializeMemoryServices @ 0x3db0 (1055 bytes)
// Source: MdeModulePkg/Core/Dxe/Gcd/Gcd.c (CoreInitializeMemoryServices)
//=====================================================================
//
// Initializes the page-based memory allocator. Walks the HOB list to find
// available physical memory resources (type 3 HOBs), selects a suitable
// region for the DXE core heap, carves out the page table structures, and
// registers the memory with the GCD layer.
//
// Parameters:
// HobList - Pointer to HOB list pointer (updated on success)
// MemoryBase - Output: base address of allocated memory
// MemoryLength - Output: length of allocated memory (in bytes)
//
// Returns: EFI_SUCCESS on success, error code otherwise
//
EFI_STATUS
EFIAPI
CoreInitializeMemoryServices (
IN OUT VOID **HobList,
OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
OUT UINT64 *MemoryLength
)
{
EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
UINT64 MinimalMemorySizeNeeded;
UINTN ResourceAttributes;
UINT64 BestBase;
UINT64 BestLength;
UINT64 BestAttributes;
UINTN Index;
//
// The first HOB must be HANDOFF_INFO_TABLE
//
PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)*HobList;
if (PhitHob->Header.HobType != EFI_HOB_TYPE_HANDOFF) {
ASSERT(FALSE);
return EFI_INVALID_PARAMETER;
}
//
// Initialize GCD memory map entries (mMemoryMap)
//
for (Index = 0; Index < MAX_GCD_MEMORY_MAP_ENTRIES; Index++) {
mGcdMemoryMap[Index].Signature = 0;
mGcdMemoryMap[Index].Link.ForwardLink = NULL;
mGcdMemoryMap[Index].GcdMemoryType = (UINTN)-1;
//
// Initialize the LINK structures embedded in each entry
//
InitializeListHead(&mGcdMemoryMap[Index].Link);
}
BestBase = 0;
BestLength = 0;
BestAttributes = 0;
//
// Find memory resource descriptor HOBs for system memory
//
//
// Process any memory configuration from config table
//
Status = CoreProcessMemoryConfiguration(HobList);
//
// Calculate minimal memory size needed for DXE core
//
MinimalMemorySizeNeeded = CalculateMinimumMemorySize();
//
// Search for a suitable system memory region
//
Status = FindSuitableMemoryRegion(
HobList,
MinimalMemorySizeNeeded,
&BestBase,
&BestLength,
&BestAttributes
);
//
// Register the selected memory with GCD
//
Status = CoreAddMemorySpace(
EfiGcdMemoryTypeSystemMemory,
BestBase,
BestLength >> EFI_PAGE_SHIFT,
BestAttributes
);
*MemoryBase = BestBase;
*MemoryLength = BestLength;
return EFI_SUCCESS;
}
//=====================================================================
// CoreExitBootServices @ 0x1db8 (604 bytes)
// Source: MdeModulePkg/Core/Dxe/Mem/Page.c
//=====================================================================
//
// Validates the memory map at ExitBootServices time. Checks that all
// memory map entries have properly aligned addresses and that no ACPI
// reclaim or NVS memory regions have incorrect types. Called when
// the OS loader calls ExitBootServices().
//
EFI_STATUS
EFIAPI
CoreExitBootServices (
IN EFI_HANDLE ImageHandle,
IN UINTN MapKey
)
{
LIST_ENTRY *Link;
MEMORY_MAP_ENTRY *Entry;
gMemoryMapValidated = TRUE;
if (gExitBootServicesFlag) {
//
// Second call to ExitBootServices -- re-validate
//
DxeMainValidateMemoryMap(&gMemoryMap);
gExitBootServicesFlag = FALSE;
}
//
// Walk all memory map entries and verify alignment/integrity
//
for (Link = gMemoryMap.ForwardLink;
Link != &gMemoryMap;
Link = Link->ForwardLink) {
Entry = CR(Link, MEMORY_MAP_ENTRY, Link, MEMORY_MAP_ENTRY_SIGNATURE);
if (Entry->Type < EfiMaxMemoryType &&
mMemoryTypeStatistics[Entry->Type]) {
//
// Validate that ACPI regions are correctly typed
//
if (Entry->Type == EfiACPIReclaimMemory) {
ASSERT(Entry->Type != EfiACPIReclaimMemory);
}
if (Entry->Type == EfiACPIMemoryNVS) {
ASSERT(Entry->Type != EfiACPIMemoryNVS);
}
//
// Check 4KB alignment of start and end+1
//
ASSERT((Entry->Start & EFI_PAGE_MASK) == 0);
ASSERT(((Entry->Start + Entry->NumberOfPages * EFI_PAGE_SIZE) & EFI_PAGE_MASK) == 0);
}
}
return EFI_SUCCESS;
}
//=====================================================================
// CoreNotifySignal @ 0x20cc (280 bytes)
// Source: MdeModulePkg/Core/Dxe/Event/Event.c
//=====================================================================
//
// Signal a specific event, transitioning it from waiting to signaled
// state and queuing any registered notification functions.
//
EFI_STATUS
EFIAPI
CoreSignalEvent (
IN EFI_EVENT Event
)
{
return CoreNotifySignal(Event);
}
//=====================================================================
// CoreWaitForEvent @ 0x21e4 (263 bytes)
// Source: MdeModulePkg/Core/Dxe/Event/Event.c
//=====================================================================
//
// Wait for a single event to be signaled. Inserts the calling thread
// into a wait loop, checking the event state until signaled.
//
EFI_STATUS
EFIAPI
CoreWaitForEvent (
IN EFI_EVENT Event
)
{
UINTN Index;
EFI_EVENT EventList[2];
//
// Check if event is already signaled or if Timer event needed
//
EventList[0] = Event;
EventList[1] = NULL;
return CoreWaitForMultipleEvents(1, EventList, &Index);
}
//=====================================================================
// CoreDispatchEvent @ 0x234c (263 bytes)
// Source: MdeModulePkg/Core/Dxe/Event/Event.c
//=====================================================================
//
// Dispatch a single event from the event queue. Checks the event
// signature and invokes the notification function.
//
VOID
EFIAPI
CoreDispatchEvent (
VOID
)
{
CoreDispatchEventNotifies(TPL_APPLICATION);
}
//=====================================================================
// CoreSetWatchdogTimer @ 0x3490 (284 bytes)
// Source: MdeModulePkg/Core/Dxe/Event/Timer.c
//=====================================================================
//
// Sets the system's watchdog timer. The watchdog timer is used to
// detect system hangs during boot.
//
EFI_STATUS
EFIAPI
CoreSetWatchdogTimer (
IN UINTN Timeout,
IN UINT64 WatchdogCode,
IN UINTN DataSize,
IN CHAR16 *WatchdogData OPTIONAL
)
{
//
// Walk the timer queue and set the timer value
//
CoreAcquireEventLock();
CoreSetTimer(WatchdogTimer, TimerPeriodic, Timeout);
CoreReleaseEventLock();
return EFI_SUCCESS;
}
//=====================================================================
// GCD Memory Map Display Functions (Gcd.c) @ 0x36ec, 0x3a9c, 0x3ba8
// Source: MdeModulePkg/Core/Dxe/Gcd/Gcd.c
//=====================================================================
//=====================================================================
// CoreDisplayGcdMemorySpaceMap @ 0x36ec (287 bytes)
//=====================================================================
//
// Displays the GCD memory space map for debug builds. Iterates all
// entries in the GCD memory map and prints their base, length,
// capabilities, and attributes.
//
VOID
CoreDisplayGcdMemorySpaceMap (
VOID
)
{
UINTN Index;
GCD_MAP_ENTRY *Entry;
Status = CoreGetMemorySpaceMap(&NumberOfEntries, &MemorySpaceMap);
DEBUG((EFI_D_INFO, "GCD:Initial GCD Memory Space Map\n"));
DEBUG((EFI_D_INFO, "GCDMemType Range Capabilities Attributes \n"));
DEBUG((EFI_D_INFO, "========== ================================= ================ ================\n"));
for (Index = 0; Index < NumberOfEntries; Index++) {
Entry = &MemorySpaceMap[Index];
DEBUG((
EFI_D_INFO,
"%a %016lx-%016lx %016lx %016lx%c\n",
(Entry->Length != 0) ? " " : "* ",
Entry->BaseAddress,
Entry->BaseAddress + Entry->Length - 1,
Entry->Capabilities,
Entry->Attributes,
(Entry->Length != 0) ? '*' : ' '
));
}
DEBUG((EFI_D_INFO, "\n"));
}
//=====================================================================
// CoreDisplayGcdIoSpaceMap @ 0x21e4 (263 bytes)
//=====================================================================
//
// Displays the GCD I/O space map for debug builds. Same structure
// as the memory space map display but for I/O resources.
//
VOID
CoreDisplayGcdIoSpaceMap (
VOID
)
{
UINTN Index;
GCD_MAP_ENTRY *Entry;
Status = CoreGetIoSpaceMap(&NumberOfEntries, &IoSpaceMap);
DEBUG((EFI_D_INFO, "GCD:Initial GCD I/O Space Map\n"));
DEBUG((EFI_D_INFO, "GCDIoType Range \n"));
DEBUG((EFI_D_INFO, "========== =================================\n"));
for (Index = 0; Index < NumberOfEntries; Index++) {
Entry = &IoSpaceMap[Index];
DEBUG((
EFI_D_INFO,
"%a %016lx-%016lx%c\n",
(Entry->Length != 0) ? " " : "* ",
Entry->BaseAddress,
Entry->BaseAddress + Entry->Length - 1,
(Entry->Length != 0) ? '*' : ' '
));
}
DEBUG((EFI_D_INFO, "\n"));
}
//=====================================================================
// CoreConvertSpaceInner (GCD split helper) @ 0x234c
// Source: MdeModulePkg/Core/Dxe/Gcd/Gcd.c
//=====================================================================
//
// Helper function for GCD space management. Handles splitting a GCD
// entry when a sub-range is being converted to a different type.
// Creates BottomEntry and TopEntry if the conversion range doesn't
// perfectly align with the existing entry boundaries.
//
EFI_STATUS
CoreConvertSpaceInner (
IN VOID *GcdEntry,
IN UINT64 BaseAddress,
IN UINT64 Length
)
{
GCD_MAP_ENTRY *BottomEntry;
GCD_MAP_ENTRY *TopEntry;
//
// If the conversion starts after the beginning of this entry,
// create a "bottom" entry for the leading unconverted part
//
if (BaseAddress > GcdEntry.BaseAddress) {
BottomEntry = AllocateZeroPool(sizeof(GCD_MAP_ENTRY));
CopyMem(BottomEntry, GcdEntry, sizeof(GCD_MAP_ENTRY));
GcdEntry.BaseAddress = BaseAddress;
BottomEntry.Length = BaseAddress - BottomEntry.BaseAddress;
CoreInsertGcdEntry(GcdEntry, BottomEntry);
}
//
// If the conversion ends before the end of this entry,
// create a "top" entry for the trailing unconverted part
//
if (BaseAddress + Length - 1 < GcdEntry.BaseAddress + GcdEntry.Length - 1) {
TopEntry = AllocateZeroPool(sizeof(GCD_MAP_ENTRY));
CopyMem(TopEntry, GcdEntry, sizeof(GCD_MAP_ENTRY));
TopEntry.BaseAddress = BaseAddress + Length;
TopEntry.Length = (GcdEntry.BaseAddress + GcdEntry.Length) - TopEntry.BaseAddress;
GcdEntry.Length = Length;
CoreInsertGcdEntry(GcdEntry, TopEntry);
}
return EFI_SUCCESS;
}
//=====================================================================
// GCD Entry Insertion/Query Helpers @ 0x2454, 0x25c0
// Source: MdeModulePkg/Core/Dxe/Gcd/Gcd.c
//=====================================================================
//=====================================================================
// CoreInsertGcdEntry @ 0x2454
//=====================================================================
//
// Inserts a new GCD entry into the linked list at the correct position.
//
UINT64
CoreInsertGcdEntry (
IN LIST_ENTRY *GcdMapList,
IN GCD_MAP_ENTRY *NewEntry,
IN GCD_MAP_ENTRY *PrevEntry
)
{
InsertTailList(PrevEntry, &NewEntry->Link);
return EFI_SUCCESS;
}
//=====================================================================
// CoreFreeGcdEntry @ 0x25c0
//=====================================================================
//
// Removes and frees a GCD entry from the list.
//
EFI_STATUS
CoreFreeGcdEntry (
IN GCD_MAP_ENTRY *Entry,
IN GCD_MAP_ENTRY **PrevEntry,
IN GCD_MAP_ENTRY **NextEntry
)
{
RemoveEntryList(&Entry->Link);
FreePool(Entry);
return EFI_SUCCESS;
}
//=====================================================================
// Debug Image Info Functions @ 0x4830
// Source: MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
//=====================================================================
//=====================================================================
// CoreNewDebugImageInfoEntry @ 0x4830
//=====================================================================
//
// Creates a new debug image information entry. Called when a driver
// image is loaded to track it for debugging purposes.
//
EFI_STATUS
CoreNewDebugImageInfoEntry (
IN UINTN ImageEntryType,
IN VOID *LoadedImageProtocol,
IN VOID *ImageInstance
)
{
EFI_DEBUG_IMAGE_INFO *DebugImageInfo;
UINTN Index;
//
// Find an empty slot in the debug image info table
//
for (Index = 0; Index < mDebugInfoTable.MaxTableEntries; Index++) {
if (mDebugInfoTable.DebugImageInfo[Index].ImageInfo == NULL) {
break;
}
}
if (Index >= mDebugInfoTable.MaxTableEntries) {
//
// Table is full, need to reallocate
//
CoreReallocateDebugImageInfoTable();
}
//
// Allocate and fill in new entry
//
DebugImageInfo = AllocatePool(sizeof(EFI_DEBUG_IMAGE_INFO));
DebugImageInfo->ImageInfoType = ImageEntryType;
DebugImageInfo->LoadedImageProtocolInstance = LoadedImageProtocol;
mDebugInfoTable.DebugImageInfo[Index] = DebugImageInfo;
return EFI_SUCCESS;
}
//=====================================================================
// Handle Database Functions
// Source: MdeModulePkg/Core/Dxe/Hand/Handle.c
//=====================================================================
//=====================================================================
// CoreGetProtocolInterface @ 0x58a8
// Source: MdeModulePkg/Core/Dxe/Hand/Handle.c
//=====================================================================
//
// Retrieves the protocol interface for a given handle and protocol GUID.
//
PROTOCOL_INTERFACE *
CoreGetProtocolInterface (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *ProtocolGuid
)
{
HANDLE_ENTRY *HandleEntry;
PROTOCOL_INTERFACE *ProtInterface;
LIST_ENTRY *Link;
HandleEntry = (HANDLE_ENTRY *)UserHandle;
for (Link = HandleEntry->Protocols.ForwardLink;
Link != &HandleEntry->Protocols;
Link = Link->ForwardLink) {
ProtInterface = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
if (CompareGuid(&ProtInterface->Protocol->ProtocolID, ProtocolGuid)) {
return ProtInterface;
}
}
return NULL;
}
//=====================================================================
// CoreUnlinkProtocolInterface @ 0x59d0
// Source: MdeModulePkg/Core/Dxe/Hand/Handle.c
//=====================================================================
//
// Unlinks a protocol interface from its handle and protocol entry.
// Validates open count consistency before unlinking.
//
EFI_STATUS
CoreUnlinkProtocolInterface (
IN EFI_HANDLE UserHandle,
IN PROTOCOL_INTERFACE *ProtInterface
)
{
HANDLE_ENTRY *HandleEntry;
PROTOCOL_ENTRY *ProtEntry;
HandleEntry = (HANDLE_ENTRY *)UserHandle;
ProtEntry = ProtInterface->Protocol;
//
// Validate that open count matches the number of open list entries
//
ASSERT(ProtInterface->OpenListCount == CountListEntries(&ProtInterface->OpenList));
//
// Remove from handle's protocol list
//
RemoveEntryList(&ProtInterface->ByProtocol);
//
// Remove from protocol's interface list
//
RemoveEntryList(&ProtInterface->AllEntries);
return EFI_SUCCESS;
}
//=====================================================================
// Handle Database Query Functions @ 0x5c40, 0x5d70
// Source: MdeModulePkg/Core/Dxe/Hand/Handle.c, DriverSupport.c
//=====================================================================
//=====================================================================
// CoreLocateHandleBuffer @ 0x5c40
//=====================================================================
//
// Locates all handles that support a given protocol and returns them
// in a buffer.
//
EFI_STATUS
EFIAPI
CoreLocateHandleBuffer (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
OUT UINTN *NumberOfHandles,
OUT EFI_HANDLE **Buffer
)
{
EFI_STATUS Status;
UINTN BufferSize;
BufferSize = 0;
*NumberOfHandles = 0;
*Buffer = NULL;
//
// First call to get required buffer size
//
Status = CoreLocateHandle(SearchType, Protocol, SearchKey, &BufferSize, NULL);
if (Status != EFI_BUFFER_TOO_SMALL) {
return Status;
}
if (BufferSize > 0) {
*Buffer = AllocatePool(BufferSize);
if (*Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
//
// Second call to fill the buffer
//
Status = CoreLocateHandle(SearchType, Protocol, SearchKey, &BufferSize, *Buffer);
if (EFI_ERROR(Status)) {
FreePool(*Buffer);
*Buffer = NULL;
return Status;
}
*NumberOfHandles = BufferSize / sizeof(EFI_HANDLE);
return EFI_SUCCESS;
}
//=====================================================================
// CoreLocateProtocol @ 0x5d70
// Source: MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
//=====================================================================
//
// Finds the first handle that supports a given protocol and returns
// the protocol interface.
//
// This is the implementation of EFI_BOOT_SERVICES.LocateProtocol().
//
EFI_STATUS
EFIAPI
CoreLocateProtocol (
IN EFI_GUID *Protocol,
IN VOID *Registration OPTIONAL,
OUT VOID **Interface
)
{
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
UINTN NumberOfHandles;
UINTN Index;
//
// If Registration is provided, this is a "notify" registration
// and we should return the next available interface
//
if (Registration != NULL) {
return CoreGetProtocolFromNotify(Protocol, Registration, Interface);
}
//
// Locate all handles supporting this protocol
//
Status = CoreLocateHandleBuffer(
ByProtocol,
Protocol,
NULL,
&NumberOfHandles,
&HandleBuffer
);
if (EFI_ERROR(Status)) {
*Interface = NULL;
return Status;
}
//
// Return the interface from the first handle found
//
Status = CoreHandleProtocol(
HandleBuffer[0],
Protocol,
Interface
);
FreePool(HandleBuffer);
return Status;
}
//=====================================================================
// CoreInstallProtocolInterfaceNotify @ 0x8e6c (869 bytes)
// Source: MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
//=====================================================================
//
// Installs or re-installs a protocol interface on a handle. This is the
// core implementation behind InstallProtocolInterface(),
// ReinstallProtocolInterface(), and related boot services.
//
EFI_STATUS
EFIAPI
CoreInstallProtocolInterfaceNotify (
IN OUT EFI_HANDLE *UserHandle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE Type,
IN VOID *Interface,
IN EFI_PLATFORM_FIRMWARE_OVERRIDE
)
{
HANDLE_ENTRY *HandleEntry;
PROTOCOL_ENTRY *ProtEntry;
PROTOCOL_INTERFACE *ProtInterface;
LIST_ENTRY *Link;
BOOLEAN Reinstall;
EFI_TPL OldTpl;
Reinstall = FALSE;
//
// Validate parameters
//
if (UserHandle == NULL || Interface == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Raise to TPL_NOTIFY to serialize protocol database access
//
OldTpl = CoreRaiseTpl(TPL_NOTIFY);
//
// Acquire protocol database lock
//
CoreAcquireProtocolLock();
//
// Check if the protocol entry already exists, create if not
//
ProtEntry = CoreFindProtocolEntry(Protocol, TRUE);
if (ProtEntry == NULL) {
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_OUT_OF_RESOURCES;
}
//
// Find or create the handle entry
//
HandleEntry = CoreFindHandleEntry(*UserHandle, TRUE);
if (HandleEntry == NULL) {
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_OUT_OF_RESOURCES;
}
//
// Check if this is a reinstall (already have this protocol on handle)
//
ProtInterface = CoreGetProtocolInterface(*UserHandle, Protocol);
if (ProtInterface != NULL) {
Reinstall = TRUE;
}
//
// Allocate and initialize protocol interface structure
//
ProtInterface = AllocateZeroPool(sizeof(PROTOCOL_INTERFACE));
if (ProtInterface == NULL) {
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_OUT_OF_RESOURCES;
}
ProtInterface->Signature = PROTOCOL_INTERFACE_SIGNATURE;
ProtInterface->Protocol = ProtEntry;
ProtInterface->Handle = HandleEntry;
ProtInterface->Interface = Interface;
InitializeListHead(&ProtInterface->OpenList);
ProtInterface->OpenCount = 0;
//
// Add to protocol entry's interface list
//
InsertTailList(&ProtEntry->AllEntries, &ProtInterface->AllEntries);
//
// Add to handle's protocol list
//
InsertTailList(&HandleEntry->Protocols, &ProtInterface->ByProtocol);
//
// If this is a reinstall, signal protocol notifications
// so that registered notify functions can reconnect
//
CoreNotifyProtocolEntry(ProtEntry);
//
// Notify any registered callbacks
//
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_SUCCESS;
}
//=====================================================================
// CoreUninstallProtocol @ 0xa0a4 (994 bytes)
// Source: MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
//=====================================================================
//
// Uninstalls a protocol interface from a handle. Validates that no
// agents have the protocol open before removing.
//
EFI_STATUS
CoreUninstallProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
{
HANDLE_ENTRY *HandleEntry;
PROTOCOL_INTERFACE *ProtInterface;
PROTOCOL_INTERFACE *OpenInterface;
LIST_ENTRY *Link;
EFI_TPL OldTpl;
//
// Raise TPL and acquire protocol lock
//
OldTpl = CoreRaiseTpl(TPL_NOTIFY);
CoreAcquireProtocolLock();
//
// Find the protocol interface on this handle
//
ProtInterface = CoreGetProtocolInterface(UserHandle, Protocol);
if (ProtInterface == NULL) {
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_NOT_FOUND;
}
//
// Check if any agent has the protocol open
//
if (ProtInterface->OpenCount > 0) {
//
// Check that all openers are child controllers (allowed)
//
for (Link = ProtInterface->OpenList.ForwardLink;
Link != &ProtInterface->OpenList;
Link = Link->ForwardLink) {
OpenInterface = CR(Link, PROTOCOL_INTERFACE, OpenList, PROTOCOL_INTERFACE_SIGNATURE);
if (OpenInterface->OpenCount > 0) {
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_ACCESS_DENIED;
}
}
}
//
// Remove the protocol interface from all lists
//
CoreUnlinkProtocolInterface(UserHandle, ProtInterface);
//
// Signal protocol notifications
//
CoreNotifyProtocolEntry(ProtInterface->Protocol);
//
// Free the protocol interface structure
//
FreePool(ProtInterface);
CoreReleaseProtocolLock();
CoreRestoreTpl(OldTpl);
return EFI_SUCCESS;
}
//=====================================================================
// Memory Page Management Functions
// Source: MdeModulePkg/Core/Dxe/Mem/Page.c
//=====================================================================
//=====================================================================
// CoreFreeMemoryMapStack @ 0x6dc0
//=====================================================================
//
// Frees entries from the memory map stack after memory map retrieval.
//
EFI_STATUS
CoreFreeMemoryMapStack (
VOID
)
{
LIST_ENTRY *Link;
MEMORY_MAP_ENTRY *Entry;
//
// Walk the memory map and free resources
//
Link = gMemoryMap.ForwardLink;
while (Link != &gMemoryMap) {
Entry = CR(Link, MEMORY_MAP_ENTRY, Link, MEMORY_MAP_ENTRY_SIGNATURE);
Link = Link->ForwardLink;
//
// Process and potentially free the entry
//
}
return EFI_SUCCESS;
}
//=====================================================================
// CoreAcquireGcdMemoryLock @ 0x6f8c
//=====================================================================
//
// Acquires the GCD memory lock to serialize GCD operations.
//
VOID
CoreAcquireGcdMemoryLock (
VOID
)
{
//
// Check if the lock is not already held
//
ASSERT(!mGcdMemoryLock.Asserted);
CoreAcquireLock(&mGcdMemoryLock);
}
//=====================================================================
// CorePromoteGcdMemoryResource @ 0x7198
//=====================================================================
//
// Promotes a GCD memory resource from reserved to system memory.
// Used when DXE drivers discover and initialize additional memory.
//
BOOLEAN
CorePromoteGcdMemoryResource (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
EFI_STATUS Status;
//
// Convert the memory range
//
Status = CoreConvertSpace(
GCD_MEMORY_SPACE,
BaseAddress,
Length,
EfiGcdMemoryTypeSystemMemory
);
if (EFI_ERROR(Status)) {
return FALSE;
}
//
// Add to page allocator
//
Status = CoreAddMemorySpace(
EfiGcdMemoryTypeSystemMemory,
BaseAddress,
Length >> EFI_PAGE_SHIFT,
EFI_MEMORY_UC
);
if (EFI_ERROR(Status)) {
return FALSE;
}
return TRUE;
}
//=====================================================================
// CoreAllocateMemoryMapEntry @ 0x7a20
//=====================================================================
//
// Allocates a new memory map entry from the free pool.
//
MEMORY_MAP_ENTRY *
CoreAllocateMemoryMapEntry (
VOID
)
{
MEMORY_MAP_ENTRY *Entry;
Entry = AllocatePool(sizeof(MEMORY_MAP_ENTRY));
if (Entry != NULL) {
Entry->Signature = MEMORY_MAP_ENTRY_SIGNATURE;
}
return Entry;
}
//=====================================================================
// Protocol Notify Functions
// Source: MdeModulePkg/Core/Dxe/Hand/Notify.c
//=====================================================================
//=====================================================================
// CoreNotifyProtocolEntry @ 0xa5a0
//=====================================================================
//
// Notifies all registered protocol events for a given protocol entry.
// Walks the notification list and signals any matching events.
//
UINT64
CoreNotifyProtocolEntry (
IN PROTOCOL_ENTRY *ProtEntry
)
{
LIST_ENTRY *Link;
PROTOCOL_NOTIFY *ProtNotify;
CoreAcquireProtocolLock();
ASSERT(gProtocolDatabaseLock.Lock != 0);
for (Link = ProtEntry->NotifyEntry.ForwardLink;
Link != &ProtEntry->NotifyEntry;
Link = Link->ForwardLink) {
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
if (ProtNotify != NULL) {
CoreSignalEvent(ProtNotify->Event);
}
}
CoreReleaseProtocolLock();
return EFI_SUCCESS;
}
//=====================================================================
// CoreRegisterProtocolNotify @ 0xa61c
//=====================================================================
//
// Registers an event to be notified when a protocol is installed.
// This is the implementation of EFI_BOOT_SERVICES.RegisterProtocolNotify()
// and the newer EFI_BOOT_SERVICES.CreateEvent() with EVT_NOTIFY_SIGNAL.
//
PROTOCOL_NOTIFY *
CoreRegisterProtocolNotify (
IN PROTOCOL_ENTRY *ProtEntry,
IN EFI_EVENT Event
)
{
PROTOCOL_NOTIFY *ProtNotify;
CoreAcquireProtocolLock();
//
// Allocate and initialize notification entry
//
ProtNotify = AllocatePool(sizeof(PROTOCOL_NOTIFY));
if (ProtNotify != NULL) {
ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
ProtNotify->Event = Event;
InsertTailList(&ProtEntry->NotifyEntry, &ProtNotify->Link);
}
CoreReleaseProtocolLock();
return ProtNotify;
}
//=====================================================================
// Event Management Functions
// Source: MdeModulePkg/Core/Dxe/Event/Event.c
//=====================================================================
//=====================================================================
// CoreGetNextEvent @ 0xa8e4
//=====================================================================
//
// Retrieves the next event from the event queue. Used for event
// enumeration by the event dispatcher.
//
EFI_STATUS
CoreGetNextEvent (
IN OUT EFI_EVENT *Event
)
{
LIST_ENTRY *Link;
CoreAcquireEventLock();
if (*Event == NULL) {
//
// Return first event in queue
//
Link = gEventQueue.ForwardLink;
if (Link == &gEventQueue) {
CoreReleaseEventLock();
return EFI_NOT_FOUND;
}
*Event = (EFI_EVENT)CR(Link, EVENT_ENTRY, Link, EVENT_ENTRY_SIGNATURE);
} else {
//
// Return next event after current
//
Link = ((EVENT_ENTRY *)*Event)->Link.ForwardLink;
if (Link == &gEventQueue) {
CoreReleaseEventLock();
return EFI_NOT_FOUND;
}
*Event = (EFI_EVENT)CR(Link, EVENT_ENTRY, Link, EVENT_ENTRY_SIGNATURE);
}
CoreReleaseEventLock();
return EFI_SUCCESS;
}
//=====================================================================
// Event Queue Lock Management @ 0xa964
//=====================================================================
//
// Acquires/releases the event queue lock.
//
LIST_ENTRY *
CoreAcquireEventQueueLock (
VOID
)
{
CoreAcquireLock(&gEventQueueLock);
return &gEventQueue;
}
//=====================================================================
// Properties Table Functions
// Source: MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c
//=====================================================================
//=====================================================================
// CoreCreatePropertiesTable @ 0xaf88 (528 bytes)
//=====================================================================
//
// Creates the UEFI memory attributes table (properties table) that
// describes the memory permissions for the OS. Sets up the table
// structure and populates it from the GCD and page allocator data.
//
EFI_STATUS
CoreCreatePropertiesTable (
IN VOID *MemoryMap,
IN UINTN MemoryMapSize,
IN UINTN DescriptorSize,
IN UINT32 DescriptorVersion
)
{
EFI_MEMORY_DESCRIPTOR *Descriptors;
UINTN DescriptorCount;
UINTN Index;
DescriptorCount = MemoryMapSize / DescriptorSize;
Descriptors = (EFI_MEMORY_DESCRIPTOR *)MemoryMap;
//
// Iterate through memory descriptors and build the properties table
//
for (Index = 0; Index < DescriptorCount; Index++) {
//
// Set appropriate attributes based on memory type
//
SetMemoryAttributes(&Descriptors[Index]);
}
//
// Publish the properties table via the configuration table
//
return gST->InstallConfigurationTable(
&gEfiPropertiesTableGuid,
PropertiesTable
);
}
//=====================================================================
// CoreUpdatePropertiesTable @ 0xb198 (1068 bytes)
//=====================================================================
//
// Updates the UEFI memory attributes table with new entries. Called
// when memory protection attributes change after image loading or
// runtime switching.
//
EFI_STATUS
CoreUpdatePropertiesTable (
IN EFI_MEMORY_DESCRIPTOR *NewRecord,
IN UINTN NewRecordCount
)
{
EFI_STATUS Status;
UINTN OldRecordCount;
EFI_MEMORY_DESCRIPTOR *OldRecord;
UINTN TotalRecordCount;
EFI_MEMORY_DESCRIPTOR *NewTable;
UINTN NewTableSize;
//
// Get existing properties table
//
Status = CoreGetPropertiesTable(&OldRecordCount, &OldRecord);
if (EFI_ERROR(Status)) {
OldRecordCount = 0;
OldRecord = NULL;
}
//
// Calculate total number of records
//
TotalRecordCount = OldRecordCount + NewRecordCount;
if (TotalRecordCount == 0) {
return EFI_SUCCESS;
}
//
// Allocate new table
//
NewTableSize = TotalRecordCount * sizeof(EFI_MEMORY_DESCRIPTOR);
NewTable = AllocatePool(NewTableSize);
if (NewTable == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Copy old records
//
if (OldRecordCount > 0) {
CopyMem(NewTable, OldRecord, OldRecordCount * sizeof(EFI_MEMORY_DESCRIPTOR));
FreePool(OldRecord);
}
//
// Append new records
//
CopyMem(
&NewTable[OldRecordCount],
NewRecord,
NewRecordCount * sizeof(EFI_MEMORY_DESCRIPTOR)
);
//
// Install updated table
//
Status = gST->InstallConfigurationTable(
&gEfiPropertiesTableGuid,
NewTable
);
return Status;
}
//=====================================================================
// CorePropertiesTableImageRecord @ 0xb5c4
//=====================================================================
//
// Records image code/data regions in the properties table for memory
// protection.
//
EFI_STATUS
CorePropertiesTableImageRecord (
IN VOID *ImageRecord,
IN VOID *MemoryMap,
IN UINTN MemoryMapSize
)
{
UINTN Index;
EFI_MEMORY_DESCRIPTOR *Descriptor;
Descriptor = (EFI_MEMORY_DESCRIPTOR *)MemoryMap;
for (Index = 0; Index < MemoryMapSize / sizeof(EFI_MEMORY_DESCRIPTOR); Index++) {
//
// Update the attributes for this descriptor
//
Descriptor[Index].Attribute |= EFI_MEMORY_XP;
}
return EFI_SUCCESS;
}
//=====================================================================
// Memory Protection Functions
// Source: MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
//=====================================================================
//=====================================================================
// CoreProtectUefiImage @ 0x8e6c
//=====================================================================
//
// Sets memory protection attributes for a loaded UEFI image. Marks
// code pages as executable and data pages as non-executable (NX).
//
EFI_STATUS
CoreProtectUefiImage (
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN EFI_PHYSICAL_ADDRESS ImageAddress,
IN UINT64 ImageSize
)
{
UINTN PageCount;
EFI_PHYSICAL_ADDRESS AlignedBase;
EFI_PHYSICAL_ADDRESS AlignedEnd;
AlignedBase = ImageAddress & ~EFI_PAGE_MASK;
AlignedEnd = (ImageAddress + ImageSize + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
PageCount = (AlignedEnd - AlignedBase) >> EFI_PAGE_SHIFT;
//
// Mark code sections as executable (clear NX)
//
Status = CoreSetMemoryAttributes(
EfiGcdMemoryTypeSystemMemory,
AlignedBase,
PageCount,
0,
EFI_MEMORY_XP
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Mark data sections as non-executable (set NX)
//
Status = CoreSetMemoryAttributes(
EfiGcdMemoryTypeSystemMemory,
AlignedBase,
PageCount,
EFI_MEMORY_XP,
0
);
if (EFI_ERROR(Status)) {
return Status;
}
return EFI_SUCCESS;
}
//=====================================================================
// CoreUnprotectUefiImage @ 0x9fa0
//=====================================================================
//
// Removes memory protection attributes for a UEFI image being
// unloaded.
//
EFI_STATUS
CoreUnprotectUefiImage (
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage
)
{
UINTN PageCount;
EFI_PHYSICAL_ADDRESS ImageBase;
ImageBase = (EFI_PHYSICAL_ADDRESS)LoadedImage->ImageBase;
PageCount = LoadedImage->ImageSize >> EFI_PAGE_SHIFT;
//
// Clear NX protection on the image region
//
CoreSetMemoryAttributes(
EfiGcdMemoryTypeSystemMemory,
ImageBase,
PageCount,
0,
EFI_MEMORY_XP
);
return EFI_SUCCESS;
}
//=====================================================================
// CoreSetNxForImageData @ 0xa0a4 (MemoryProtection.c)
//=====================================================================
//
// Sets the NX (non-executable) flag for data sections of a loaded
// image. This provides finer-grained control than ProtectUefiImage.
//
VOID
CoreSetNxForImageData (
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
{
UINTN NumberOfSections;
EFI_IMAGE_SECTION_HEADER *Section;
UINTN Index;
NumberOfSections = ImageContext->NumberOfSections;
Section = ImageContext->SectionHeaders;
for (Index = 0; Index < NumberOfSections; Index++) {
//
// If section has execute attribute, skip it (code section)
//
if ((Section[Index].Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) != 0) {
continue;
}
//
// Mark data sections as non-executable
//
CoreSetMemoryAttributes(
EfiGcdMemoryTypeSystemMemory,
(EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase + Section[Index].VirtualAddress,
Section[Index].Misc.VirtualSize >> EFI_PAGE_SHIFT,
EFI_MEMORY_XP,
0
);
}
}
//=====================================================================
// CoreCreateEvent (Event functions) @ 0xa8e4, 0xaf88
//=====================================================================
//=====================================================================
// CoreCreateEvent @ 0xa8e4
//=====================================================================
//
// Creates a new event of the specified type and TPL.
//
EFI_STATUS
EFIAPI
CoreCreateEvent (
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN VOID *NotifyContext OPTIONAL,
OUT EFI_EVENT *Event
)
{
EVENT_ENTRY *EventEntry;
EventEntry = AllocateZeroPool(sizeof(EVENT_ENTRY));
if (EventEntry == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EventEntry->Signature = EVENT_ENTRY_SIGNATURE;
EventEntry->Type = Type;
EventEntry->NotifyTpl = NotifyTpl;
EventEntry->NotifyFunction = NotifyFunction;
EventEntry->NotifyContext = NotifyContext;
EventEntry->SignalCount = 0;
CoreAcquireEventLock();
InsertTailList(&gEventQueue, &EventEntry->Link);
CoreReleaseEventLock();
*Event = (EFI_EVENT)EventEntry;
return EFI_SUCCESS;
}
//=====================================================================
// Debug Image Information (DebugImageInfo.c)
//=====================================================================
//=====================================================================
// CoreUpdateDebugImageInfoTable @ 0xdb28
//=====================================================================
//
// Updates the debug image information table entry count.
//
EFI_DEBUG_IMAGE_INFO *
CoreUpdateDebugImageInfoTable (
IN UINTN Index
)
{
if (Index < mDebugInfoTable.MaxTableEntries) {
return mDebugInfoTable.DebugImageInfo[Index];
}
return NULL;
}
//=====================================================================
// Library Support Functions
// Source: MdeModulePkg/Core/Dxe/Library/Library.c
//=====================================================================
//=====================================================================
// CoreReleaseLock @ 0x1109c
//=====================================================================
//
// Releases a spin lock.
//
VOID
CoreReleaseLock (
IN OUT EFI_LOCK *Lock
)
{
Lock->Lock = 0;
}
//=====================================================================
// CoreAcquireLock @ 0x110f8
//=====================================================================
//
// Acquires a spin lock, raising TPL to TPL_NOTIFY first.
//
VOID
CoreAcquireLock (
IN OUT EFI_LOCK *Lock
)
{
//
// Raise TPL to NOTIFY level
//
Lock->Tpl = CoreRaiseTpl(TPL_NOTIFY);
Lock->Lock = 1;
}
//=====================================================================
// Firmware Volume Functions
// Source: MdeModulePkg/Core/Dxe/FwVol/FwVol.c
//=====================================================================
//=====================================================================
// CoreProcessFirmwareVolumesFromHob @ 0x10720 (1234 bytes)
// Source: MdeModulePkg/Core/Dxe/FwVol/FwVol.c
//=====================================================================
//
// Processes firmware volumes discovered from HOB entries. Iterates
// the HOB list looking for FV HOBs (types 5, 9, 12) and registers
// each firmware volume with the FV block protocol and FV protocol
// infrastructure.
//
EFI_STATUS
CoreProcessFirmwareVolumesFromHob (
IN VOID *HobList
)
{
EFI_HOB_GENERIC_HEADER *Hob;
EFI_PHYSICAL_ADDRESS FvBase;
UINT64 FvLength;
UINT32 FvAttributes;
UINT16 FvAlignment;
EFI_STATUS Status;
//
// Walk HOB list to find FV-related HOBs
//
Hob = (EFI_HOB_GENERIC_HEADER *)HobList;
while (Hob->HobType != EFI_HOB_TYPE_END_OF_HOB_LIST) {
switch (Hob->HobType) {
case EFI_HOB_TYPE_FV:
//
// Standard FV HOB (type 5)
//
FvBase = ((EFI_HOB_FIRMWARE_VOLUME *)Hob)->BaseAddress;
FvLength = ((EFI_HOB_FIRMWARE_VOLUME *)Hob)->Length;
DEBUG((EFI_D_INFO, "FV Hob 0x%016lx - 0x%016lx\n", FvBase, FvBase + FvLength - 1));
break;
case EFI_HOB_TYPE_FV2:
//
// Extended FV HOB with GUID (type 9)
//
FvBase = ((EFI_HOB_FIRMWARE_VOLUME2 *)Hob)->BaseAddress;
FvLength = ((EFI_HOB_FIRMWARE_VOLUME2 *)Hob)->Length;
DEBUG((EFI_D_INFO, "FV2 Hob 0x%016lx - 0x%016lx\n", FvBase, FvBase + (UINT32)FvLength - 1));
DEBUG((EFI_D_INFO, " %g - %g\n", &FvNameGuid, &FvFileSystemGuid));
break;
case EFI_HOB_TYPE_FV3:
//
// FV3 HOB with alignment info (type 12)
//
FvBase = ((EFI_HOB_FIRMWARE_VOLUME3 *)Hob)->BaseAddress;
FvLength = ((EFI_HOB_FIRMWARE_VOLUME3 *)Hob)->Length;
FvAlignment = ((EFI_HOB_FIRMWARE_VOLUME3 *)Hob)->FvAlignment;
DEBUG((
EFI_D_INFO,
"FV3 Hob 0x%016lx - 0x%016lx - 0x%x - 0x%x\n",
FvBase,
(UINT32)FvLength + FvBase - 1,
((EFI_HOB_FIRMWARE_VOLUME3 *)Hob)->Attributes,
FvAlignment
));
break;
default:
break;
}
//
// Advance to next HOB
//
Hob = (EFI_HOB_GENERIC_HEADER *)((UINT8 *)Hob + Hob->HobLength);
}
return EFI_SUCCESS;
}
//=====================================================================
// Section Extraction Functions
// Source: MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
//=====================================================================
//=====================================================================
// CoreOpenSectionStream @ 0xcc94 (1228 bytes)
//=====================================================================
//
// Opens a section stream from a firmware file section. Used to extract
// individual sections (e.g., PE32, GUIDed, compressed) from a firmware
// file.
//
EFI_STATUS
CoreOpenSectionStream (
IN UINTN SectionStreamLength,
IN VOID *SectionStream,
OUT SECTION_NODE **SectionNode
)
{
SECTION_NODE *NewNode;
EFI_COMMON_SECTION_HEADER *SectionHeader;
UINTN ParsedLength;
UINT32 SectionLength;
UINT8 *Buffer;
EFI_STATUS Status;
//
// Allocate a new section stream node
//
NewNode = AllocatePool(sizeof(SECTION_NODE));
if (NewNode == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NewNode->Signature = SECTION_STREAM_SIGNATURE;
NewNode->StreamLength = SectionStreamLength;
NewNode->EncapsulatedStreamCount = 0;
InitializeListHead(&NewNode->EncapsulatedStreams);
//
// Parse sections and discover encapsulated streams
//
Buffer = (UINT8 *)SectionStream;
ParsedLength = 0;
while (ParsedLength < SectionStreamLength) {
SectionHeader = (EFI_COMMON_SECTION_HEADER *)Buffer;
SectionLength = SECTION_SIZE(SectionHeader);
if (SectionHeader->Type == EFI_SECTION_GUID_DEFINED) {
//
// This is a GUID-defined section (e.g., LZMA compressed, CRC32)
// Need to find the extraction protocol and process it
//
Status = CoreProcessGuidedSection(NewNode, SectionHeader);
if (EFI_ERROR(Status)) {
break;
}
}
Buffer += SectionLength;
ParsedLength += SectionLength;
}
*SectionNode = NewNode;
return EFI_SUCCESS;
}
//=====================================================================
// CoreFindChildSection @ 0xd7d0 (248 bytes)
//=====================================================================
//
// Finds a child section within an encapsulated section stream by index.
//
EFI_STATUS
CoreFindChildSection (
IN UINTN SectionIndex,
IN SECTION_NODE *SectionNode,
OUT EFI_COMMON_SECTION_HEADER **Section
)
{
//
// Look up the section node and find the child
//
ASSERT(SectionNode->EncapsulatedStreamCount >= SectionIndex);
//
// Return the section header for the requested child
//
*Section = (EFI_COMMON_SECTION_HEADER *)SectionNode->EncapsulatedStreams[SectionIndex].Stream;
return EFI_SUCCESS;
}
//=====================================================================
// Firmware Volume Block Protocol
// Source: MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c (sub_B98)
//=====================================================================
//=====================================================================
// FvBlockRead @ 0xb98 (1248 bytes)
//=====================================================================
//
// Reads data from a firmware volume block. This is part of the
// EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL implementation.
//
EFI_STATUS
FvBlockRead (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
IN EFI_LBA Lba,
IN UINTN Offset,
IN OUT UINTN *NumBytes,
OUT UINT8 *Buffer
)
{
FV_DEVICE *FvDevice;
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
UINTN LbaIndex;
UINTN LbaOffset;
UINTN BytesToRead;
EFI_STATUS Status;
FvDevice = FV_DEVICE_FROM_THIS(This);
//
// Validate parameters
//
if (NumBytes == NULL || Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Calculate the byte offset for the given LBA
//
LbaIndex = 0;
LbaOffset = 0;
BlockMap = FvDevice->FvbHeader->BlockMap;
while (LbaIndex < Lba) {
LbaOffset += BlockMap->Length;
LbaIndex++;
if (LbaIndex >= BlockMap->NumBlocks) {
BlockMap++;
LbaIndex = 0;
}
}
BytesToRead = *NumBytes;
//
// Read from the FV base
//
CopyMem(Buffer, (UINT8 *)FvDevice->FvBase + LbaOffset + Offset, BytesToRead);
*NumBytes = BytesToRead;
return EFI_SUCCESS;
}
//=====================================================================
// Image Management Functions
// Source: MdeModulePkg/Core/Dxe/Image/Image.c
//=====================================================================
//=====================================================================
// CoreGetImageRecord @ 0x882c (175 bytes)
//=====================================================================
//
// Retrieves the image record for a given image handle by searching
// the loaded image list.
//
IMAGE_RECORD *
CoreGetImageRecord (
IN EFI_HANDLE ImageHandle,
OUT UINTN *Count OPTIONAL
)
{
LIST_ENTRY *Link;
IMAGE_RECORD *ImageRecord;
for (Link = gImageList.ForwardLink;
Link != &gImageList;
Link = Link->ForwardLink) {
ImageRecord = CR(Link, IMAGE_RECORD, Link, IMAGE_RECORD_SIGNATURE);
if (ImageRecord->ImageHandle == ImageHandle) {
if (Count != NULL) {
(*Count)++;
}
return ImageRecord;
}
}
return NULL;
}
//=====================================================================
// CoreFreeImageRecord @ 0x8de0 (137 bytes)
//=====================================================================
//
// Frees an image record and removes it from the image list.
//
EFI_STATUS
CoreFreeImageRecord (
IN IMAGE_RECORD *ImageRecord
)
{
RemoveEntryList(&ImageRecord->Link);
FreePool(ImageRecord);
return EFI_SUCCESS;
}
//=====================================================================
// CoreIsImageExitable @ 0x9c50
//=====================================================================
//
// Checks if a given image can be exited (unloaded). Only the image
// itself or a parent controller can unload it.
//
BOOLEAN
CoreIsImageExitable (
IN IMAGE_RECORD *ImageRecord,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData
)
{
//
// Validate that the image has been started and can be unloaded
//
if (ImageRecord->Started && !ImageRecord->Exitable) {
return FALSE;
}
return TRUE;
}
//=====================================================================
// PE/COFF Image Handling
//=====================================================================
//=====================================================================
// CoreGetPeCoffImageContext @ 0x18044 (179 bytes)
//=====================================================================
//
// Retrieves the PE/COFF image context including section alignment and
// debug information.
//
BOOLEAN
CoreGetPeCoffImageContext (
OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN VOID *PeCoffData
)
{
IMAGE_CONTEXT *Context;
BOOLEAN Result;
Context = ImageContext;
Result = PeCoffLoaderGetImageInfo(Context);
//
// Copy debug directory entry info
//
return Result;
}
//=====================================================================
// Dispatcher Functions
// Source: MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
//=====================================================================
//=====================================================================
// CoreDispatcher @ 0xcc94
//=====================================================================
//
// The main DXE driver dispatcher loop. Iterates through all discovered
// FVs, finds FFS files, evaluates dependency expressions, and loads/
// starts drivers whose dependencies are satisfied.
//
// This is the heart of the DXE phase: it processes the FV files
// iteratively until no more drivers can be started.
//
EFI_STATUS
EFIAPI
CoreDispatcher (
VOID
)
{
LIST_ENTRY *Link;
KNOWN_FV_ENTRY *FvEntry;
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
EFI_FFS_FILE_HEADER *FfsHeader;
EFI_FV_FILETYPE FileType;
EFI_FV_FILE_ATTRIBUTES Attributes;
UINTN Key;
UINTN Index;
EFI_STATUS Status;
//
// Walk through all registered firmware volumes
//
for (Link = gKnownFvList.ForwardLink;
Link != &gKnownFvList;
Link = Link->ForwardLink) {
FvEntry = CR(Link, KNOWN_FV_ENTRY, Link, KNOWN_FV_ENTRY_SIGNATURE);
FvProtocol = FvEntry->FvProtocol;
Key = 0;
do {
//
// Get the next file in the FV
//
Status = FvProtocol->GetNextFile(
FvProtocol,
&Key,
&FileType,
&Attributes,
&FfsHeader
);
if (EFI_ERROR(Status)) {
break;
}
//
// Process the file based on its type
//
switch (FileType) {
case EFI_FV_FILETYPE_DRIVER:
case EFI_FV_FILETYPE_DRIVER_EX:
case EFI_FV_FILETYPE_APPLICATION:
//
// Evaluate dependency expression
//
Status = CoreEvaluateDepex(FfsHeader, FvProtocol);
if (!EFI_ERROR(Status)) {
//
// Dependencies satisfied -- load and start the driver
//
Status = CoreLoadDxeImage(FfsHeader, FvProtocol);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "Failed to load driver: %r\n", Status));
}
}
break;
default:
break;
}
} while (TRUE);
}
//
// If no more drivers can be dispatched, wait for dependency events
//
return EFI_SUCCESS;
}
//=====================================================================
// End of DxeCore.c
//=====================================================================