进入点
DxeCoreEntryPoint = 0x6f0fdf0
DOS Header = 06f0d000

            
            
              C
              
              
            
          
          VOID
EFIAPI
_ModuleEntryPoint (
  IN VOID  *HobStart
  )
{
  //
  // Cache a pointer to the HobList
  //
  gHobList = HobStart;
  //
  // Call the DXE Core entry point
  //
  ProcessModuleEntryPointList (HobStart);
  //
  // Should never return
  //
  ASSERT (FALSE);
  CpuDeadLoop ();
}
        
            
            
              C
              
              
            
          
          VOID
EFIAPI
ProcessModuleEntryPointList (
  IN VOID  *HobStart
  )
{
  DxeMain (HobStart);
}
        DxeMain
代码总览:
            
            
              C
              
              
            
          
          VOID
EFIAPI
DxeMain (
  IN  VOID  *HobStart
  )
{
  EFI_STATUS                    Status;
  EFI_PHYSICAL_ADDRESS          MemoryBaseAddress;
  UINT64                        MemoryLength;
  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
  UINTN                         Index;
  EFI_HOB_GUID_TYPE             *GuidHob;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfoList;
  EFI_VECTOR_HANDOFF_INFO       *VectorInfo;
  VOID                          *EntryPoint;
  //
  // Setup the default exception handlers
  //
  DEBUG((DEBUG_INFO,"Entry DxeMain\n"));
  //断点无效等到初始化debug时可用__debugbreak();
  VectorInfoList = NULL;
  GuidHob        = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *)(GET_GUID_HOB_DATA (GuidHob));
  }
  Status = InitializeCpuExceptionHandlers (VectorInfoList);
  ASSERT_EFI_ERROR (Status);
  //
  // Setup Stack Guard
  //
  if (PcdGetBool (PcdCpuStackGuard)) {
    Status = InitializeSeparateExceptionStacks (NULL, NULL);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Initialize Debug Agent to support source level debug in DXE phase
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE, HobStart, NULL);
  __debugbreak();
  //
  // Initialize Memory Services
  //
  CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
  MemoryProfileInit (HobStart);
  //
  // Start the Handle Services.
  //
  Status = CoreInitializeHandleServices ();
  ASSERT_EFI_ERROR (Status);
  //
  // Start the Image Services.
  //
  Status = CoreInitializeImageServices (HobStart);
  ASSERT_EFI_ERROR (Status);
  //
  // Initialize the Global Coherency Domain Services
  //
  Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
  ASSERT_EFI_ERROR (Status);
  //
  // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
  // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
  //
  gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
  ASSERT (gDxeCoreST != NULL);
  gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
  ASSERT (gDxeCoreRT != NULL);
  gDxeCoreST->RuntimeServices = gDxeCoreRT;
  //
  // Update DXE Core Loaded Image Protocol with allocated UEFI System Table
  //
  gDxeCoreLoadedImage->SystemTable = gDxeCoreST;
  //
  // Call constructor for all libraries
  //
  ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST);
  PERF_CROSSMODULE_END ("PEI");
  PERF_CROSSMODULE_BEGIN ("DXE");
  //
  // Log MemoryBaseAddress and MemoryLength again (from
  // CoreInitializeMemoryServices()), now that library constructors have
  // executed.
  //
  DEBUG ((
    DEBUG_INFO,
    "%a: MemoryBaseAddress=0x%Lx MemoryLength=0x%Lx\n",
    __func__,
    MemoryBaseAddress,
    MemoryLength
    ));
  //
  // Report DXE Core image information to the PE/COFF Extra Action Library
  //
  ZeroMem (&ImageContext, sizeof (ImageContext));
  ImageContext.ImageAddress  = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase;
  ImageContext.PdbPointer    = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
  ImageContext.SizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageContext.ImageAddress);
  Status                     = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageContext.ImageAddress, &EntryPoint);
  if (Status == EFI_SUCCESS) {
    ImageContext.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
  }
  ImageContext.Handle    = (VOID *)(UINTN)gDxeCoreLoadedImage->ImageBase;
  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
  //
  // Install the DXE Services Table into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDxeCoreDS);
  ASSERT_EFI_ERROR (Status);
  //
  // Install the HOB List into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
  ASSERT_EFI_ERROR (Status);
  //
  // Install Memory Type Information Table into the EFI System Tables's Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
  ASSERT_EFI_ERROR (Status);
  //
  // If Loading modules At fixed address feature is enabled, install Load moduels at fixed address
  // Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI
  // Code and Tseg base to load SMM driver.
  //
  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
    Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Report Status Code here for DXE_ENTRY_POINT once it is available
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT)
    );
  //
  // Create the aligned system table pointer structure that is used by external
  // debuggers to locate the system table...  Also, install debug image info
  // configuration table.
  //
  CoreInitializeDebugImageInfoTable ();
  CoreNewDebugImageInfoEntry (
    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
    gDxeCoreLoadedImage,
    gDxeCoreImageHandle
    );
  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "HOBLIST address in DXE = 0x%p\n", HobStart));
  DEBUG_CODE_BEGIN ();
  EFI_PEI_HOB_POINTERS  Hob;
  for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
      DEBUG ((
        DEBUG_INFO | DEBUG_LOAD,
        "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
        Hob.MemoryAllocation->AllocDescriptor.MemoryType,                      \
        Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,               \
        Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1
        ));
    }
  }
  for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
      DEBUG ((
        DEBUG_INFO | DEBUG_LOAD,
        "FV Hob            0x%0lx - 0x%0lx\n",
        Hob.FirmwareVolume->BaseAddress,
        Hob.FirmwareVolume->BaseAddress + Hob.FirmwareVolume->Length - 1
        ));
    } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
      DEBUG ((
        DEBUG_INFO | DEBUG_LOAD,
        "FV2 Hob           0x%0lx - 0x%0lx\n",
        Hob.FirmwareVolume2->BaseAddress,
        Hob.FirmwareVolume2->BaseAddress + Hob.FirmwareVolume2->Length - 1
        ));
      DEBUG ((
        DEBUG_INFO | DEBUG_LOAD,
        "                  %g - %g\n",
        &Hob.FirmwareVolume2->FvName,
        &Hob.FirmwareVolume2->FileName
        ));
    } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
      DEBUG ((
        DEBUG_INFO | DEBUG_LOAD,
        "FV3 Hob           0x%0lx - 0x%0lx - 0x%x - 0x%x\n",
        Hob.FirmwareVolume3->BaseAddress,
        Hob.FirmwareVolume3->BaseAddress + Hob.FirmwareVolume3->Length - 1,
        Hob.FirmwareVolume3->AuthenticationStatus,
        Hob.FirmwareVolume3->ExtractedFv
        ));
      if (Hob.FirmwareVolume3->ExtractedFv) {
        DEBUG ((
          DEBUG_INFO | DEBUG_LOAD,
          "                  %g - %g\n",
          &Hob.FirmwareVolume3->FvName,
          &Hob.FirmwareVolume3->FileName
          ));
      }
    }
  }
  DEBUG_CODE_END ();
  //
  // Initialize the Event Services
  //
  Status = CoreInitializeEventServices ();
  ASSERT_EFI_ERROR (Status);
  //
  // Give the debug agent a chance to initialize with events.
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE_LATE, HobStart, NULL);
  MemoryProfileInstallProtocol ();
  CoreInitializeMemoryAttributesTable ();
  CoreInitializeMemoryProtection ();
  //
  // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated,
  // and install configuration table
  //
  GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *)(GET_GUID_HOB_DATA (GuidHob));
    VectorInfo     = VectorInfoList;
    Index          = 1;
    while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
      VectorInfo++;
      Index++;
    }
    VectorInfo = AllocateCopyPool (sizeof (EFI_VECTOR_HANDOFF_INFO) * Index, (VOID *)VectorInfoList);
    ASSERT (VectorInfo != NULL);
    Status = CoreInstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *)VectorInfo);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs
  //
  // These Protocols are not architectural. This implementation is sharing code between
  // PEI and DXE in order to save FLASH space. These Protocols could also be implemented
  // as part of the DXE Core. However, that would also require the DXE Core to be ported
  // each time a different CPU is used, a different Decompression algorithm is used, or a
  // different Image type is used. By placing these Protocols in PEI, the DXE Core remains
  // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform,
  // and from CPU to CPU.
  //
  //
  // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components
  //
  Status = CoreInstallMultipleProtocolInterfaces (
             &mDecompressHandle,
             &gEfiDecompressProtocolGuid,
             &gEfiDecompress,
             NULL
             );
  ASSERT_EFI_ERROR (Status);
  //
  // Register for the GUIDs of the Architectural Protocols, so the rest of the
  // EFI Boot Services and EFI Runtime Services tables can be filled in.
  // Also register for the GUIDs of optional protocols.
  //
  CoreNotifyOnProtocolInstallation ();
  //
  // Produce Firmware Volume Protocols, one for each FV in the HOB list.
  //
  Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
  Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
  //
  // Produce the Section Extraction Protocol
  //
  Status = InitializeSectionExtraction (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
  //
  // Initialize the DXE Dispatcher
  //
  CoreInitializeDispatcher ();
  //
  // Invoke the DXE Dispatcher
  //
  CoreDispatcher ();
  //
  // Display Architectural protocols that were not loaded if this is DEBUG build
  //
  DEBUG_CODE_BEGIN ();
  CoreDisplayMissingArchProtocols ();
  DEBUG_CODE_END ();
  //
  // Display any drivers that were not dispatched because dependency expression
  // evaluated to false if this is a debug build
  //
  DEBUG_CODE_BEGIN ();
  CoreDisplayDiscoveredNotDispatched ();
  DEBUG_CODE_END ();
  //
  // Assert if the Architectural Protocols are not present.
  //
  Status = CoreAllEfiServicesAvailable ();
  if (EFI_ERROR (Status)) {
    //
    // Report Status code that some Architectural Protocols are not present.
    //
    REPORT_STATUS_CODE (
      EFI_ERROR_CODE | EFI_ERROR_MAJOR,
      (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_EC_NO_ARCH)
      );
  }
  ASSERT_EFI_ERROR (Status);
  //
  // Report Status code before transfer control to BDS
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)
    );
  //
  // Transfer control to the BDS Architectural Protocol
  //
  gBds->Entry (gBds);
  //
  // BDS should never return
  //
  ASSERT (FALSE);
  CpuDeadLoop ();
  UNREACHABLE ();
}
        1 设置默认的异常处理程序
            
            
              C
              
              
            
          
            VectorInfoList = NULL;
  GuidHob        = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *)(GET_GUID_HOB_DATA (GuidHob));
  }
  Status = InitializeCpuExceptionHandlers (VectorInfoList);
  ASSERT_EFI_ERROR (Status);
        通过HOB获取持久化向量传递信息,然后去初始化CPU异常处理程序
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlers (
  IN EFI_VECTOR_HANDOFF_INFO  *VectorInfo OPTIONAL
  )
{
  InitializeSpinLock (&mExceptionHandlerData.DisplayMessageSpinLock);
  return InitializeCpuExceptionHandlersWorker (VectorInfo, &mExceptionHandlerData);
}
        2 设置栈保护
            
            
              C
              
              
            
          
            if (PcdGetBool (PcdCpuStackGuard)) {
    Status = InitializeSeparateExceptionStacks (NULL, NULL);
    ASSERT_EFI_ERROR (Status);
  }
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
InitializeSeparateExceptionStacks (
  IN     VOID   *Buffer,
  IN OUT UINTN  *BufferSize
  )
{
  UINTN       LocalBufferSize;
  EFI_STATUS  Status;
  if ((Buffer == NULL) && (BufferSize == NULL)) {
    SetMem (mBuffer, sizeof (mBuffer), 0);
    LocalBufferSize = sizeof (mBuffer);
    Status          = ArchSetupExceptionStack (mBuffer, &LocalBufferSize);
    ASSERT_EFI_ERROR (Status);
    return Status;
  } else {
    return ArchSetupExceptionStack (Buffer, BufferSize);
  }
}
        3 初始化早期Debug代理
            
            
              C
              
              
            
          
            InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE, HobStart, NULL);
        
            
            
              C
              
              
            
          
          VOID
EFIAPI
InitializeDebugAgent (
  IN UINT32                InitFlag,
  IN VOID                  *Context  OPTIONAL,
  IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
  )
{
  UINT64               *MailboxLocation;
  DEBUG_AGENT_MAILBOX  *Mailbox;
  BOOLEAN              InterruptStatus;
  VOID                 *HobList;
  IA32_DESCRIPTOR      IdtDescriptor;
  IA32_DESCRIPTOR      *Ia32Idtr;
  IA32_IDT_ENTRY       *Ia32IdtEntry;
  BOOLEAN              PeriodicMode;
  UINTN                TimerCycle;
  if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
    //
    // Check if CPU APIC Timer is working, otherwise initialize it.
    //
    InitializeLocalApicSoftwareEnable (TRUE);
    GetApicTimerState (NULL, &PeriodicMode, NULL);
    TimerCycle = GetApicTimerInitCount ();
    if (!PeriodicMode || (TimerCycle == 0)) {
      InitializeDebugTimer (NULL, FALSE);
    }
    //
    // Invoked by AP, enable interrupt to let AP could receive IPI from other processors
    //
    EnableInterrupts ();
    return;
  }
  //
  // Disable Debug Timer interrupt
  //
  SaveAndSetDebugTimerInterrupt (FALSE);
  //
  // Save and disable original interrupt status
  //
  InterruptStatus = SaveAndDisableInterrupts ();
  //
  // Try to get mailbox firstly
  //
  HobList         = NULL;
  Mailbox         = NULL;
  MailboxLocation = NULL;
  switch (InitFlag) {
    case DEBUG_AGENT_INIT_DXE_LOAD:
      //
      // Check if Debug Agent has been initialized before
      //
      if (IsDebugAgentInitialzed ()) {
        DEBUG ((DEBUG_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));
      }
      mMultiProcessorDebugSupport = TRUE;
      //
      // Save original IDT table
      //
      AsmReadIdtr (&IdtDescriptor);
      mSaveIdtTableSize = IdtDescriptor.Limit + 1;
      mSavedIdtTable    = AllocateCopyPool (mSaveIdtTableSize, (VOID *)IdtDescriptor.Base);
      //
      // Check if Debug Agent initialized in DXE phase
      //
      Mailbox = GetMailboxFromConfigurationTable ();
      if (Mailbox == NULL) {
        //
        // Try to get mailbox from GUIDed HOB build in PEI
        //
        HobList = GetHobList ();
        Mailbox = GetMailboxFromHob (HobList);
      }
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol
      // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()
      //
      InternalConstructorWorker ();
      //
      // Enable Debug Timer interrupt
      //
      SaveAndSetDebugTimerInterrupt (TRUE);
      //
      // Enable interrupt to receive Debug Timer interrupt
      //
      EnableInterrupts ();
      mDebugAgentInitialized = TRUE;
      FindAndReportModuleImageInfo (SIZE_4KB);
      *(EFI_STATUS *)Context = EFI_SUCCESS;
      break;
    case DEBUG_AGENT_INIT_DXE_UNLOAD:
      if (mDebugAgentInitialized) {
        if (IsHostAttached ()) {
          *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;
          //
          // Enable Debug Timer interrupt again
          //
          SaveAndSetDebugTimerInterrupt (TRUE);
        } else {
          //
          // Restore original IDT table
          //
          AsmReadIdtr (&IdtDescriptor);
          IdtDescriptor.Limit = (UINT16)(mSaveIdtTableSize - 1);
          CopyMem ((VOID *)IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);
          AsmWriteIdtr (&IdtDescriptor);
          FreePool (mSavedIdtTable);
          mDebugAgentInitialized = FALSE;
          *(EFI_STATUS *)Context = EFI_SUCCESS;
        }
      } else {
        *(EFI_STATUS *)Context = EFI_NOT_STARTED;
      }
      //
      // Restore interrupt state.
      //
      SetInterruptState (InterruptStatus);
      break;
    case DEBUG_AGENT_INIT_DXE_CORE:
      mDxeCoreFlag                = TRUE;
      mMultiProcessorDebugSupport = TRUE;
      //
      // Try to get mailbox from GUIDed HOB build in PEI
      //
      HobList = Context;
      Mailbox = GetMailboxFromHob (HobList);
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // Enable Debug Timer interrupt
      //
      SaveAndSetDebugTimerInterrupt (TRUE);
      //
      // Enable interrupt to receive Debug Timer interrupt
      //
      EnableInterrupts ();
      break;
    case DEBUG_AGENT_INIT_S3:
      if (Context != NULL) {
        Ia32Idtr        =  (IA32_DESCRIPTOR *)Context;
        Ia32IdtEntry    = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);
        MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
                                     ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
        Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
        VerifyMailboxChecksum (Mailbox);
      }
      //
      // Save Mailbox pointer in global variable
      //
      mMailboxPointer = Mailbox;
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // Disable interrupt
      //
      DisableInterrupts ();
      FindAndReportModuleImageInfo (SIZE_4KB);
      if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {
        //
        // If Boot Script entry break is set, code will be break at here.
        //
        CpuBreakpoint ();
      }
      break;
    case DEBUG_AGENT_INIT_REINITIALIZE:
    case DEBUG_AGENT_INIT_DXE_CORE_LATE:
      break;
    default:
      //
      // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
      // Debug Agent library instance.
      //
      DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
      CpuDeadLoop ();
      break;
  }
}
        4 初始化内存服务

