Newer
Older
AMI-Aptio-BIOS-Reversed / DxeCore / DxeMain / DxeMain.c
@Ajax Dong Ajax Dong 2 days ago 62 KB Init
// 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
//=====================================================================