图来源于 " UEFI Platform Initialization Specification Version 1.8 "

图来源于 " Unified Extensible Firmware Interface (UEFl) Specification, Release 2.11 "
            
            
              C
              
              
            
          
            CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
  MemoryProfileInit (HobStart);
        
            
            
              C
              
              
            
          
          EFI_STATUS
CoreInitializeMemoryServices (
  IN  VOID                  **HobStart,
  OUT EFI_PHYSICAL_ADDRESS  *MemoryBaseAddress,
  OUT UINT64                *MemoryLength
  )
{
  EFI_PEI_HOB_POINTERS         Hob;
  EFI_MEMORY_TYPE_INFORMATION  *EfiMemoryTypeInformation;
  UINTN                        DataSize;
  BOOLEAN                      Found;
  EFI_HOB_HANDOFF_INFO_TABLE   *PhitHob;
  EFI_HOB_RESOURCE_DESCRIPTOR  *ResourceHob;
  EFI_HOB_RESOURCE_DESCRIPTOR  *PhitResourceHob;
  EFI_HOB_RESOURCE_DESCRIPTOR  *MemoryTypeInformationResourceHob;
  UINTN                        Count;
  EFI_PHYSICAL_ADDRESS         BaseAddress;
  UINT64                       Length;
  UINT64                       Attributes;
  UINT64                       Capabilities;
  EFI_PHYSICAL_ADDRESS         TestedMemoryBaseAddress;
  UINT64                       TestedMemoryLength;
  EFI_PHYSICAL_ADDRESS         HighAddress;
  EFI_HOB_GUID_TYPE            *GuidHob;
  UINT32                       ReservedCodePageNumber;
  UINT64                       MinimalMemorySizeNeeded;
  //
  // Point at the first HOB.  This must be the PHIT HOB.
  //
  Hob.Raw = *HobStart;
  ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
  //
  // Initialize the spin locks and maps in the memory services.
  // Also fill in the memory services into the EFI Boot Services Table
  //
  CoreInitializePool ();
  //
  // Initialize Local Variables
  //
  PhitResourceHob = NULL;
  ResourceHob     = NULL;
  BaseAddress     = 0;
  Length          = 0;
  Attributes      = 0;
  //
  // Cache the PHIT HOB for later use
  //
  PhitHob = Hob.HandoffInformationTable;
  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
    ReservedCodePageNumber  = PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);
    ReservedCodePageNumber += PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);
    //
    // cache the Top address for loading modules at Fixed Address
    //
    gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop
                                                                  + EFI_PAGES_TO_SIZE (ReservedCodePageNumber);
  }
  //
  // See if a Memory Type Information HOB is available
  //
  MemoryTypeInformationResourceHob = NULL;
  GuidHob                          = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
  if (GuidHob != NULL) {
    EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
    DataSize                 = GET_GUID_HOB_DATA_SIZE (GuidHob);
    if ((EfiMemoryTypeInformation != NULL) && (DataSize > 0) && (DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION))) {
      CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
      //
      // Look for Resource Descriptor HOB with a ResourceType of System Memory
      // and an Owner GUID of gEfiMemoryTypeInformationGuid. If more than 1 is
      // found, then set MemoryTypeInformationResourceHob to NULL.
      //
      Count = 0;
      for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
        if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
          continue;
        }
        ResourceHob = Hob.ResourceDescriptor;
        if (!CompareGuid (&ResourceHob->Owner, &gEfiMemoryTypeInformationGuid)) {
          continue;
        }
        Count++;
        if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
          continue;
        }
        if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
          continue;
        }
        if (ResourceHob->ResourceLength >= CalculateTotalMemoryBinSizeNeeded ()) {
          MemoryTypeInformationResourceHob = ResourceHob;
        }
      }
      if (Count > 1) {
        MemoryTypeInformationResourceHob = NULL;
      }
    }
  }
  //
  // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
  //
  MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();
  //
  // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
  //
  Found = FALSE;
  for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    //
    // Skip all HOBs except Resource Descriptor HOBs
    //
    if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
      continue;
    }
    //
    // Skip Resource Descriptor HOBs that do not describe tested system memory
    //
    ResourceHob = Hob.ResourceDescriptor;
    if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
      continue;
    }
    if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
      continue;
    }
    //
    // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
    //
    if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {
      continue;
    }
    if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
      continue;
    }
    //
    // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
    //
    PhitResourceHob = ResourceHob;
    Found           = TRUE;
    //
    // If a Memory Type Information Resource HOB was found and is the same
    // Resource HOB that describes the PHIT HOB, then ignore the Memory Type
    // Information Resource HOB.
    //
    if (MemoryTypeInformationResourceHob == PhitResourceHob) {
      MemoryTypeInformationResourceHob = NULL;
    }
    //
    // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
    //
    Attributes  = PhitResourceHob->ResourceAttribute;
    BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
    Length      = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
    FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
    if (Length < MinimalMemorySizeNeeded) {
      //
      // If that range is not large enough to intialize the DXE Core, then
      // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
      //
      BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
      Length      = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
      // This region is required to have no memory allocation inside it, skip check for entries in HOB List
      if (Length < MinimalMemorySizeNeeded) {
        //
        // If that range is not large enough to intialize the DXE Core, then
        // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
        //
        BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
        Length      = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
        FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
      }
    }
    break;
  }
  //
  // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
  //
  ASSERT (Found);
  //
  // Take the range in the resource descriptor HOB for the memory region described
  // by the PHIT as higher priority if it is big enough. It can make the memory bin
  // allocated to be at the same memory region with PHIT that has more better compatibility
  // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
  //
  if (Length < MinimalMemorySizeNeeded) {
    //
    // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
    // region that is big enough to initialize the DXE core.  Always skip the PHIT Resource HOB
    // and the Memory Type Information Resource HOB. The max address must be within the physically
    // addressable range for the processor.
    //
    HighAddress = MAX_ALLOC_ADDRESS;
    for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
      //
      // Skip the Resource Descriptor HOB that contains the PHIT
      //
      if (Hob.ResourceDescriptor == PhitResourceHob) {
        continue;
      }
      //
      // Skip the Resource Descriptor HOB that contains Memory Type Information bins
      //
      if (Hob.ResourceDescriptor == MemoryTypeInformationResourceHob) {
        continue;
      }
      //
      // Skip all HOBs except Resource Descriptor HOBs
      //
      if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
        continue;
      }
      //
      // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ALLOC_ADDRESS
      //
      ResourceHob = Hob.ResourceDescriptor;
      if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
        continue;
      }
      if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
        continue;
      }
      if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS) {
        continue;
      }
      //
      // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
      //
      if ((HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS) && (ResourceHob->PhysicalStart <= HighAddress)) {
        continue;
      }
      //
      // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
      //
      TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
      TestedMemoryLength      = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);
      FindLargestFreeRegion (&TestedMemoryBaseAddress, &TestedMemoryLength, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
      if (TestedMemoryLength < MinimalMemorySizeNeeded) {
        continue;
      }
      //
      // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
      //
      BaseAddress = TestedMemoryBaseAddress;
      Length      = TestedMemoryLength;
      Attributes  = ResourceHob->ResourceAttribute;
      HighAddress = ResourceHob->PhysicalStart;
    }
  }
  DEBUG ((DEBUG_INFO, "CoreInitializeMemoryServices:\n"));
  DEBUG ((DEBUG_INFO, "  BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress, Length, MinimalMemorySizeNeeded));
  //
  // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
  //
  ASSERT (Length >= MinimalMemorySizeNeeded);
  //
  // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
  //
  if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {
    Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);
  } else {
    Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
  }
  if (MemoryTypeInformationResourceHob != NULL) {
    //
    // If a Memory Type Information Resource HOB was found, then use the address
    // range of the  Memory Type Information Resource HOB as the preferred
    // address range for the Memory Type Information bins.
    //
    CoreSetMemoryTypeInformationRange (
      MemoryTypeInformationResourceHob->PhysicalStart,
      MemoryTypeInformationResourceHob->ResourceLength
      );
  }
  //
  // Declare the very first memory region, so the EFI Memory Services are available.
  //
  CoreAddMemoryDescriptor (
    EfiConventionalMemory,
    BaseAddress,
    RShiftU64 (Length, EFI_PAGE_SHIFT),
    Capabilities
    );
  *MemoryBaseAddress = BaseAddress;
  *MemoryLength      = Length;
  return EFI_SUCCESS;
}
        4.1 指出第一个HOB(PHIT HOB)
PHIT HOB是整个 HOB 列表的表头,由 PEI 阶段创建,必须放在列表最前面,用来告诉 DXE 阶段 HOB 列表在哪、有多大、当前内存布局怎样
            
            
              C
              
              
            
          
            Hob.Raw = *HobStart;
  ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
        4.2 初始化池
在 DXE 内核里划出一块常驻内存,做成固定大小的空闲链表
            
            
              C
              
              
            
          
            CoreInitializePool ();
        
            
            
              C
              
              
            
          
          VOID
CoreInitializePool (
  VOID
  )
{
  UINTN  Type;
  UINTN  Index;
  for (Type = 0; Type < EfiMaxMemoryType; Type++) {
    mPoolHead[Type].Signature  = 0;
    mPoolHead[Type].Used       = 0;
    mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE)Type;
    for (Index = 0; Index < MAX_POOL_LIST; Index++) {
      InitializeListHead (&mPoolHead[Type].FreeList[Index]);
    }
  }
}
        4.3 缓存 PHIT HOB
            
            
              C
              
              
            
          
            PhitHob = Hob.HandoffInformationTable;
  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
    ReservedCodePageNumber  = PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);
    ReservedCodePageNumber += PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);
    //
    // cache the Top address for loading modules at Fixed Address
    //
    gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop
                                                                  + EFI_PAGES_TO_SIZE (ReservedCodePageNumber);
  }
        4.4 检查内存类型信息表 HOB 是否有效

            
            
              C
              
              
            
          
            MemoryTypeInformationResourceHob = NULL;
  GuidHob                          = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
  if (GuidHob != NULL) {
    EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
    DataSize                 = GET_GUID_HOB_DATA_SIZE (GuidHob);
    if ((EfiMemoryTypeInformation != NULL) && (DataSize > 0) && (DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION))) {
      CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
      //
      // Look for Resource Descriptor HOB with a ResourceType of System Memory
      // and an Owner GUID of gEfiMemoryTypeInformationGuid. If more than 1 is
      // found, then set MemoryTypeInformationResourceHob to NULL.
      //
      Count = 0;
      for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
        if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
          continue;
        }
        ResourceHob = Hob.ResourceDescriptor;
        if (!CompareGuid (&ResourceHob->Owner, &gEfiMemoryTypeInformationGuid)) {
          continue;
        }
        Count++;
        if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
          continue;
        }
        if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
          continue;
        }
        if (ResourceHob->ResourceLength >= CalculateTotalMemoryBinSizeNeeded ()) {
          MemoryTypeInformationResourceHob = ResourceHob;
        }
      }
      if (Count > 1) {
        MemoryTypeInformationResourceHob = NULL;
      }
    }
  }
        4.5 计算所需的内存 bin 大小
内存 bin 大小是某个 Type 在内存类型信息里要的页数
            
            
              C
              
              
            
          
            MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();
        
            
            
              C
              
              
            
          
          UINT64
CalculateTotalMemoryBinSizeNeeded (
  VOID
  )
{
  UINTN   Index;
  UINT64  TotalSize;
  //
  // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
  //
  TotalSize = 0;
  for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
    TotalSize += LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT);
  }
  return TotalSize;
}
        4.6 查找资源描述表 HOB
            
            
              C
              
              
            
          
            Found = FALSE;
  for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    //
    // Skip all HOBs except Resource Descriptor HOBs
    //
    if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
      continue;
    }
    //
    // Skip Resource Descriptor HOBs that do not describe tested system memory
    //
    ResourceHob = Hob.ResourceDescriptor;
    if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
      continue;
    }
    if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
      continue;
    }
    //
    // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
    //
    if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {
      continue;
    }
    if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
      continue;
    }
    //
    // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
    //
    PhitResourceHob = ResourceHob;
    Found           = TRUE;
    //
    // If a Memory Type Information Resource HOB was found and is the same
    // Resource HOB that describes the PHIT HOB, then ignore the Memory Type
    // Information Resource HOB.
    //
    if (MemoryTypeInformationResourceHob == PhitResourceHob) {
      MemoryTypeInformationResourceHob = NULL;
    }
    //
    // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
    //
    Attributes  = PhitResourceHob->ResourceAttribute;
    BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
    Length      = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
    FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
    if (Length < MinimalMemorySizeNeeded) {
      //
      // If that range is not large enough to intialize the DXE Core, then
      // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
      //
      BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
      Length      = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
      // This region is required to have no memory allocation inside it, skip check for entries in HOB List
      if (Length < MinimalMemorySizeNeeded) {
        //
        // If that range is not large enough to intialize the DXE Core, then
        // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
        //
        BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
        Length      = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
        FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
      }
    }
    break;
  }
        4.7 生成 EFI 内存能力掩码
将资源描述表 HOB 里记录的那段物理内存的硬件属性翻译成 UEFI 规范定义的 EFI_MEMORY_CAPABILITIES 位掩码
            
            
              C
              
              
            
          
            if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {
    Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);
  } else {
    Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
  }
        4.8 为所需的内存类型划分区域
            
            
              C
              
              
            
          
            CoreAddMemoryDescriptor (
    EfiConventionalMemory,
    BaseAddress,
    RShiftU64 (Length, EFI_PAGE_SHIFT),
    Capabilities
    );
  *MemoryBaseAddress = BaseAddress;
  *MemoryLength      = Length;
        
            
            
              C
              
              
            
          
          VOID
CoreAddMemoryDescriptor (
  IN EFI_MEMORY_TYPE       Type,
  IN EFI_PHYSICAL_ADDRESS  Start,
  IN UINT64                NumberOfPages,
  IN UINT64                Attribute
  )
{
  EFI_PHYSICAL_ADDRESS  End;
  EFI_STATUS            Status;
  UINTN                 Index;
  UINTN                 FreeIndex;
  if ((Start & EFI_PAGE_MASK) != 0) {
    return;
  }
  if ((Type >= EfiMaxMemoryType) && (Type < MEMORY_TYPE_OEM_RESERVED_MIN)) {
    return;
  }
  CoreAcquireMemoryLock ();
  End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
  CoreAddRange (Type, Start, End, Attribute);
  CoreFreeMemoryMapStack ();
  CoreReleaseMemoryLock ();
  ApplyMemoryProtectionPolicy (
    EfiMaxMemoryType,
    Type,
    Start,
    LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT)
    );
  //
  // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type
  //
  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
    CoreLoadingFixedAddressHook ();
  }
  //
  // Check to see if the statistics for the different memory types have already been established
  //
  if (mMemoryTypeInformationInitialized) {
    return;
  }
  //
  // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
  //
  for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
    //
    // Make sure the memory type in the gMemoryTypeInformation[] array is valid
    //
    Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
    if ((UINT32)Type > EfiMaxMemoryType) {
      continue;
    }
    if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
      //
      // Allocate pages for the current memory type from the top of available memory
      //
      Status = CoreAllocatePages (
                 AllocateAnyPages,
                 Type,
                 gMemoryTypeInformation[Index].NumberOfPages,
                 &mMemoryTypeStatistics[Type].BaseAddress
                 );
      if (EFI_ERROR (Status)) {
        //
        // If an error occurs allocating the pages for the current memory type, then
        // free all the pages allocates for the previous memory types and return.  This
        // operation with be retied when/if more memory is added to the system
        //
        for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {
          //
          // Make sure the memory type in the gMemoryTypeInformation[] array is valid
          //
          Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[FreeIndex].Type);
          if ((UINT32)Type > EfiMaxMemoryType) {
            continue;
          }
          if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {
            CoreFreePages (
              mMemoryTypeStatistics[Type].BaseAddress,
              gMemoryTypeInformation[FreeIndex].NumberOfPages
              );
            mMemoryTypeStatistics[Type].BaseAddress    = 0;
            mMemoryTypeStatistics[Type].MaximumAddress = MAX_ALLOC_ADDRESS;
          }
        }
        return;
      }
      //
      // Compute the address at the top of the current statistics
      //
      mMemoryTypeStatistics[Type].MaximumAddress =
        mMemoryTypeStatistics[Type].BaseAddress +
        LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1;
      //
      // If the current base address is the lowest address so far, then update the default
      // maximum address
      //
      if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
        mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
      }
    }
  }
  //
  // There was enough system memory for all the the memory types were allocated.  So,
  // those memory areas can be freed for future allocations, and all future memory
  // allocations can occur within their respective bins
  //
  for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
    //
    // Make sure the memory type in the gMemoryTypeInformation[] array is valid
    //
    Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
    if ((UINT32)Type > EfiMaxMemoryType) {
      continue;
    }
    if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
      CoreFreePages (
        mMemoryTypeStatistics[Type].BaseAddress,
        gMemoryTypeInformation[Index].NumberOfPages
        );
      mMemoryTypeStatistics[Type].NumberOfPages   = gMemoryTypeInformation[Index].NumberOfPages;
      gMemoryTypeInformation[Index].NumberOfPages = 0;
    }
  }
  //
  // If the number of pages reserved for a memory type is 0, then all allocations for that type
  // should be in the default range.
  //
  for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
    for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
      if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
        mMemoryTypeStatistics[Type].InformationIndex = Index;
      }
    }
    mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
    if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) {
      mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
    }
  }
  mMemoryTypeInformationInitialized = TRUE;
}
        5 初始化内存配置文件
            
            
              C
              
              
            
          
          VOID
MemoryProfileInit (
  IN VOID  *HobStart
  )
{
  MEMORY_PROFILE_CONTEXT_DATA  *ContextData;
  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    return;
  }
  ContextData = GetMemoryProfileContext ();
  if (ContextData != NULL) {
    return;
  }
  mMemoryProfileGettingStatus = FALSE;
  if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
    mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
  } else {
    mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
  }
  mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
  mMemoryProfileDriverPath     = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
  mMemoryProfileContextPtr     = &mMemoryProfileContext;
  RegisterDxeCore (HobStart, &mMemoryProfileContext);
  DEBUG ((DEBUG_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));
}
        6 启动句柄服务
            
            
              C
              
              
            
          
          EFI_STATUS
CoreInitializeHandleServices (
  VOID
  )
{
  gOrderedHandleList = OrderedCollectionInit (PointerCompare, PointerCompare);
  if (gOrderedHandleList == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  return EFI_SUCCESS;
}
        
            
            
              C
              
              
            
          
          RED_BLACK_TREE *
EFIAPI
OrderedCollectionInit (
  IN RED_BLACK_TREE_USER_COMPARE  UserStructCompare,
  IN RED_BLACK_TREE_KEY_COMPARE   KeyCompare
  )
{
  RED_BLACK_TREE  *Tree;
  Tree = AllocatePool (sizeof *Tree);
  if (Tree == NULL) {
    return NULL;
  }
  Tree->Root              = NULL;
  Tree->UserStructCompare = UserStructCompare;
  Tree->KeyCompare        = KeyCompare;
  if (FeaturePcdGet (PcdValidateOrderedCollection)) {
    RedBlackTreeValidate (Tree);
  }
  return Tree;
}
        7 启动映像服务
            
            
              C
              
              
            
          
          EFI_STATUS
CoreInitializeImageServices (
  IN  VOID  *HobStart
  )
{
  EFI_STATUS                 Status;
  LOADED_IMAGE_PRIVATE_DATA  *Image;
  EFI_PHYSICAL_ADDRESS       DxeCoreImageBaseAddress;
  UINT64                     DxeCoreImageLength;
  VOID                       *DxeCoreEntryPoint;
  EFI_PEI_HOB_POINTERS       DxeCoreHob;
  //
  // Searching for image hob
  //
  DxeCoreHob.Raw = HobStart;
  while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
    if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
      //
      // Find Dxe Core HOB
      //
      break;
    }
    DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
  }
  ASSERT (DxeCoreHob.Raw != NULL);
  DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
  DxeCoreImageLength      = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
  DxeCoreEntryPoint       = (VOID *)(UINTN)DxeCoreHob.MemoryAllocationModule->EntryPoint;
  gDxeCoreFileName        = &DxeCoreHob.MemoryAllocationModule->ModuleName;
  //
  // Initialize the fields for an internal driver
  //
  Image = &mCorePrivateImage;
  Image->EntryPoint     = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
  Image->ImageBasePage  = DxeCoreImageBaseAddress;
  Image->NumberOfPages  = (UINTN)(EFI_SIZE_TO_PAGES ((UINTN)(DxeCoreImageLength)));
  Image->Tpl            = gEfiCurrentTpl;
  Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;
  Image->Info.ImageSize = DxeCoreImageLength;
  //
  // Install the protocol interfaces for this image
  //
  Status = CoreInstallProtocolInterface (
             &Image->Handle,
             &gEfiLoadedImageProtocolGuid,
             EFI_NATIVE_INTERFACE,
             &Image->Info
             );
  ASSERT_EFI_ERROR (Status);
  mCurrentImage = Image;
  //
  // Fill in DXE globals
  //
  mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);
  gDxeCoreImageHandle      = Image->Handle;
  gDxeCoreLoadedImage      = &Image->Info;
  //
  // Create the PE/COFF emulator protocol registration event
  //
  Status = CoreCreateEvent (
             EVT_NOTIFY_SIGNAL,
             TPL_CALLBACK,
             PeCoffEmuProtocolNotify,
             NULL,
             &mPeCoffEmuProtocolRegistrationEvent
             );
  ASSERT_EFI_ERROR (Status);
  //
  // Register for protocol notifications on this event
  //
  Status = CoreRegisterProtocolNotify (
             &gEdkiiPeCoffImageEmulatorProtocolGuid,
             mPeCoffEmuProtocolRegistrationEvent,
             &mPeCoffEmuProtocolNotifyRegistration
             );
  ASSERT_EFI_ERROR (Status);
  InitializeListHead (&mAvailableEmulators);
  ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
  return Status;
}
        寻找映像HOB -> 初始化内部映像的字段 -> 为映像安装协议接口 -> 填充 DXE 全局变量 -> 创建 PE/COFF 仿真器协议的注册事件 -> 为此事件注册协议通知
安装协议接口
https://blog.csdn.net/degen_/article/details/153976229
创建协议注册事件https://blog.csdn.net/degen_/article/details/154009562
注册协议通知
8 初始化全局一致性域(GCD)服务
GCD服务用于管理平台中的系统内存、内存映射I/O和I/O资源。调度服务用于调用DXE调度器,并修改DXE调度器跟踪的DXE驱动的状态。
            
            
              C
              
              
            
          
            Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
        
            
            
              C
              
              
            
          
          EFI_STATUS
CoreInitializeGcdServices (
  IN OUT VOID              **HobStart,
  IN EFI_PHYSICAL_ADDRESS  MemoryBaseAddress,
  IN UINT64                MemoryLength
  )
{
  EFI_PEI_HOB_POINTERS             Hob;
  VOID                             *NewHobList;
  EFI_HOB_HANDOFF_INFO_TABLE       *PhitHob;
  UINT8                            SizeOfMemorySpace;
  UINT8                            SizeOfIoSpace;
  EFI_HOB_RESOURCE_DESCRIPTOR      *ResourceHob;
  EFI_PHYSICAL_ADDRESS             BaseAddress;
  UINT64                           Length;
  EFI_STATUS                       Status;
  EFI_GCD_MAP_ENTRY                *Entry;
  EFI_GCD_MEMORY_TYPE              GcdMemoryType;
  EFI_GCD_IO_TYPE                  GcdIoType;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;
  EFI_HOB_MEMORY_ALLOCATION        *MemoryHob;
  EFI_HOB_FIRMWARE_VOLUME          *FirmwareVolumeHob;
  UINTN                            NumberOfDescriptors;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;
  UINTN                            Index;
  UINT64                           Capabilities;
  EFI_HOB_CPU                      *CpuHob;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMapHobList;
  //
  // Cache the PHIT HOB for later use
  //
  PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
  //
  // Get the number of address lines in the I/O and Memory space for the CPU
  //
  CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
  ASSERT (CpuHob != NULL);
  SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;
  SizeOfIoSpace     = CpuHob->SizeOfIoSpace;
  //
  // Initialize the GCD Memory Space Map
  //
  Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
  ASSERT (Entry != NULL);
  Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
  InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
  CoreDumpGcdMemorySpaceMap (TRUE);
  //
  // Initialize the GCD I/O Space Map
  //
  Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
  ASSERT (Entry != NULL);
  Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
  InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
  CoreDumpGcdIoSpaceMap (TRUE);
  //
  // Walk the HOB list and add all resource descriptors to the GCD
  //
  for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    GcdMemoryType = EfiGcdMemoryTypeNonExistent;
    GcdIoType     = EfiGcdIoTypeNonExistent;
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
      ResourceHob = Hob.ResourceDescriptor;
      switch (ResourceHob->ResourceType) {
        case EFI_RESOURCE_SYSTEM_MEMORY:
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
            if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {
              GcdMemoryType = EfiGcdMemoryTypeMoreReliable;
            } else {
              GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
            }
          }
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
            GcdMemoryType = EfiGcdMemoryTypeReserved;
          }
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
            GcdMemoryType = EfiGcdMemoryTypeReserved;
          }
          if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {
            GcdMemoryType = EfiGcdMemoryTypePersistent;
          }
          // Mark special purpose memory as system memory, if it was system memory in the HOB
          // However, if this is also marked as persistent, let persistent take precedence
          if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) == EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) {
            GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
          }
          break;
        case EFI_RESOURCE_MEMORY_MAPPED_IO:
        case EFI_RESOURCE_FIRMWARE_DEVICE:
          GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
          break;
        case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
        case EFI_RESOURCE_MEMORY_RESERVED:
          GcdMemoryType = EfiGcdMemoryTypeReserved;
          break;
        case EFI_RESOURCE_MEMORY_UNACCEPTED:
          GcdMemoryType = EfiGcdMemoryTypeUnaccepted;
          break;
        case EFI_RESOURCE_IO:
          GcdIoType = EfiGcdIoTypeIo;
          break;
        case EFI_RESOURCE_IO_RESERVED:
          GcdIoType = EfiGcdIoTypeReserved;
          break;
      }
      if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
        //
        // Validate the Resource HOB Attributes
        //
        CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);
        //
        // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
        //
        Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
                         GcdMemoryType,
                         ResourceHob->ResourceAttribute
                         );
        Status = CoreInternalAddMemorySpace (
                   GcdMemoryType,
                   ResourceHob->PhysicalStart,
                   ResourceHob->ResourceLength,
                   Capabilities
                   );
      }
      if (GcdIoType != EfiGcdIoTypeNonExistent) {
        Status = CoreAddIoSpace (
                   GcdIoType,
                   ResourceHob->PhysicalStart,
                   ResourceHob->ResourceLength
                   );
      }
    }
  }
  //
  // Allocate first memory region from the GCD by the DXE core
  //
  Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);
  if (!EFI_ERROR (Status)) {
    ASSERT (
      (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
      (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable)
      );
    Status = CoreAllocateMemorySpace (
               EfiGcdAllocateAddress,
               Descriptor.GcdMemoryType,
               0,
               MemoryLength,
               &MemoryBaseAddress,
               gDxeCoreImageHandle,
               NULL
               );
  }
  //
  // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
  // and Firmware Volume HOBs.  Also update the EFI Memory Map with the memory allocation HOBs.
  //
  for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
      MemoryHob   = Hob.MemoryAllocation;
      BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
      Status      = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
      if (!EFI_ERROR (Status)) {
        Status = CoreAllocateMemorySpace (
                   EfiGcdAllocateAddress,
                   Descriptor.GcdMemoryType,
                   0,
                   MemoryHob->AllocDescriptor.MemoryLength,
                   &BaseAddress,
                   gDxeCoreImageHandle,
                   NULL
                   );
        if (!EFI_ERROR (Status) &&
            ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
             (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable)))
        {
          CoreAddMemoryDescriptor (
            MemoryHob->AllocDescriptor.MemoryType,
            MemoryHob->AllocDescriptor.MemoryBaseAddress,
            RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
            Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
            );
        }
      }
    }
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
      FirmwareVolumeHob = Hob.FirmwareVolume;
      BaseAddress       = FirmwareVolumeHob->BaseAddress;
      Status            = CoreAllocateMemorySpace (
                            EfiGcdAllocateAddress,
                            EfiGcdMemoryTypeMemoryMappedIo,
                            0,
                            FirmwareVolumeHob->Length,
                            &BaseAddress,
                            gDxeCoreImageHandle,
                            NULL
                            );
    }
  }
  //
  // Add and allocate the remaining unallocated system memory to the memory services.
  //
  Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
  ASSERT (Status == EFI_SUCCESS);
  MemorySpaceMapHobList = NULL;
  for (Index = 0; Index < NumberOfDescriptors; Index++) {
    if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
        (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable))
    {
      if (MemorySpaceMap[Index].ImageHandle == NULL) {
        BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
        Length      = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
        if ((Length == 0) || (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress)) {
          continue;
        }
        if (((UINTN)MemorySpaceMap[Index].BaseAddress <= (UINTN)(*HobStart)) &&
            ((UINTN)(MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN)PhitHob->EfiFreeMemoryBottom))
        {
          //
          // Skip the memory space that covers HOB List, it should be processed
          // after HOB List relocation to avoid the resources allocated by others
          // to corrupt HOB List before its relocation.
          //
          MemorySpaceMapHobList = &MemorySpaceMap[Index];
          continue;
        }
        CoreAddMemoryDescriptor (
          EfiConventionalMemory,
          BaseAddress,
          RShiftU64 (Length, EFI_PAGE_SHIFT),
          MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
          );
        Status = CoreAllocateMemorySpace (
                   EfiGcdAllocateAddress,
                   MemorySpaceMap[Index].GcdMemoryType,
                   0,
                   Length,
                   &BaseAddress,
                   gDxeCoreImageHandle,
                   NULL
                   );
      }
    }
  }
  //
  // Relocate HOB List to an allocated pool buffer.
  // The relocation should be at after all the tested memory resources added
  // (except the memory space that covers HOB List) to the memory services,
  // because the memory resource found in CoreInitializeMemoryServices()
  // may have not enough remaining resource for HOB List.
  //
  NewHobList = AllocateCopyPool (
                 (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
                 *HobStart
                 );
  ASSERT (NewHobList != NULL);
  *HobStart = NewHobList;
  gHobList  = NewHobList;
  if (MemorySpaceMapHobList != NULL) {
    //
    // Add and allocate the memory space that covers HOB List to the memory services
    // after HOB List relocation.
    //
    BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);
    Length      = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);
    CoreAddMemoryDescriptor (
      EfiConventionalMemory,
      BaseAddress,
      RShiftU64 (Length, EFI_PAGE_SHIFT),
      MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)
      );
    Status = CoreAllocateMemorySpace (
               EfiGcdAllocateAddress,
               MemorySpaceMapHobList->GcdMemoryType,
               0,
               Length,
               &BaseAddress,
               gDxeCoreImageHandle,
               NULL
               );
  }
  CoreFreePool (MemorySpaceMap);
  return EFI_SUCCESS;
}
        8.1 缓存PHIT HOB
            
            
              C
              
              
            
          
            PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
        8.2 获取 CPU 在 I/O 和内存空间中的地址线数量
通过CPU HOB
            
            
              C
              
              
            
          
            CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
  ASSERT (CpuHob != NULL);
  SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;
  SizeOfIoSpace     = CpuHob->SizeOfIoSpace;
        8.3 初始化 GCD 内存空间映射
GCD Memory Space 状态:
- EfiGcdMemoryTypeNonExistent
 - EfiGcdMemoryTypeSystemMemory
 - EfiGcdMemoryTypeMemoryMappedIo
 - EfiGcdMemoryTypeReserved

图来源于 " UEFI Platform Initialization Specification Version 1.8 " 
            
            
              C
              
              
            
          
            Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
  ASSERT (Entry != NULL);
  Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
  InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
  CoreDumpGcdMemorySpaceMap (TRUE);
        8.4 初始化 GCD I/O 空间映射
GCD I/O Space 状态:
- EfiGcdIoTypeNonExistent
 - EfiGcdIoTypeIo
 - EfiGcdIoTypeReserved

 
图来源于 " UEFI Platform Initialization Specification Version 1.8 "
            
            
              C
              
              
            
          
            Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
  ASSERT (Entry != NULL);
  Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
  InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
  CoreDumpGcdIoSpaceMap (TRUE);
        8.5 添加资源描述符到 GCD
遍历 HOB 列表,将所有资源描述符添加到 GCD 中
            
            
              C
              
              
            
          
            for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    GcdMemoryType = EfiGcdMemoryTypeNonExistent;
    GcdIoType     = EfiGcdIoTypeNonExistent;
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
      ResourceHob = Hob.ResourceDescriptor;
      switch (ResourceHob->ResourceType) {
        case EFI_RESOURCE_SYSTEM_MEMORY:
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
            if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {
              GcdMemoryType = EfiGcdMemoryTypeMoreReliable;
            } else {
              GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
            }
          }
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
            GcdMemoryType = EfiGcdMemoryTypeReserved;
          }
          if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
            GcdMemoryType = EfiGcdMemoryTypeReserved;
          }
          if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {
            GcdMemoryType = EfiGcdMemoryTypePersistent;
          }
          // Mark special purpose memory as system memory, if it was system memory in the HOB
          // However, if this is also marked as persistent, let persistent take precedence
          if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) == EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) {
            GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
          }
          break;
        case EFI_RESOURCE_MEMORY_MAPPED_IO:
        case EFI_RESOURCE_FIRMWARE_DEVICE:
          GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
          break;
        case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
        case EFI_RESOURCE_MEMORY_RESERVED:
          GcdMemoryType = EfiGcdMemoryTypeReserved;
          break;
        case EFI_RESOURCE_MEMORY_UNACCEPTED:
          GcdMemoryType = EfiGcdMemoryTypeUnaccepted;
          break;
        case EFI_RESOURCE_IO:
          GcdIoType = EfiGcdIoTypeIo;
          break;
        case EFI_RESOURCE_IO_RESERVED:
          GcdIoType = EfiGcdIoTypeReserved;
          break;
      }
      if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
        //
        // Validate the Resource HOB Attributes
        //
        CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);
        //
        // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
        //
        Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
                         GcdMemoryType,
                         ResourceHob->ResourceAttribute
                         );
        Status = CoreInternalAddMemorySpace (
                   GcdMemoryType,
                   ResourceHob->PhysicalStart,
                   ResourceHob->ResourceLength,
                   Capabilities
                   );
      }
      if (GcdIoType != EfiGcdIoTypeNonExistent) {
        Status = CoreAddIoSpace (
                   GcdIoType,
                   ResourceHob->PhysicalStart,
                   ResourceHob->ResourceLength
                   );
      }
    }
  }
        8.6 从 GCD 分配第一个内存区域
            
            
              C
              
              
            
          
            Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);
  if (!EFI_ERROR (Status)) {
    ASSERT (
      (Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
      (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable)
      );
    Status = CoreAllocateMemorySpace (
               EfiGcdAllocateAddress,
               Descriptor.GcdMemoryType,
               0,
               MemoryLength,
               &MemoryBaseAddress,
               gDxeCoreImageHandle,
               NULL
               );
  }
        8.7 分配被占用的内存空间并更新到内存映射
遍历 HOB 列表,分配被内存分配 HOB 和固件卷 HOB 占用的内存空间并将内存分配 HOB 更新到内存映射中
            
            
              C
              
              
            
          
            for (Hob.Raw = *HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
      MemoryHob   = Hob.MemoryAllocation;
      BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
      Status      = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
      if (!EFI_ERROR (Status)) {
        Status = CoreAllocateMemorySpace (
                   EfiGcdAllocateAddress,
                   Descriptor.GcdMemoryType,
                   0,
                   MemoryHob->AllocDescriptor.MemoryLength,
                   &BaseAddress,
                   gDxeCoreImageHandle,
                   NULL
                   );
        if (!EFI_ERROR (Status) &&
            ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
             (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable)))
        {
          CoreAddMemoryDescriptor (
            MemoryHob->AllocDescriptor.MemoryType,
            MemoryHob->AllocDescriptor.MemoryBaseAddress,
            RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
            Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
            );
        }
      }
    }
    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
      FirmwareVolumeHob = Hob.FirmwareVolume;
      BaseAddress       = FirmwareVolumeHob->BaseAddress;
      Status            = CoreAllocateMemorySpace (
                            EfiGcdAllocateAddress,
                            EfiGcdMemoryTypeMemoryMappedIo,
                            0,
                            FirmwareVolumeHob->Length,
                            &BaseAddress,
                            gDxeCoreImageHandle,
                            NULL
                            );
    }
  }
        8.8 添加并分配未分配的系统内存到内存服务
            
            
              C
              
              
            
          
            Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
  ASSERT (Status == EFI_SUCCESS);
  MemorySpaceMapHobList = NULL;
  for (Index = 0; Index < NumberOfDescriptors; Index++) {
    if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
        (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable))
    {
      if (MemorySpaceMap[Index].ImageHandle == NULL) {
        BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
        Length      = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
        if ((Length == 0) || (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress)) {
          continue;
        }
        if (((UINTN)MemorySpaceMap[Index].BaseAddress <= (UINTN)(*HobStart)) &&
            ((UINTN)(MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN)PhitHob->EfiFreeMemoryBottom))
        {
          //
          // Skip the memory space that covers HOB List, it should be processed
          // after HOB List relocation to avoid the resources allocated by others
          // to corrupt HOB List before its relocation.
          //
          MemorySpaceMapHobList = &MemorySpaceMap[Index];
          continue;
        }
        CoreAddMemoryDescriptor (
          EfiConventionalMemory,
          BaseAddress,
          RShiftU64 (Length, EFI_PAGE_SHIFT),
          MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
          );
        Status = CoreAllocateMemorySpace (
                   EfiGcdAllocateAddress,
                   MemorySpaceMap[Index].GcdMemoryType,
                   0,
                   Length,
                   &BaseAddress,
                   gDxeCoreImageHandle,
                   NULL
                   );
      }
    }
  }
        8.9 重定位 HOB 列表到已分配的系统内存(池缓冲区)中
            
            
              C
              
              
            
          
            NewHobList = AllocateCopyPool (
                 (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
                 *HobStart
                 );
  ASSERT (NewHobList != NULL);
  *HobStart = NewHobList;
  gHobList  = NewHobList;
  if (MemorySpaceMapHobList != NULL) {
    //
    // Add and allocate the memory space that covers HOB List to the memory services
    // after HOB List relocation.
    //
    BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);
    Length      = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);
    CoreAddMemoryDescriptor (
      EfiConventionalMemory,
      BaseAddress,
      RShiftU64 (Length, EFI_PAGE_SHIFT),
      MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)
      );
    Status = CoreAllocateMemorySpace (
               EfiGcdAllocateAddress,
               MemorySpaceMapHobList->GcdMemoryType,
               0,
               Length,
               &BaseAddress,
               gDxeCoreImageHandle,
               NULL
               );
  }
  CoreFreePool (MemorySpaceMap);
        9 分配 EFI 系统表和 EFI 运行时服务表
9.1 EFI系统表
            
            
              C
              
              
            
          
          typedef struct {
  ///
  /// The table header for the EFI System Table.
  ///
  EFI_TABLE_HEADER                   Hdr;
  ///
  /// A pointer to a null terminated string that identifies the vendor
  /// that produces the system firmware for the platform.
  ///
  CHAR16                             *FirmwareVendor;
  ///
  /// A firmware vendor specific value that identifies the revision
  /// of the system firmware for the platform.
  ///
  UINT32                             FirmwareRevision;
  ///
  /// The handle for the active console input device. This handle must support
  /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. If
  /// there is no active console, these protocols must still be present.
  ///
  EFI_HANDLE                         ConsoleInHandle;
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is
  /// associated with ConsoleInHandle.
  ///
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL     *ConIn;
  ///
  /// The handle for the active console output device. This handle must support the
  /// EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there is no active console, these protocols
  /// must still be present.
  ///
  EFI_HANDLE                         ConsoleOutHandle;
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
  /// that is associated with ConsoleOutHandle.
  ///
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *ConOut;
  ///
  /// The handle for the active standard error console device.
  /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. If there
  /// is no active console, this protocol must still be present.
  ///
  EFI_HANDLE                         StandardErrorHandle;
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
  /// that is associated with StandardErrorHandle.
  ///
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *StdErr;
  ///
  /// A pointer to the EFI Runtime Services Table.
  ///
  EFI_RUNTIME_SERVICES               *RuntimeServices;
  ///
  /// A pointer to the EFI Boot Services Table.
  ///
  EFI_BOOT_SERVICES                  *BootServices;
  ///
  /// The number of system configuration tables in the buffer ConfigurationTable.
  ///
  UINTN                              NumberOfTableEntries;
  ///
  /// A pointer to the system configuration tables.
  /// The number of entries in the table is NumberOfTableEntries.
  ///
  EFI_CONFIGURATION_TABLE            *ConfigurationTable;
} EFI_SYSTEM_TABLE;
        9.2 EFI 运行时服务表
            
            
              C
              
              
            
          
          typedef struct {
  ///
  /// The table header for the EFI Runtime Services Table.
  ///
  EFI_TABLE_HEADER                  Hdr;
  //
  // Time Services
  //
  EFI_GET_TIME                      GetTime;
  EFI_SET_TIME                      SetTime;
  EFI_GET_WAKEUP_TIME               GetWakeupTime;
  EFI_SET_WAKEUP_TIME               SetWakeupTime;
  //
  // Virtual Memory Services
  //
  EFI_SET_VIRTUAL_ADDRESS_MAP       SetVirtualAddressMap;
  EFI_CONVERT_POINTER               ConvertPointer;
  //
  // Variable Services
  //
  EFI_GET_VARIABLE                  GetVariable;
  EFI_GET_NEXT_VARIABLE_NAME        GetNextVariableName;
  EFI_SET_VARIABLE                  SetVariable;
  //
  // Miscellaneous Services
  //
  EFI_GET_NEXT_HIGH_MONO_COUNT      GetNextHighMonotonicCount;
  EFI_RESET_SYSTEM                  ResetSystem;
  //
  // UEFI 2.0 Capsule Services
  //
  EFI_UPDATE_CAPSULE                UpdateCapsule;
  EFI_QUERY_CAPSULE_CAPABILITIES    QueryCapsuleCapabilities;
  //
  // Miscellaneous UEFI 2.0 Service
  //
  EFI_QUERY_VARIABLE_INFO           QueryVariableInfo;
} EFI_RUNTIME_SERVICES;
        9.3 实现流程
            
            
              C
              
              
            
          
            gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
  ASSERT (gDxeCoreST != NULL);
  gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
  ASSERT (gDxeCoreRT != NULL);
  gDxeCoreST->RuntimeServices = gDxeCoreRT;
        
            
            
              C
              
              
            
          
          VOID *
EFIAPI
AllocateRuntimeCopyPool (
  IN UINTN       AllocationSize,
  IN CONST VOID  *Buffer
  )
{
  VOID  *NewBuffer;
  NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
  if (NewBuffer != NULL) {
    MemoryProfileLibRecord (
      (PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
      MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL,
      EfiRuntimeServicesData,
      NewBuffer,
      AllocationSize,
      NULL
      );
  }
  return NewBuffer;
}
        10 用ST更新 DXE 已加载的映像协议
            
            
              C
              
              
            
          
            gDxeCoreLoadedImage->SystemTable = gDxeCoreST;
        11 调用所有库的构造函数

            
            
              C
              
              
            
          
            ProcessLibraryConstructorList (gDxeCoreImageHandle, gDxeCoreST);
  PERF_CROSSMODULE_END ("PEI");
  PERF_CROSSMODULE_BEGIN ("DXE");
        
            
            
              C
              
              
            
          
          VOID
EFIAPI
ProcessLibraryConstructorList (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  Status = BaseDebugLibSerialPortConstructor ();
  ASSERT_RETURN_ERROR (Status);
  Status = UefiBootServicesTableLibConstructor (ImageHandle, SystemTable);
  ASSERT_EFI_ERROR (Status);
  Status = UefiRuntimeServicesTableLibConstructor (ImageHandle, SystemTable);
  ASSERT_EFI_ERROR (Status);
  Status = AcpiTimerLibConstructor ();
  ASSERT_RETURN_ERROR (Status);
  Status = UefiLibConstructor (ImageHandle, SystemTable);
  ASSERT_EFI_ERROR (Status);
  Status = DxeExtractGuidedSectionLibConstructor (ImageHandle, SystemTable);
  ASSERT_EFI_ERROR (Status);
  Status = DxeDebugAgentLibConstructor (ImageHandle, SystemTable);
  ASSERT_EFI_ERROR (Status);
  Status = LzmaDecompressLibConstructor ();
  ASSERT_RETURN_ERROR (Status);
}
        11.1 初始化串口库
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
BaseDebugLibSerialPortConstructor (
  VOID
  )
{
  return SerialPortInitialize ();
}
        
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
SerialPortInitialize (
  VOID
  )
{
  UINTN  Divisor;
  UINT8  OutputData;
  UINT8  Data;
  //
  // Map 5..8 to 0..3
  //
  Data = (UINT8)(gData - (UINT8)5);   //3
  //
  // Calculate divisor for baud generator
  //
  Divisor = 115200 / gBps;   
  //
  // Set communications format
  //
  OutputData = (UINT8)((DLAB << 7) | (gBreakSet << 6) | (gParity << 3) | (gStop << 2) | Data);//10xx0103
                      //    1              0                      0           1             3
  IoWrite8 (gUartBase + LCR_OFFSET, OutputData);
  //
  // Configure baud rate
  //
  IoWrite8 (gUartBase + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8));
  IoWrite8 (gUartBase + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff));
  //
  // Switch back to bank 0
  //
  OutputData = (UINT8)((gBreakSet << 6) | (gParity << 3) | (gStop << 2) | Data);
  IoWrite8 (gUartBase + LCR_OFFSET, OutputData);
  return RETURN_SUCCESS;
}
        11.2 缓存启动服务表指针
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
UefiBootServicesTableLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  //
  // Cache the Image Handle
  //
  gImageHandle = ImageHandle;
  ASSERT (gImageHandle != NULL);
  //
  // Cache pointer to the EFI System Table
  //
  gST = SystemTable;
  ASSERT (gST != NULL);
  //
  // Cache pointer to the EFI Boot Services Table
  //
  gBS = SystemTable->BootServices;
  ASSERT (gBS != NULL);
  return EFI_SUCCESS;
}
        11.3 缓存运行时服务表指针
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
UefiRuntimeServicesTableLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  //
  // Cache pointer to the EFI Runtime Services Table
  //
  gRT = SystemTable->RuntimeServices;
  ASSERT (gRT != NULL);
  return EFI_SUCCESS;
}
        11.4 缓存 ACPI 计时器计数地址
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
AcpiTimerLibConstructor (
  VOID
  )
{
  UINT16  HostBridgeDevId;
  UINTN   Pmba;
  UINT32  PmbaAndVal;
  UINT32  PmbaOrVal;
  UINTN   AcpiCtlReg;
  UINT8   AcpiEnBit;
  //
  // Query Host Bridge DID to determine platform type
  //
  HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
  switch (HostBridgeDevId) {
    case INTEL_82441_DEVICE_ID:
      Pmba       = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
      PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
      PmbaOrVal  = PIIX4_PMBA_VALUE;
      AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
      AcpiEnBit  = PIIX4_PMREGMISC_PMIOSE;
      break;
    case INTEL_Q35_MCH_DEVICE_ID:
      Pmba       = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
      PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
      PmbaOrVal  = ICH9_PMBASE_VALUE;
      AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
      AcpiEnBit  = ICH9_ACPI_CNTL_ACPI_EN;
      break;
    case CLOUDHV_DEVICE_ID:
      mAcpiTimerIoAddr =  CLOUDHV_ACPI_TIMER_IO_ADDRESS;
      return RETURN_SUCCESS;
    default:
      DEBUG ((
        DEBUG_ERROR,
        "%a: Unknown Host Bridge Device ID: 0x%04x\n",
        __func__,
        HostBridgeDevId
        ));
      ASSERT (FALSE);
      return RETURN_UNSUPPORTED;
  }
  //
  // Check to see if the Power Management Base Address is already enabled
  //
  if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
    //
    // If the Power Management Base Address is not programmed,
    // then program it now.
    //
    PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
    //
    // Enable PMBA I/O port decodes
    //
    PciOr8 (AcpiCtlReg, AcpiEnBit);
  }
  mAcpiTimerIoAddr = (PciRead32 (Pmba) & ~PMBA_RTE) + ACPI_TIMER_OFFSET;
  return RETURN_SUCCESS;
}
        11.5 初始化通用 UEFI 辅助函数库(当前阶段为空)
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
UefiLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  return EFI_SUCCESS;
}
        11.6 分配全局内存去存储已注册的 GUID 和处理器列表
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
DxeExtractGuidedSectionLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  return ReallocateExtractHandlerTable ();
}
        
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
ReallocateExtractHandlerTable (
  VOID
  )
{
  //
  // Reallocate memory for GuidTable
  //
  mExtractHandlerGuidTable = ReallocatePool (
                               mMaxNumberOfExtractHandler * sizeof (GUID),
                               (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (GUID),
                               mExtractHandlerGuidTable
                               );
  if (mExtractHandlerGuidTable == NULL) {
    goto Done;
  }
  //
  // Reallocate memory for Decode handler Table
  //
  mExtractDecodeHandlerTable = ReallocatePool (
                                 mMaxNumberOfExtractHandler * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER),
                                 (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (EXTRACT_GUIDED_SECTION_DECODE_HANDLER),
                                 mExtractDecodeHandlerTable
                                 );
  if (mExtractDecodeHandlerTable == NULL) {
    goto Done;
  }
  //
  // Reallocate memory for GetInfo handler Table
  //
  mExtractGetInfoHandlerTable = ReallocatePool (
                                  mMaxNumberOfExtractHandler * sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER),
                                  (mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE) * sizeof (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER),
                                  mExtractGetInfoHandlerTable
                                  );
  if (mExtractGetInfoHandlerTable == NULL) {
    goto Done;
  }
  //
  // Increase max handler number
  //
  mMaxNumberOfExtractHandler = mMaxNumberOfExtractHandler + EXTRACT_HANDLER_TABLE_SIZE;
  return RETURN_SUCCESS;
Done:
  if (mExtractHandlerGuidTable != NULL) {
    FreePool (mExtractHandlerGuidTable);
  }
  if (mExtractDecodeHandlerTable != NULL) {
    FreePool (mExtractDecodeHandlerTable);
  }
  if (mExtractGetInfoHandlerTable != NULL) {
    FreePool (mExtractGetInfoHandlerTable);
  }
  return RETURN_OUT_OF_RESOURCES;
}
        11.7 调试代理的构造函数
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
DxeDebugAgentLibConstructor (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  if (mDxeCoreFlag) {
    //
    // Invoke internal constructor function only when DXE core links this library instance
    //
    InternalConstructorWorker ();
  }
  return RETURN_SUCCESS;
}
        
            
            
              C
              
              
            
          
          VOID
InternalConstructorWorker (
  VOID
  )
{
  EFI_STATUS               Status;
  EFI_PHYSICAL_ADDRESS     Address;
  BOOLEAN                  DebugTimerInterruptState;
  DEBUG_AGENT_MAILBOX      *Mailbox;
  DEBUG_AGENT_MAILBOX      *NewMailbox;
  EFI_HOB_GUID_TYPE        *GuidHob;
  EFI_VECTOR_HANDOFF_INFO  *VectorHandoffInfo;
  //
  // Check persisted vector handoff info
  //
  Status  = EFI_SUCCESS;
  GuidHob = GetFirstGuidHob (&gEfiVectorHandoffInfoPpiGuid);
  if ((GuidHob != NULL) && !mDxeCoreFlag) {
    //
    // Check if configuration table is installed or not if GUIDed HOB existed,
    // only when Debug Agent is not linked by DXE Core
    //
    Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorHandoffInfo);
  }
  if ((GuidHob == NULL) || (Status != EFI_SUCCESS)) {
    //
    // Install configuration table for persisted vector handoff info if GUIDed HOB cannot be found or
    // configuration table does not exist
    //
    Status = gBS->InstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *)&mVectorHandoffInfoDebugAgent[0]);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
      CpuDeadLoop ();
    }
  }
  //
  // Install EFI Serial IO protocol on debug port
  //
  InstallSerialIo ();
  Address = 0;
  Status  = gBS->AllocatePages (
                   AllocateAnyPages,
                   EfiACPIMemoryNVS,
                   EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX) + PcdGet16 (PcdDebugPortHandleBufferSize)),
                   &Address
                   );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for mailbox!\n"));
    CpuDeadLoop ();
  }
  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
  NewMailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)Address;
  //
  // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox
  // and Debug Port Handle buffer may be free at runtime, SMM debug agent needs to access them
  //
  Mailbox = GetMailboxPointer ();
  CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
  CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16 (PcdDebugPortHandleBufferSize));
  //
  // Update Debug Port Handle in new Mailbox
  //
  UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));
  mMailboxPointer = NewMailbox;
  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
  Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *)mMailboxPointer);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to install configuration for mailbox!\n"));
    CpuDeadLoop ();
  }
}
        11.8 注册 Lzma 解压和 Lzma 解压前信息获取处理器
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
LzmaDecompressLibConstructor (
  VOID
  )
{
  return ExtractGuidedSectionRegisterHandlers (
           &gLzmaCustomDecompressGuid,
           LzmaGuidedSectionGetInfo,
           LzmaGuidedSectionExtraction
           );
}
        
            
            
              C
              
              
            
          
          RETURN_STATUS
EFIAPI
ExtractGuidedSectionRegisterHandlers (
  IN CONST  GUID                                     *SectionGuid,
  IN        EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER  GetInfoHandler,
  IN        EXTRACT_GUIDED_SECTION_DECODE_HANDLER    DecodeHandler
  )
{
  UINT32  Index;
  VOID    *GuidData;
  //
  // Check input parameter.
  //
  ASSERT (SectionGuid != NULL);
  ASSERT (GetInfoHandler != NULL);
  ASSERT (DecodeHandler != NULL);
  //
  // Search the match registered GetInfo handler for the input guided section.
  //
  for (Index = 0; Index < mNumberOfExtractHandler; Index++) {
    if (CompareGuid (&mExtractHandlerGuidTable[Index], SectionGuid)) {
      //
      // If the guided handler has been registered before, only update its handler.
      //
      mExtractDecodeHandlerTable[Index]  = DecodeHandler;
      mExtractGetInfoHandlerTable[Index] = GetInfoHandler;
      return RETURN_SUCCESS;
    }
  }
  //
  // Check the global table is enough to contain new Handler.
  //
  if (mNumberOfExtractHandler >= mMaxNumberOfExtractHandler) {
    if (ReallocateExtractHandlerTable () != RETURN_SUCCESS) {
      return RETURN_OUT_OF_RESOURCES;
    }
  }
  //
  // Register new Handler and guid value.
  //
  CopyGuid (&mExtractHandlerGuidTable[mNumberOfExtractHandler], SectionGuid);
  mExtractDecodeHandlerTable[mNumberOfExtractHandler]    = DecodeHandler;
  mExtractGetInfoHandlerTable[mNumberOfExtractHandler++] = GetInfoHandler;
  //
  // Install the Guided Section GUID configuration table to record the GUID itself.
  // Then the content of the configuration table buffer will be the same as the GUID value itself.
  //
  GuidData = AllocateCopyPool (sizeof (GUID), (VOID *)SectionGuid);
  if (GuidData != NULL) {
    gBS->InstallConfigurationTable ((EFI_GUID *)SectionGuid, GuidData);
  }
  return RETURN_SUCCESS;
}
        12 报告 DXE Core 映像信息
            
            
              C
              
              
            
          
            ZeroMem (&ImageContext, sizeof (ImageContext));
  ImageContext.ImageAddress  = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase;
  ImageContext.PdbPointer    = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
  ImageContext.SizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageContext.ImageAddress);
  Status                     = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageContext.ImageAddress, &EntryPoint);
  if (Status == EFI_SUCCESS) {
    ImageContext.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
  }
  ImageContext.Handle    = (VOID *)(UINTN)gDxeCoreLoadedImage->ImageBase;
  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
        13 安装 DXE 服务表到配置表
            
            
              C
              
              
            
          
            Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDxeCoreDS);
  ASSERT_EFI_ERROR (Status);
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
CoreInstallConfigurationTable (
  IN EFI_GUID  *Guid,
  IN VOID      *Table
  )
{
  UINTN                    Index;
  EFI_CONFIGURATION_TABLE  *EfiConfigurationTable;
  EFI_CONFIGURATION_TABLE  *OldTable;
  //
  // If Guid is NULL, then this operation cannot be performed
  //
  if (Guid == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  EfiConfigurationTable = gDxeCoreST->ConfigurationTable;
  //
  // Search all the table for an entry that matches Guid
  //
  for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) {
    if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) {
      break;
    }
  }
  if (Index < gDxeCoreST->NumberOfTableEntries) {
    //
    // A match was found, so this is either a modify or a delete operation
    //
    if (Table != NULL) {
      //
      // If Table is not NULL, then this is a modify operation.
      // Modify the table entry and return.
      //
      gDxeCoreST->ConfigurationTable[Index].VendorTable = Table;
      //
      // Signal Configuration Table change
      //
      CoreNotifySignalList (Guid);
      return EFI_SUCCESS;
    }
    //
    // A match was found and Table is NULL, so this is a delete operation.
    //
    gDxeCoreST->NumberOfTableEntries--;
    //
    // Copy over deleted entry
    //
    CopyMem (
      &(EfiConfigurationTable[Index]),
      &(gDxeCoreST->ConfigurationTable[Index + 1]),
      (gDxeCoreST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
      );
  } else {
    //
    // No matching GUIDs were found, so this is an add operation.
    //
    if (Table == NULL) {
      //
      // If Table is NULL on an add operation, then return an error.
      //
      return EFI_NOT_FOUND;
    }
    //
    // Assume that Index == gDxeCoreST->NumberOfTableEntries
    //
    if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
      //
      // Allocate a table with one additional entry.
      //
      mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
      EfiConfigurationTable     = AllocateRuntimePool (mSystemTableAllocateSize);
      if (EfiConfigurationTable == NULL) {
        //
        // If a new table could not be allocated, then return an error.
        //
        return EFI_OUT_OF_RESOURCES;
      }
      if (gDxeCoreST->ConfigurationTable != NULL) {
        //
        // Copy the old table to the new table.
        //
        CopyMem (
          EfiConfigurationTable,
          gDxeCoreST->ConfigurationTable,
          Index * sizeof (EFI_CONFIGURATION_TABLE)
          );
        //
        // Record the old table pointer.
        //
        OldTable = gDxeCoreST->ConfigurationTable;
        //
        // As the CoreInstallConfigurationTable() may be re-entered by CoreFreePool()
        // in its calling stack, updating System table to the new table pointer must
        // be done before calling CoreFreePool() to free the old table.
        // It can make sure the gDxeCoreST->ConfigurationTable point to the new table
        // and avoid the errors of use-after-free to the old table by the reenter of
        // CoreInstallConfigurationTable() in CoreFreePool()'s calling stack.
        //
        gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
        //
        // Free the old table after updating System Table to the new table pointer.
        //
        CoreFreePool (OldTable);
      } else {
        //
        // Update System Table
        //
        gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
      }
    }
    //
    // Fill in the new entry
    //
    CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid);
    EfiConfigurationTable[Index].VendorTable = Table;
    //
    // This is an add operation, so increment the number of table entries
    //
    gDxeCoreST->NumberOfTableEntries++;
  }
  //
  // Fix up the CRC-32 in the EFI System Table
  //
  CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
  //
  // Signal Configuration Table change
  //
  CoreNotifySignalList (Guid);
  return EFI_SUCCESS;
}
        14 安装 HOB 列表到配置表
            
            
              C
              
              
            
          
            Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
  ASSERT_EFI_ERROR (Status);
        与前面安装DXE服务表流程相同
15 安装内存类型信息表到配置表
            
            
              C
              
              
            
          
            Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
  ASSERT_EFI_ERROR (Status);
        与前面安装DXE服务表流程相同
16 若支持固定地址加载模块功能则安装对应配置表
            
            
              C
              
              
            
          
            if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
    Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);
    ASSERT_EFI_ERROR (Status);
  }
        OVMF不支持
17 DXE 入口点可用即报告状态代码
            
            
              C
              
              
            
          
            REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT)
    );
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
ReportStatusCode (
  IN EFI_STATUS_CODE_TYPE   Type,
  IN EFI_STATUS_CODE_VALUE  Value
  )
{
  return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL);
}
        
            
            
              C
              
              
            
          
          EFI_STATUS
InternalReportStatusCode (
  IN EFI_STATUS_CODE_TYPE   Type,
  IN EFI_STATUS_CODE_VALUE  Value,
  IN UINT32                 Instance,
  IN CONST EFI_GUID         *CallerId OPTIONAL,
  IN EFI_STATUS_CODE_DATA   *Data     OPTIONAL
  )
{
  if ((ReportProgressCodeEnabled () && (((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE)) ||
      (ReportErrorCodeEnabled () && (((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE)) ||
      (ReportDebugCodeEnabled () && (((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)))
  {
    //
    // If mReportStatusCodeLibStatusCodeProtocol is NULL, then check if Report Status Code Protocol is available in system.
    //
    InternalGetReportStatusCode ();
    if (mReportStatusCodeLibStatusCodeProtocol == NULL) {
      return EFI_UNSUPPORTED;
    }
    //
    // A Report Status Code Protocol is present in system, so pass in all the parameters to the service.
    //
    return mReportStatusCodeLibStatusCodeProtocol->ReportStatusCode (Type, Value, Instance, (EFI_GUID *)CallerId, Data);
  }
  return EFI_UNSUPPORTED;
}
        
            
            
              C
              
              
            
          
          VOID
InternalGetReportStatusCode (
  VOID
  )
{
  EFI_STATUS  Status;
  if (mReportStatusCodeLibStatusCodeProtocol != NULL) {
    return;
  }
  //
  // Check gBS just in case ReportStatusCode is called before gBS is initialized.
  //
  if ((gBS != NULL) && (gBS->LocateProtocol != NULL)) {
    Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID **)&mReportStatusCodeLibStatusCodeProtocol);
    if (EFI_ERROR (Status)) {
      mReportStatusCodeLibStatusCodeProtocol = NULL;
    }
  }
}
        18 创建对齐系统表指针结构并安装调试映像信息配置表
对齐系统表指针结构用于外部调试器定位系统表
            
            
              C
              
              
            
          
            CoreInitializeDebugImageInfoTable ();
  CoreNewDebugImageInfoEntry (
    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
    gDxeCoreLoadedImage,
    gDxeCoreImageHandle
    );
        18.1 CoreInitializeDebugImageInfoTable
            
            
              C
              
              
            
          
          VOID
CoreInitializeDebugImageInfoTable (
  VOID
  )
{
  EFI_STATUS            Status;
  UINTN                 Pages;
  EFI_PHYSICAL_ADDRESS  Memory;
  UINTN                 AlignedMemory;
  UINTN                 AlignmentMask;
  UINTN                 UnalignedPages;
  UINTN                 RealPages;
  //
  // Allocate 4M aligned page for the structure and fill in the data.
  // Ideally we would update the CRC now as well, but the service may not yet be available.
  // See comments in the CoreUpdateDebugTableCrc32() function below for details.
  //
  Pages         = EFI_SIZE_TO_PAGES (sizeof (EFI_SYSTEM_TABLE_POINTER));
  AlignmentMask = SIZE_4MB - 1;
  RealPages     = Pages + EFI_SIZE_TO_PAGES (SIZE_4MB);
  //
  // Attempt to allocate memory below PcdMaxEfiSystemTablePointerAddress
  // If PcdMaxEfiSystemTablePointerAddress is 0, then allocate memory below
  // MAX_ADDRESS
  //
  Memory = PcdGet64 (PcdMaxEfiSystemTablePointerAddress);
  if (Memory == 0) {
    Memory = MAX_ADDRESS;
  }
  Status = CoreAllocatePages (
             AllocateMaxAddress,
             EfiBootServicesData,
             RealPages,
             &Memory
             );
  if (EFI_ERROR (Status)) {
    if (PcdGet64 (PcdMaxEfiSystemTablePointerAddress) != 0) {
      DEBUG ((DEBUG_INFO, "Allocate memory for EFI_SYSTEM_TABLE_POINTER below PcdMaxEfiSystemTablePointerAddress failed. \
                          Retry to allocate memroy as close to the top of memory as feasible.\n"));
    }
    //
    // If the initial memory allocation fails, then reattempt allocation
    // as close to the top of memory as feasible.
    //
    Status = CoreAllocatePages (
               AllocateAnyPages,
               EfiBootServicesData,
               RealPages,
               &Memory
               );
    ASSERT_EFI_ERROR (Status);
    if (EFI_ERROR (Status)) {
      return;
    }
  }
  //
  // Free overallocated pages
  //
  AlignedMemory  = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
  UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
  if (UnalignedPages > 0) {
    //
    // Free first unaligned page(s).
    //
    Status = CoreFreePages (Memory, UnalignedPages);
    ASSERT_EFI_ERROR (Status);
  }
  Memory         = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
  UnalignedPages = RealPages - Pages - UnalignedPages;
  if (UnalignedPages > 0) {
    //
    // Free last unaligned page(s).
    //
    Status = CoreFreePages (Memory, UnalignedPages);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Set mDebugTable to the 4MB aligned allocated pages
  //
  mDebugTable = (EFI_SYSTEM_TABLE_POINTER  *)(AlignedMemory);
  ASSERT (mDebugTable != NULL);
  //
  // Initialize EFI_SYSTEM_TABLE_POINTER structure
  //
  mDebugTable->Signature          = EFI_SYSTEM_TABLE_SIGNATURE;
  mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreST;
  mDebugTable->Crc32              = 0;
  //
  // Install the EFI_SYSTEM_TABLE_POINTER structure in the EFI System
  // Configuration Table
  //
  Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
  ASSERT_EFI_ERROR (Status);
}
        分配一个 4 MiB 对齐的页面并填充数据 -> 尝试在 PcdMaxEfiSystemTablePointerAddress 以下分配内存 -> 释放超额分配的页面 -> 将 mDebugTable 设置为 4MB 对齐的已分配页面 -> 初始化 mDebugTable 结构 -> 安装DebugInfoTableHeader到配置表
18.2 CoreNewDebugImageInfoEntry
            
            
              C
              
              
            
          
          VOID
CoreNewDebugImageInfoEntry (
  IN  UINT32                     ImageInfoType,
  IN  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
  IN  EFI_HANDLE                 ImageHandle
  )
{
  EFI_DEBUG_IMAGE_INFO  *Table;
  EFI_DEBUG_IMAGE_INFO  *NewTable;
  UINTN                 Index;
  UINTN                 TableSize;
  //
  // Set the flag indicating that we're in the process of updating the table.
  //
  mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
  Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
  if (mDebugInfoTableHeader.TableSize >= mMaxTableEntries) {
    //
    //  Table is full, so re-allocate another page for a larger table...
    //
    TableSize = mMaxTableEntries * EFI_DEBUG_TABLE_ENTRY_SIZE;
    NewTable  = AllocateZeroPool (TableSize + EFI_PAGE_SIZE);
    if (NewTable == NULL) {
      mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
      return;
    }
    //
    // Copy the old table into the new one
    //
    CopyMem (NewTable, Table, TableSize);
    //
    // Free the old table
    //
    CoreFreePool (Table);
    //
    // Update the table header
    //
    Table                                        = NewTable;
    mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
    //
    // Enlarge the max table entries and set the first empty entry index to
    // be the original max table entries.
    //
    mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
  }
  // We always put the next entry at the end of the currently consumed table (i.e. first free entry)
  Index = mDebugInfoTableHeader.TableSize;
  //
  // Allocate data for new entry
  //
  Table[Index].NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
  if (Table[Index].NormalImage != NULL) {
    //
    // Update the entry
    //
    Table[Index].NormalImage->ImageInfoType               = (UINT32)ImageInfoType;
    Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
    Table[Index].NormalImage->ImageHandle                 = ImageHandle;
    //
    // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
    //
    mDebugInfoTableHeader.TableSize++;
    mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
  }
  mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
}
        19 初始化事件服务
            
            
              C
              
              
            
          
            Status = CoreInitializeEventServices ();
  ASSERT_EFI_ERROR (Status);
        
            
            
              C
              
              
            
          
          EFI_STATUS
CoreInitializeEventServices (
  VOID
  )
{
  UINTN  Index;
  for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) {
    InitializeListHead (&gEventQueue[Index]);
  }
  CoreInitializeTimer ();
  CoreCreateEventEx (
    EVT_NOTIFY_SIGNAL,
    TPL_NOTIFY,
    EfiEventEmptyFunction,
    NULL,
    &gIdleLoopEventGuid,
    &gIdleLoopEvent
    );
  return EFI_SUCCESS;
}
        19.1 初始化双向链表的头节点
            
            
              C
              
              
            
          
          LIST_ENTRY *
EFIAPI
InitializeListHead (
  IN OUT  LIST_ENTRY  *ListHead
  )
{
  ASSERT (ListHead != NULL);
  ListHead->ForwardLink = ListHead;
  ListHead->BackLink    = ListHead;
  return ListHead;
}
        19.2 初始化计时器支持
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
CoreCreateEventInternal (
  IN UINT32            Type,
  IN EFI_TPL           NotifyTpl,
  IN EFI_EVENT_NOTIFY  NotifyFunction  OPTIONAL,
  IN CONST VOID        *NotifyContext  OPTIONAL,
  IN CONST EFI_GUID    *EventGroup     OPTIONAL,
  OUT EFI_EVENT        *Event
  )
{
  EFI_STATUS  Status;
  IEVENT      *IEvent;
  INTN        Index;
  if (Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check to make sure no reserved flags are set
  //
  Status = EFI_INVALID_PARAMETER;
  for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
    if (Type == mEventTable[Index]) {
      Status = EFI_SUCCESS;
      break;
    }
  }
  if (EFI_ERROR (Status)) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Convert Event type for pre-defined Event groups
  //
  if (EventGroup != NULL) {
    //
    // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
    // are not valid
    //
    if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
      return EFI_INVALID_PARAMETER;
    }
    if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {
      Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;
    } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
      Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
    }
  } else {
    //
    // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping
    //
    if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {
      EventGroup = &gEfiEventExitBootServicesGuid;
    } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
      EventGroup = &gEfiEventVirtualAddressChangeGuid;
    }
  }
  //
  // If it's a notify type of event, check its parameters
  //
  if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
    //
    // Check for an invalid NotifyFunction or NotifyTpl
    //
    if ((NotifyFunction == NULL) ||
        (NotifyTpl <= TPL_APPLICATION) ||
        (NotifyTpl >= TPL_HIGH_LEVEL))
    {
      return EFI_INVALID_PARAMETER;
    }
  } else {
    //
    // No notification needed, zero ignored values
    //
    NotifyTpl      = 0;
    NotifyFunction = NULL;
    NotifyContext  = NULL;
  }
  //
  // Allocate and initialize a new event structure.
  //
  if ((Type & EVT_RUNTIME) != 0) {
    IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));
  } else {
    IEvent = AllocateZeroPool (sizeof (IEVENT));
  }
  if (IEvent == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  IEvent->Signature = EVENT_SIGNATURE;
  IEvent->Type      = Type;
  IEvent->NotifyTpl      = NotifyTpl;
  IEvent->NotifyFunction = NotifyFunction;
  IEvent->NotifyContext  = (VOID *)NotifyContext;
  if (EventGroup != NULL) {
    CopyGuid (&IEvent->EventGroup, EventGroup);
    IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP;
  }
  *Event = IEvent;
  if ((Type & EVT_RUNTIME) != 0) {
    //
    // Keep a list of all RT events so we can tell the RT AP.
    //
    IEvent->RuntimeData.Type           = Type;
    IEvent->RuntimeData.NotifyTpl      = NotifyTpl;
    IEvent->RuntimeData.NotifyFunction = NotifyFunction;
    IEvent->RuntimeData.NotifyContext  = (VOID *)NotifyContext;
    //
    // Work around the bug in the Platform Init specification (v1.7), reported
    // as Mantis#2017: "EFI_RUNTIME_EVENT_ENTRY.Event" should have type
    // EFI_EVENT, not (EFI_EVENT*). The PI spec documents the field correctly
    // as "The EFI_EVENT returned by CreateEvent()", but the type of the field
    // doesn't match the natural language description. Therefore we need an
    // explicit cast here.
    //
    IEvent->RuntimeData.Event = (EFI_EVENT *)IEvent;
    InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
  }
  CoreAcquireEventLock ();
  if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {
    //
    // The Event's NotifyFunction must be queued whenever the event is signaled
    //
    InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
  }
  CoreReleaseEventLock ();
  //
  // Done
  //
  return EFI_SUCCESS;
}
        19.3 为系统空闲循环提供通知事件
            
            
              C
              
              
            
          
            CoreCreateEventEx (
    EVT_NOTIFY_SIGNAL,
    TPL_NOTIFY,
    EfiEventEmptyFunction,
    NULL,
    &gIdleLoopEventGuid,
    &gIdleLoopEvent
    );
        20 给调试代理提供初始化事件的机会
            
            
              C
              
              
            
          
            InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE_LATE, HobStart, NULL);
  MemoryProfileInstallProtocol ();
  CoreInitializeMemoryAttributesTable ();
  CoreInitializeMemoryProtection ();
        20.1 初始化后期Debug代理
            
            
              C
              
              
            
          
          VOID
EFIAPI
InitializeDebugAgent (
  IN UINT32                InitFlag,
  IN VOID                  *Context  OPTIONAL,
  IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
  )
{
  UINT64               *MailboxLocation;
  DEBUG_AGENT_MAILBOX  *Mailbox;
  BOOLEAN              InterruptStatus;
  VOID                 *HobList;
  IA32_DESCRIPTOR      IdtDescriptor;
  IA32_DESCRIPTOR      *Ia32Idtr;
  IA32_IDT_ENTRY       *Ia32IdtEntry;
  BOOLEAN              PeriodicMode;
  UINTN                TimerCycle;
  DEBUG((DEBUG_INFO,"DxeDebugAgentLib\n"));
  if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
    //
    // Check if CPU APIC Timer is working, otherwise initialize it.
    //
    InitializeLocalApicSoftwareEnable (TRUE);
    GetApicTimerState (NULL, &PeriodicMode, NULL);
    TimerCycle = GetApicTimerInitCount ();
    if (!PeriodicMode || (TimerCycle == 0)) {
      InitializeDebugTimer (NULL, FALSE);
    }
    //
    // Invoked by AP, enable interrupt to let AP could receive IPI from other processors
    //
    EnableInterrupts ();
    return;
  }
  //
  // Disable Debug Timer interrupt
  //
  SaveAndSetDebugTimerInterrupt (FALSE);
  //
  // Save and disable original interrupt status
  //
  InterruptStatus = SaveAndDisableInterrupts ();
  //
  // Try to get mailbox firstly
  //
  HobList         = NULL;
  Mailbox         = NULL;
  MailboxLocation = NULL;
  switch (InitFlag) {
    case DEBUG_AGENT_INIT_DXE_LOAD:
      //
      // Check if Debug Agent has been initialized before
      //
      if (IsDebugAgentInitialzed ()) {
        DEBUG ((DEBUG_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));
      }
      mMultiProcessorDebugSupport = TRUE;
      //
      // Save original IDT table
      //
      AsmReadIdtr (&IdtDescriptor);
      mSaveIdtTableSize = IdtDescriptor.Limit + 1;
      mSavedIdtTable    = AllocateCopyPool (mSaveIdtTableSize, (VOID *)IdtDescriptor.Base);
      //
      // Check if Debug Agent initialized in DXE phase
      //
      Mailbox = GetMailboxFromConfigurationTable ();
      if (Mailbox == NULL) {
        //
        // Try to get mailbox from GUIDed HOB build in PEI
        //
        HobList = GetHobList ();
        Mailbox = GetMailboxFromHob (HobList);
      }
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol
      // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()
      //
      InternalConstructorWorker ();
      //
      // Enable Debug Timer interrupt
      //
      SaveAndSetDebugTimerInterrupt (TRUE);
      //
      // Enable interrupt to receive Debug Timer interrupt
      //
      EnableInterrupts ();
      mDebugAgentInitialized = TRUE;
      FindAndReportModuleImageInfo (SIZE_4KB);
      *(EFI_STATUS *)Context = EFI_SUCCESS;
      break;
    case DEBUG_AGENT_INIT_DXE_UNLOAD:
      if (mDebugAgentInitialized) {
        if (IsHostAttached ()) {
          *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;
          //
          // Enable Debug Timer interrupt again
          //
          SaveAndSetDebugTimerInterrupt (TRUE);
        } else {
          //
          // Restore original IDT table
          //
          AsmReadIdtr (&IdtDescriptor);
          IdtDescriptor.Limit = (UINT16)(mSaveIdtTableSize - 1);
          CopyMem ((VOID *)IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);
          AsmWriteIdtr (&IdtDescriptor);
          FreePool (mSavedIdtTable);
          mDebugAgentInitialized = FALSE;
          *(EFI_STATUS *)Context = EFI_SUCCESS;
        }
      } else {
        *(EFI_STATUS *)Context = EFI_NOT_STARTED;
      }
      //
      // Restore interrupt state.
      //
      SetInterruptState (InterruptStatus);
      break;
    case DEBUG_AGENT_INIT_DXE_CORE:
      mDxeCoreFlag                = TRUE;
      mMultiProcessorDebugSupport = TRUE;
      //
      // Try to get mailbox from GUIDed HOB build in PEI
      //
      HobList = Context;
      Mailbox = GetMailboxFromHob (HobList);
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // Enable Debug Timer interrupt
      //
      SaveAndSetDebugTimerInterrupt (TRUE);
      //
      // Enable interrupt to receive Debug Timer interrupt
      //
      EnableInterrupts ();
      break;
    case DEBUG_AGENT_INIT_S3:
      if (Context != NULL) {
        Ia32Idtr        =  (IA32_DESCRIPTOR *)Context;
        Ia32IdtEntry    = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);
        MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
                                     ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
        Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
        VerifyMailboxChecksum (Mailbox);
      }
      //
      // Save Mailbox pointer in global variable
      //
      mMailboxPointer = Mailbox;
      //
      // Set up Debug Agent Environment and try to connect HOST if required
      //
      SetupDebugAgentEnvironment (Mailbox);
      //
      // Disable interrupt
      //
      DisableInterrupts ();
      FindAndReportModuleImageInfo (SIZE_4KB);
      if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {
        //
        // If Boot Script entry break is set, code will be break at here.
        //
        CpuBreakpoint ();
      }
      break;
    case DEBUG_AGENT_INIT_REINITIALIZE:
    case DEBUG_AGENT_INIT_DXE_CORE_LATE:
      break;
    default:
      //
      // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
      // Debug Agent library instance.
      //
      DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
      CpuDeadLoop ();
      break;
  }
}
        20.2 安装内存配置文件协议
            
            
              C
              
              
            
          
          VOID
MemoryProfileInstallProtocol (
  VOID
  )
{
  EFI_HANDLE  Handle;
  EFI_STATUS  Status;
  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    return;
  }
  Handle = NULL;
  Status = CoreInstallMultipleProtocolInterfaces (
             &Handle,
             &gEdkiiMemoryProfileGuid,
             &mProfileProtocol,
             NULL
             );
  ASSERT_EFI_ERROR (Status);
}
        20.3 初始化内存状态表支持
            
            
              C
              
              
            
          
          VOID
EFIAPI
CoreInitializeMemoryAttributesTable (
  VOID
  )
{
  EFI_STATUS  Status;
  EFI_EVENT   ReadyToBootEvent;
  EFI_EVENT   EndOfDxeEvent;
  //
  // Construct the table at ReadyToBoot.
  //
  Status = CoreCreateEventInternal (
             EVT_NOTIFY_SIGNAL,
             TPL_CALLBACK,
             InstallMemoryAttributesTableOnReadyToBoot,
             NULL,
             &gEfiEventReadyToBootGuid,
             &ReadyToBootEvent
             );
  ASSERT_EFI_ERROR (Status);
  //
  // Construct the initial table at EndOfDxe,
  // then SMM can consume this information.
  // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
  // can run after it.
  //
  Status = CoreCreateEventInternal (
             EVT_NOTIFY_SIGNAL,
             TPL_NOTIFY,
             InstallMemoryAttributesTableOnEndOfDxe,
             NULL,
             &gEfiEndOfDxeEventGroupGuid,
             &EndOfDxeEvent
             );
  ASSERT_EFI_ERROR (Status);
  return;
}
        创建两个事件,分别在 ReadyToBoot 和 EndOfDxe 阶段触发
20.4 初始化内存保护支持
            
            
              C
              
              
            
          
          VOID
EFIAPI
CoreInitializeMemoryProtection (
  VOID
  )
{
  EFI_STATUS  Status;
  EFI_EVENT   Event;
  EFI_EVENT   EndOfDxeEvent;
  VOID        *Registration;
  mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy);
  InitializeListHead (&mProtectedImageRecordList);
  //
  // Sanity check the PcdDxeNxMemoryProtectionPolicy setting:
  // - code regions should have no EFI_MEMORY_XP attribute
  // - EfiConventionalMemory and EfiBootServicesData should use the
  //   same attribute
  //
  ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0);
  ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0);
  ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0);
  ASSERT (
    GetPermissionAttributeForMemoryType (EfiBootServicesData) ==
    GetPermissionAttributeForMemoryType (EfiConventionalMemory)
    );
  Status = CoreCreateEvent (
             EVT_NOTIFY_SIGNAL,
             TPL_CALLBACK,
             MemoryProtectionCpuArchProtocolNotify,
             NULL,
             &Event
             );
  ASSERT_EFI_ERROR (Status);
  //
  // Register for protocol notifactions on this event
  //
  Status = CoreRegisterProtocolNotify (
             &gEfiCpuArchProtocolGuid,
             Event,
             &Registration
             );
  ASSERT_EFI_ERROR (Status);
  // Register an event to populate the memory attribute protocol
  Status = CoreCreateEvent (
             EVT_NOTIFY_SIGNAL,
             TPL_CALLBACK,
             MemoryAttributeProtocolNotify,
             NULL,
             &Event
             );
  // if we fail to create the event or the protocol notify, we should still continue, we won't be able to query the
  // memory attributes on FreePages(), so we may encounter a driver or bootloader that has not set attributes back to
  // RW, but this matches the state of the world before this protocol was introduced, so it is not a regression.
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a - Failed to create event for the Memory Attribute Protocol notification: %r\n", __func__, Status));
    ASSERT_EFI_ERROR (Status);
  }
  // Register for protocol notification
  Status = CoreRegisterProtocolNotify (
             &gEfiMemoryAttributeProtocolGuid,
             Event,
             &Registration
             );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a - Failed to register for the Memory Attribute Protocol notification: %r\n", __func__, Status));
    ASSERT_EFI_ERROR (Status);
  }
  //
  // Register a callback to disable NULL pointer detection at EndOfDxe
  //
  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))
      == (BIT0|BIT7))
  {
    Status = CoreCreateEventEx (
               EVT_NOTIFY_SIGNAL,
               TPL_NOTIFY,
               DisableNullDetectionAtTheEndOfDxe,
               NULL,
               &gEfiEndOfDxeEventGroupGuid,
               &EndOfDxeEvent
               );
    ASSERT_EFI_ERROR (Status);
  }
  return;
}
        21 再次获取持久化向量传递信息并安装配置表
HobStart 可能已更新,故再次从 GUIDed HOB 获取持久化向量传递信息,并安装配置表。
            
            
              C
              
              
            
          
            GuidHob = GetNextGuidHob (&gEfiVectorHandoffInfoPpiGuid, HobStart);
  if (GuidHob != NULL) {
    VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *)(GET_GUID_HOB_DATA (GuidHob));
    VectorInfo     = VectorInfoList;
    Index          = 1;
    while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
      VectorInfo++;
      Index++;
    }
    VectorInfo = AllocateCopyPool (sizeof (EFI_VECTOR_HANDOFF_INFO) * Index, (VOID *)VectorInfoList);
    ASSERT (VectorInfo != NULL);
    Status = CoreInstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *)VectorInfo);
    ASSERT_EFI_ERROR (Status);
  }
        22 发布 EFI、Tiano 和自定义解压缩协议
            
            
              C
              
              
            
          
            Status = CoreInstallMultipleProtocolInterfaces (
             &mDecompressHandle,
             &gEfiDecompressProtocolGuid,
             &gEfiDecompress,
             NULL
             );
  ASSERT_EFI_ERROR (Status);
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
CoreInstallMultipleProtocolInterfaces (
  IN OUT EFI_HANDLE  *Handle,
  ...
  )
{
  VA_LIST     Args;
  EFI_STATUS  Status;
  EFI_GUID    *Protocol;
  VOID        *Interface;
  EFI_TPL     OldTpl;
  UINTN       Index;
  EFI_HANDLE  OldHandle;
  if (Handle == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Syncronize with notifcations.
  //
  OldTpl    = CoreRaiseTpl (TPL_NOTIFY);
  OldHandle = *Handle;
  //
  // Check for duplicate device path and install the protocol interfaces
  //
  VA_START (Args, Handle);
  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
    //
    // If protocol is NULL, then it's the end of the list
    //
    Protocol = VA_ARG (Args, EFI_GUID *);
    if (Protocol == NULL) {
      break;
    }
    Interface = VA_ARG (Args, VOID *);
    //
    // Make sure you are installing on top a device path that has already been added.
    //
    if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid) &&
        IsDevicePathInstalled (Interface))
    {
      Status = EFI_ALREADY_STARTED;
      continue;
    }
    //
    // Install it
    //
    Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
  }
  VA_END (Args);
  //
  // If there was an error, remove all the interfaces that were installed without any errors
  //
  if (EFI_ERROR (Status)) {
    //
    // Reset the va_arg back to the first argument.
    //
    VA_START (Args, Handle);
    for ( ; Index > 1; Index--) {
      Protocol  = VA_ARG (Args, EFI_GUID *);
      Interface = VA_ARG (Args, VOID *);
      CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
    }
    VA_END (Args);
    *Handle = OldHandle;
  }
  //
  // Done
  //
  CoreRestoreTpl (OldTpl);
  return Status;
}
        23 为架构协议和可选协议创建事件

            
            
              C
              
              
            
          
           CoreNotifyOnProtocolInstallation ();
        
            
            
              C
              
              
            
          
          VOID
CoreNotifyOnProtocolInstallation (
  VOID
  )
{
  CoreNotifyOnProtocolEntryTable (mArchProtocols);
  CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
}
        
            
            
              C
              
              
            
          
          VOID
CoreNotifyOnProtocolEntryTable (
  EFI_CORE_PROTOCOL_NOTIFY_ENTRY  *Entry
  )
{
  EFI_STATUS  Status;
  for ( ; Entry->ProtocolGuid != NULL; Entry++) {
    //
    // Create the event
    //
    Status = CoreCreateEvent (
               EVT_NOTIFY_SIGNAL,
               TPL_CALLBACK,
               GenericProtocolNotify,
               Entry,
               &Entry->Event
               );
    ASSERT_EFI_ERROR (Status);
    //
    // Register for protocol notifactions on this event
    //
    Status = CoreRegisterProtocolNotify (
               Entry->ProtocolGuid,
               Entry->Event,
               &Entry->Registration
               );
    ASSERT_EFI_ERROR (Status);
  }
}
        24 生成固件卷协议
            
            
              C
              
              
            
          
            Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
  Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
        24.1 FwVolBlockDriverInit
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
FwVolBlockDriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_PEI_HOB_POINTERS  FvHob;
  EFI_PEI_HOB_POINTERS  Fv3Hob;
  UINT32                AuthenticationStatus;
  //
  // Core Needs Firmware Volumes to function
  //
  FvHob.Raw = GetHobList ();
  while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
    AuthenticationStatus = 0;
    //
    // Get the authentication status propagated from PEI-phase to DXE.
    //
    Fv3Hob.Raw = GetHobList ();
    while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) {
      if ((Fv3Hob.FirmwareVolume3->BaseAddress == FvHob.FirmwareVolume->BaseAddress) &&
          (Fv3Hob.FirmwareVolume3->Length == FvHob.FirmwareVolume->Length))
      {
        AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus;
        break;
      }
      Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob);
    }
    //
    // Produce an FVB protocol for it
    //
    ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, AuthenticationStatus, NULL);
    FvHob.Raw = GET_NEXT_HOB (FvHob);
  }
  return EFI_SUCCESS;
}
        24.2 FwVolDriverInit
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
FwVolDriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (
                          &gEfiFirmwareVolumeBlockProtocolGuid,
                          TPL_CALLBACK,
                          NotifyFwVolBlock,
                          NULL,
                          &gEfiFwVolBlockNotifyReg
                          );
  return EFI_SUCCESS;
}
        
            
            
              C
              
              
            
          
          EFI_EVENT
EFIAPI
EfiCreateProtocolNotifyEvent (
  IN  EFI_GUID          *ProtocolGuid,
  IN  EFI_TPL           NotifyTpl,
  IN  EFI_EVENT_NOTIFY  NotifyFunction,
  IN  VOID              *NotifyContext   OPTIONAL,
  OUT VOID              **Registration
  )
{
  EFI_STATUS  Status;
  EFI_EVENT   Event;
  ASSERT (ProtocolGuid != NULL);
  ASSERT (NotifyFunction != NULL);
  ASSERT (Registration != NULL);
  //
  // Create the event
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  NotifyTpl,
                  NotifyFunction,
                  NotifyContext,
                  &Event
                  );
  ASSERT_EFI_ERROR (Status);
  //
  // Register for protocol notifications on this event
  //
  Status = gBS->RegisterProtocolNotify (
                  ProtocolGuid,
                  Event,
                  Registration
                  );
  ASSERT_EFI_ERROR (Status);
  //
  // Kick the event so we will perform an initial pass of
  // current installed drivers
  //
  gBS->SignalEvent (Event);
  return Event;
}
        25 生成段提取协议
            
            
              C
              
              
            
          
            Status = InitializeSectionExtraction (gDxeCoreImageHandle, gDxeCoreST);
  ASSERT_EFI_ERROR (Status);
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
InitializeSectionExtraction (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  EFI_GUID    *ExtractHandlerGuidTable;
  UINTN       ExtractHandlerNumber;
  //
  // Get custom extract guided section method guid list
  //
  ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
  Status = EFI_SUCCESS;
  //
  // Install custom guided extraction protocol
  //
  while (ExtractHandlerNumber-- > 0) {
    Status = CoreInstallProtocolInterface (
               &mSectionExtractionHandle,
               &ExtractHandlerGuidTable[ExtractHandlerNumber],
               EFI_NATIVE_INTERFACE,
               &mCustomGuidedSectionExtractionProtocol
               );
    ASSERT_EFI_ERROR (Status);
  }
  return Status;
}
        26 初始化 DXE 调度器(建立回调机制)
            
            
              C
              
              
            
          
            CoreInitializeDispatcher ();
        
            
            
              C
              
              
            
          
          VOID
CoreInitializeDispatcher (
  VOID
  )
{
  PERF_FUNCTION_BEGIN ();
  mFwVolEvent = EfiCreateProtocolNotifyEvent (
                  &gEfiFirmwareVolume2ProtocolGuid,
                  TPL_CALLBACK,
                  CoreFwVolEventProtocolNotify,
                  NULL,
                  &mFwVolEventRegistration
                  );
  PERF_FUNCTION_END ();
}
        27 调用DXE调度器
            
            
              C
              
              
            
          
            CoreDispatcher ();
        
            
            
              C
              
              
            
          
          EFI_STATUS
EFIAPI
CoreDispatcher (
  VOID
  )
{
  EFI_STATUS             Status;
  EFI_STATUS             ReturnStatus;
  LIST_ENTRY             *Link;
  EFI_CORE_DRIVER_ENTRY  *DriverEntry;
  BOOLEAN                ReadyToRun;
  EFI_EVENT              DxeDispatchEvent;
  PERF_FUNCTION_BEGIN ();
  if (gDispatcherRunning) {
    //
    // If the dispatcher is running don't let it be restarted.
    //
    return EFI_ALREADY_STARTED;
  }
  gDispatcherRunning = TRUE;
  Status = CoreCreateEventEx (
             EVT_NOTIFY_SIGNAL,
             TPL_NOTIFY,
             EfiEventEmptyFunction,
             NULL,
             &gEfiEventDxeDispatchGuid,
             &DxeDispatchEvent
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  ReturnStatus = EFI_NOT_FOUND;
  do {
    //
    // Drain the Scheduled Queue
    //
    while (!IsListEmpty (&mScheduledQueue)) {
      DriverEntry = CR (
                      mScheduledQueue.ForwardLink,
                      EFI_CORE_DRIVER_ENTRY,
                      ScheduledLink,
                      EFI_CORE_DRIVER_ENTRY_SIGNATURE
                      );
      //
      // Load the DXE Driver image into memory. If the Driver was transitioned from
      // Untrused to Scheduled it would have already been loaded so we may need to
      // skip the LoadImage
      //
      if ((DriverEntry->ImageHandle == NULL) && !DriverEntry->IsFvImage) {
        DEBUG ((DEBUG_INFO, "Loading driver %g\n", &DriverEntry->FileName));
        Status = CoreLoadImage (
                   FALSE,
                   gDxeCoreImageHandle,
                   DriverEntry->FvFileDevicePath,
                   NULL,
                   0,
                   &DriverEntry->ImageHandle
                   );
        //
        // Update the driver state to reflect that it's been loaded
        //
        if (EFI_ERROR (Status)) {
          CoreAcquireDispatcherLock ();
          if (Status == EFI_SECURITY_VIOLATION) {
            //
            // Take driver from Scheduled to Untrused state
            //
            DriverEntry->Untrusted = TRUE;
          } else {
            //
            // The DXE Driver could not be loaded, and do not attempt to load or start it again.
            // Take driver from Scheduled to Initialized.
            //
            // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
            //
            DriverEntry->Initialized = TRUE;
          }
          DriverEntry->Scheduled = FALSE;
          RemoveEntryList (&DriverEntry->ScheduledLink);
          CoreReleaseDispatcherLock ();
          //
          // If it's an error don't try the StartImage
          //
          continue;
        }
      }
      CoreAcquireDispatcherLock ();
      DriverEntry->Scheduled   = FALSE;
      DriverEntry->Initialized = TRUE;
      RemoveEntryList (&DriverEntry->ScheduledLink);
      CoreReleaseDispatcherLock ();
      if (DriverEntry->IsFvImage) {
        //
        // Produce a firmware volume block protocol for FvImage so it gets dispatched from.
        //
        Status = CoreProcessFvImageFile (DriverEntry->Fv, DriverEntry->FvHandle, &DriverEntry->FileName);
      } else {
        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
          EFI_PROGRESS_CODE,
          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN),
          &DriverEntry->ImageHandle,
          sizeof (DriverEntry->ImageHandle)
          );
        ASSERT (DriverEntry->ImageHandle != NULL);
        Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
        REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
          EFI_PROGRESS_CODE,
          (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END),
          &DriverEntry->ImageHandle,
          sizeof (DriverEntry->ImageHandle)
          );
      }
      ReturnStatus = EFI_SUCCESS;
    }
    //
    // Now DXE Dispatcher finished one round of dispatch, signal an event group
    // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend
    // on UEFI protocols
    //
    if (!EFI_ERROR (ReturnStatus)) {
      CoreSignalEvent (DxeDispatchEvent);
    }
    //
    // Search DriverList for items to place on Scheduled Queue
    //
    ReadyToRun = FALSE;
    for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
      DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
      if (DriverEntry->DepexProtocolError) {
        //
        // If Section Extraction Protocol did not let the Depex be read before retry the read
        //
        Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
      }
      if (DriverEntry->Dependent) {
        if (CoreIsSchedulable (DriverEntry)) {
          CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
          ReadyToRun = TRUE;
        }
      } else {
        if (DriverEntry->Unrequested) {
          DEBUG ((DEBUG_DISPATCH, "Evaluate DXE DEPEX for FFS(%g)\n", &DriverEntry->FileName));
          DEBUG ((DEBUG_DISPATCH, "  SOR                                             = Not Requested\n"));
          DEBUG ((DEBUG_DISPATCH, "  RESULT = FALSE\n"));
        }
      }
    }
  } while (ReadyToRun);
  //
  // Close DXE dispatch Event
  //
  CoreCloseEvent (DxeDispatchEvent);
  gDispatcherRunning = FALSE;
  PERF_FUNCTION_END ();
  return ReturnStatus;
}
        27.1 判断设置条件
            
            
              C
              
              
            
          
            PERF_FUNCTION_BEGIN ();
  if (gDispatcherRunning) {
    //
    // If the dispatcher is running don't let it be restarted.
    //
    return EFI_ALREADY_STARTED;
  }
  gDispatcherRunning = TRUE;
        27.2 创建事件
            
            
              C
              
              
            
          
            Status = CoreCreateEventEx (
             EVT_NOTIFY_SIGNAL,
             TPL_NOTIFY,
             EfiEventEmptyFunction,
             NULL,
             &gEfiEventDxeDispatchGuid,
             &DxeDispatchEvent
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  ReturnStatus = EFI_NOT_FOUND;
        27.3 耗尽调度队列
一次性把当前调度队列里所有已就绪的驱动映像全部加载并执行,直到队列为空
流程:
- 获取 DriverEntry
 - 加载 DXE Driver 映像到内存
 
- 转交控制权给已加载映像的入口点
 
DXE Driver:
- DEVICEPATHDXE
 - PCDDXE
 - AMDSEVDXE
 - REPORTSTATUSCODEROUTERRUNTIMEDXE
 - RUNTIMEDXE
 - SECURITYSTUBDXE
 - EBCDXE
 - CPUIO2DXE
 - CPUDXE
 - INCOMPATIBLEPCIDEVICESUPPORTDXE
 - PCIHOTPLUGINITDXE
 - RESETSYSTEMRUNTIMEDXE
 - METRONOME
 - HIIDATABASE
 - ACPITABLEDXE
 - S3SAVESTATEDXE
 - DPCDXE
 - IOMMUDXE
 - VIRTHSTIDXE
 - SMMACCESS2DXE
 - SMMCOMMUNICATIONBUFFERDXE
 - RNGDXE
 - STATUSCODEHANDLERRUNTIMEDXE
 - LOCALAPICTIMERDXE
 - PCIHOSTBRIDGEDXE
 - SETUPBROWSER
 - SMBIOSDXE
 - QEMUFWCFGACPIPLATFORM
 - LOGODXE
 - QEMURAMFBDXE
 - SMMCONTROL2DXE
 - CPUS3DATADXE
 - WATCHDOGTIMER
 - DRIVERHEALTHMANAGERDXE
 - RAMDISKDXE
 - DISPLAYENGINE
 - SMBIOSPLATFORMDXE
 - PISMMIPL
 - PISMMCORE
 - CPUIO2SMM
 - SMMLOCKBOX
 - PISMMCPUDXESMM
 - FVBSERVICESSMM
 - VARIABLESMM
 - CPUHOTPLUGSMM
 - SMMFAULTTOLERANTWRITEDXE
 - BOOTSCRIPTEXECUTORDXE
 - VARIABLESMMRUNTIMEDXE
 - PCRTC
 - SECUREBOOTCONFIGDXE
 - MONOTONICCOUNTERRUNTIMEDXE
 - CAPSULERUNTIMEDXE
 - BDSDXE
 - PLATFORMDXE
 - PCIBUSDXE
 - VIRTIOPCIDEVICEDXE
 - VIRTIO10
 - VIRTIOBLKDXE
 - VIRTIOSCSIDXE
 - VIRTIOSERIALDXE
 - VIRTIOKEYBOARDDXE
 - CONPLATFORMDXE
 - CONSPLITTERDXE
 - GRAPHICSCONSOLEDXE
 - TERMINALDXE
 - QEMUKERNELLOADERFSDXE
 - DISKIODXE
 - PARTITIONDXE
 - ENGLISHDXE
 - SCSIBUS
 - SCSIDISK
 - SATACONTROLLER
 - ATAATAPIPASSTHRUDXE
 - ATABUSDXE
 - NVMEXPRESSDXE
 - SIOBUSDXE
 - PS2KEYBOARDDXE
 - BOOTGRAPHICSRESOURCETABLEDXE
 - FAT
 - UDFDXE
 - VIRTIOFSDXE
 - HASH2DXECRYPTO
 - VIRTIONETDXE
 - UHCIDXE
 - EHCIDXE
 - XHCIDXE
 - USBBUSDXE
 - USBKBDXE
 - USBMASSSTORAGEDXE
 - QEMUVIDEODXE
 - VIRTIOGPUDXE
 - VIRTIORNGDXE
 - SDMMCPCIHCDXE
 - SDDXE
 - EMMCDXE
 
27.4 整个系统正在等下一个阶段被唤醒
