UEFI中PEI階段概總

----------------------------------------整體流程

  1. UEFI一個重要特點就是其模塊化設計。PEI也是一個模塊,PEI Image的入口函數位_ModuleEntryPoit,該函數最終調用PEI模塊的入口函數PeiCore。
  2. 進入PeiCore後,首先根據SEC階段傳進來的信息設置Pei Core Services。
  3. 信息設置完成後,調用PeiDispatcher執行PEIM;
  4. 內存初始化。
  5. 當內存初始化後,系統會發生棧切換並重新進入PeiCore,重新進入到PeiCore後使用的內存是我們熟悉的內存。
  6. 待所有PEIM執行完後,調用PeiServices的LocatePpi服務得到DXE IPL PPI的Entry服務,這個Entry服務實際上是DxeLoadCore,它找出DXE Image的入口函數,執行DXE Image的入口函數並將HOB列表傳遞給DXE。

----------------------------------------特點

  • PEI階段資源依然十分有限,內存到了PEI後期才被初始化。其主要功能是爲DXE準備執行環境,將需要傳遞給DXE的信息組成HOB(Handoff Block)列表,最終將控制權交給DXE。
  • 從功能上講,PEI可分爲兩個部分:PEI C/PEIM
  • PEI Core Services(PEI Foundation)負責PEI基礎服務和流程;
  • PEIM(PEI Module)Dispatch。主要功能是找出系統中所有PEIM,並根據PEIM之間的依賴關係按順序執行PEIM。
  • PEI階段對系統的初始化主要是由PEIM完成的(CPU初始化、Chipset初始化、內存控制器初始化、IO控制器初始化、內存初始化等功能)。
  • 每個PEIM是一個獨立模塊,模塊的入口函數傳入兩個參數,FileHandle和**PeiServices。通過PEIServices,PEIM可以使用PEI階段提供的系統服務,通過這些服務,PEIM可以訪問PEI Core。PEIM之間通過PPI(PEIM-to-PEIM Interface)完成。
  • PPI與DXE階段的Protocol類似,每個PPI都是一個結構體,包含了函數指針和變量。每個PPI都有對應的GUID,通過PeiService的LocatePpi服務可以得到該PPI實例。

----------------------------------------代碼流程

  • SEC階段通過(*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable); 這段代碼跳轉到MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c中的

VOID EFIAPI
_ModuleEntryPoint(                                                                                                                                              
  IN CONST  EFI_SEC_PEI_HAND_OFF    *SecCoreData,
  IN CONST  EFI_PEI_PPI_DESCRIPTOR  *PpiList

)

  • 這個函數又調用ProcessModuleEntryPointList (SecCoreData, PpiList, NULL);函數,這個函數位於AutoGen.c中,這個文件是腳本生成的,在這個函數中調用了PeiCore入口函數

VOID EFIAPI
ProcessModuleEntryPointList (
  IN CONST  EFI_SEC_PEI_HAND_OFF    *SecCoreData,
  IN CONST  EFI_PEI_PPI_DESCRIPTOR  *PpiList,
  IN VOID                           *Context
  )

  •   這個函數又調用PeiCore (SecCoreData, PpiList, Context);       這樣便跳轉到了Pei階段。

----------------------------------------

EFI_PEI_SERVICES  gPs = {
  {
    PEI_SERVICES_SIGNATURE,                  
    PEI_SERVICES_REVISION,                   
    sizeof (EFI_PEI_SERVICES),               
    0,
    0
  },
  PeiInstallPpi,
  PeiReInstallPpi,
  PeiLocatePpi,
  PeiNotifyPpi,

  PeiGetBootMode,
  PeiSetBootMode,

  PeiGetHobList,
  PeiCreateHob,

  PeiFfsFindNextVolume,
  PeiFfsFindNextFile,
  PeiFfsFindSectionData,                                                                                                                                                                      

  PeiInstallPeiMemory,      
  PeiAllocatePages,
  PeiAllocatePool,
  (EFI_PEI_COPY_MEM)CopyMem,
  (EFI_PEI_SET_MEM)SetMem,

  PeiReportStatusCode,
  PeiResetSystem,

  &gPeiDefaultCpuIoPpi,
  &gPeiDefaultPciCfg2Ppi,

  PeiFfsFindFileByName,
  PeiFfsGetFileInfo,
  PeiFfsGetVolumeInfo,
  PeiRegisterForShadow,
  PeiFfsFindSectionData3,
  PeiFfsGetFileInfo2,
  PeiResetSystem2,
  PeiFreePages,
};

----------------------------

typedef struct {
  UINTN     Flags;
  EFI_GUID  *Guid;
  VOID      *Ppi;     ===>
} EFI_PEI_PPI_DESCRIPTOR;

 

struct _EFI_PEI_FIRMWARE_VOLUME_INFO_PPI {
  EFI_GUID  FvFormat;
  VOID      *FvInfo;     ===>
  UINT32    FvInfoSize;
  EFI_GUID  *ParentFvName;
  EFI_GUID  *ParentFileName;
};

-----------------------------------------------------------------------------------------------------------------------------

struct _PEI_CORE_INSTANCE {
  UINTN                              Signature;
  EFI_PEI_SERVICES                   *Ps;              ==========> 1 //指向本結構成員ServiceTableShadow
  PEI_PPI_DATABASE                   PpiData;            ==========> 2 
  UINTN                              FvCount;
  PEI_CORE_FV_HANDLE                 *Fv;                       ==========> 3 數組指針
  PEI_CORE_UNKNOW_FORMAT_FV_INFO     *UnknownFvInfo;      ==========> 4 數組指針
  UINTN                              UnknownFvInfoCount;

 EFI_PEI_FILE_HANDLE                *CurrentFvFileHandles;       ==========>5
  UINTN                              AprioriCount;
  UINTN                              CurrentPeimFvCount;
  UINTN                              CurrentPeimCount;
  EFI_PEI_FILE_HANDLE                CurrentFileHandle;
  BOOLEAN                            PeimNeedingDispatch;
  BOOLEAN                            PeimDispatchOnThisPass;
  BOOLEAN                            PeimDispatcherReenter;
  EFI_PEI_HOB_POINTERS               HobList;                ==========>6
  BOOLEAN                            SwitchStackSignal;
  BOOLEAN                            PeiMemoryInstalled;
  VOID                               *CpuIo;
  EFI_PEI_SECURITY2_PPI              *PrivateSecurityPpi; 
  EFI_PEI_SERVICES                   ServiceTableShadow;         ==========>1
  EFI_PEI_PPI_DESCRIPTOR             *XipLoadFile;
  EFI_PHYSICAL_ADDRESS               PhysicalMemoryBegin;
  UINT64                             PhysicalMemoryLength;
  EFI_PHYSICAL_ADDRESS               FreePhysicalMemoryTop;
  UINTN                              HeapOffset;
  BOOLEAN                            HeapOffsetPositive;
  UINTN                              StackOffset;
  BOOLEAN                            StackOffsetPositive;
  HOLE_MEMORY_DATA                   MemoryPages;
  PEICORE_FUNCTION_POINTER           ShadowedPeiCore;
  CACHE_SECTION_DATA                 CacheSection;
  EFI_PHYSICAL_ADDRESS               LoadModuleAtFixAddressTopAddress;

UINT64                            *PeiCodeMemoryRangeUsageBitMap;
  PE_COFF_LOADER_READ_FILE          ShadowedImageRead;
  EFI_PEI_FILE_HANDLE               *FileHandles;
  EFI_GUID                          *FileGuid;                ==========>7
  HOLE_MEMORY_DATA                  HoleData[HOLE_MAX_NUMBER];
};
 ==========> 1

struct _EFI_PEI_SERVICES {
  EFI_TABLE_HEADER                Hdr;
  EFI_PEI_INSTALL_PPI             InstallPpi;
  EFI_PEI_REINSTALL_PPI           ReInstallPpi;
  EFI_PEI_LOCATE_PPI              LocatePpi;
  EFI_PEI_NOTIFY_PPI              NotifyPpi;
  EFI_PEI_GET_BOOT_MODE           GetBootMode;
  EFI_PEI_SET_BOOT_MODE           SetBootMode;
  EFI_PEI_GET_HOB_LIST            GetHobList;
  EFI_PEI_CREATE_HOB              CreateHob;
  EFI_PEI_FFS_FIND_NEXT_VOLUME2   FfsFindNextVolume;
  EFI_PEI_FFS_FIND_NEXT_FILE2     FfsFindNextFile;
  EFI_PEI_FFS_FIND_SECTION_DATA2  FfsFindSectionData;

 EFI_PEI_INSTALL_PEI_MEMORY      InstallPeiMemory;
  EFI_PEI_ALLOCATE_PAGES          AllocatePages;
  EFI_PEI_ALLOCATE_POOL           AllocatePool;
  EFI_PEI_COPY_MEM                CopyMem;
  EFI_PEI_SET_MEM                 SetMem;
  EFI_PEI_REPORT_STATUS_CODE      ReportStatusCode;
  EFI_PEI_RESET_SYSTEM            ResetSystem;
  EFI_PEI_CPU_IO_PPI              *CpuIo;
  EFI_PEI_PCI_CFG2_PPI            *PciCfg;
  EFI_PEI_FFS_FIND_BY_NAME        FfsFindFileByName;
  EFI_PEI_FFS_GET_FILE_INFO       FfsGetFileInfo;
  EFI_PEI_FFS_GET_VOLUME_INFO     FfsGetVolumeInfo;
  EFI_PEI_REGISTER_FOR_SHADOW     RegisterForShadow;
  EFI_PEI_FFS_FIND_SECTION_DATA3  FindSectionData3;
  EFI_PEI_FFS_GET_FILE_INFO2      FfsGetFileInfo2;
  EFI_PEI_RESET2_SYSTEM           ResetSystem2;
  EFI_PEI_FREE_PAGES              FreePages;
};

 ==========> 2

typedef struct {
  INTN                    PpiListEnd;
  INTN                    NotifyListEnd;            //PcdGet32 (PcdPeiCoreMaxPpiSupported)-1
  INTN                    DispatchListEnd;             //PcdGet32 (PcdPeiCoreMaxPpiSupported)-1
  INTN                    LastDispatchedInstall;     //PcdGet32 (PcdPeiCoreMaxPpiSupported)-1 
  INTN                    LastDispatchedNotify;              
  PEI_PPI_LIST_POINTERS   *PpiListPtrs;   ==========> 數組列表 2.1
} PEI_PPI_DATABASE; 

 ==========> 2.1

typedef union {
  EFI_PEI_PPI_DESCRIPTOR      *Ppi;                ==========> 2.1.1
  EFI_PEI_NOTIFY_DESCRIPTOR   *Notify;      ==========> 2.1.2
  VOID                        *Raw;
} PEI_PPI_LIST_POINTERS;

==========> 2.1.1

typedef struct {
  UINTN     Flags;                
  EFI_GUID  *Guid;
  VOID      *Ppi;
} EFI_PEI_PPI_DESCRIPTOR

==========> 2.1.2

struct _EFI_PEI_NOTIFY_DESCRIPTOR {                                                                                                                                                          
  UINTN                       Flags; 
  EFI_GUID                    *Guid; 
  EFI_PEIM_NOTIFY_ENTRY_POINT Notify;  (函數)
};

==========> 3

typedef struct {
  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader;     =====>3.1
  EFI_PEI_FIRMWARE_VOLUME_PPI         *FvPpi;        ======> 3.2
  EFI_PEI_FV_HANDLE                   FvHandle;                (空間)
  UINT8                               *PeimState;                        
  EFI_PEI_FILE_HANDLE                 *FvFileHandles;
  BOOLEAN                             ScanFv;                             
  UINT32                              AuthenticationStatus;               
} PEI_CORE_FV_HANDLE; 

=====>3.1

typedef struct {
  UINT8                     ZeroVector[16];
  EFI_GUID                  FileSystemGuid;
  UINT64                    FvLength;
  UINT32                    Signature;
  EFI_FVB_ATTRIBUTES_2      Attributes;
  UINT16                    HeaderLength;
  UINT16                    Checksum;
  UINT16                    ExtHeaderOffset;
  UINT8                     Reserved[1];

  UINT8                     Revision;
  EFI_FV_BLOCK_MAP_ENTRY    BlockMap[1];
} EFI_FIRMWARE_VOLUME_HEADER;

=====>3.2

struct _EFI_PEI_FIRMWARE_VOLUME_PPI {
  EFI_PEI_FV_PROCESS_FV         ProcessVolume;                                                                                                  
  EFI_PEI_FV_FIND_FILE_TYPE   FindFileByType;
  EFI_PEI_FV_FIND_FILE_NAME   FindFileByName;
  EFI_PEI_FV_GET_FILE_INFO    GetFileInfo;
  EFI_PEI_FV_GET_INFO         GetVolumeInfo;
  EFI_PEI_FV_FIND_SECTION     FindSectionByType;
  EFI_PEI_FV_GET_FILE_INFO2   GetFileInfo2;
  EFI_PEI_FV_FIND_SECTION2    FindSectionByType2;
  UINT32                      Signature;
  UINT32                      Revision;
};

==========> 4

typedef struct {
  EFI_GUID                            FvFormat;                           
  VOID                                *FvInfo;                            
  UINT32                              FvInfoSize;                         
  UINT32                              AuthenticationStatus;               
  EFI_PEI_NOTIFY_DESCRIPTOR           NotifyDescriptor;
} PEI_CORE_UNKNOW_FORMAT_FV_INFO;

  ==========>5
/// The handles of EFI FFS.
typedef VOID    *EFI_PEI_FILE_HANDLE;

  ==========>6

typedef union {
  EFI_HOB_GENERIC_HEADER              *Header;
  EFI_HOB_HANDOFF_INFO_TABLE          *HandoffInformationTable;
  EFI_HOB_MEMORY_ALLOCATION           *MemoryAllocation;
  EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore;
  EFI_HOB_MEMORY_ALLOCATION_STACK     *MemoryAllocationStack;
  EFI_HOB_MEMORY_ALLOCATION_MODULE    *MemoryAllocationModule;
  EFI_HOB_RESOURCE_DESCRIPTOR         *ResourceDescriptor;
  EFI_HOB_GUID_TYPE                   *Guid;
  EFI_HOB_FIRMWARE_VOLUME             *FirmwareVolume;
  EFI_HOB_FIRMWARE_VOLUME2            *FirmwareVolume2;
  EFI_HOB_FIRMWARE_VOLUME3            *FirmwareVolume3;
  EFI_HOB_CPU                         *Cpu;
  EFI_HOB_MEMORY_POOL                 *Pool;
  EFI_HOB_UEFI_CAPSULE                *Capsule;
  UINT8                               *Raw;  // 將SecCoreData->PeiTemporaryRamBase
} EFI_PEI_HOB_POINTERS; 

-----------------------------------------------------------------------------------------------------------------------------

typedef struct { //包含Hob產生器階段使用的一般狀態信息。這個Hob必須是Hob列表中的第一個。

  EFI_HOB_GENERIC_HEADER  Header;
  UINT32                  Version;
  EFI_BOOT_MODE           BootMode;
  EFI_PHYSICAL_ADDRESS    EfiMemoryTop;
  EFI_PHYSICAL_ADDRESS    EfiMemoryBottom;
  EFI_PHYSICAL_ADDRESS    EfiFreeMemoryTop;
  EFI_PHYSICAL_ADDRESS    EfiFreeMemoryBottom;
  EFI_PHYSICAL_ADDRESS    EfiEndOfHobList;
} EFI_HOB_HANDOFF_INFO_TABLE;           

typedef struct {
  EFI_HOB_GENERIC_HEADER Header;   ====>
  EFI_PHYSICAL_ADDRESS   BaseAddress;      (空間)
  UINT64                 Length;
} EFI_HOB_FIRMWARE_VOLUME;

typedef struct { //描述Hob內數據的格式和大小。所有的Hob都必須包含這個通用的Hob頭。

  UINT16    HobType;
  UINT16    HobLength;
  UINT32    Reserved;
} EFI_HOB_GENERIC_HEADER;

-----------------------------------------------------------------------------------------------------------------------------

struct _EFI_PEI_NOTIFY_DESCRIPTOR {
  UINTN                       Flags; 
  EFI_GUID                    *Guid; 
  EFI_PEIM_NOTIFY_ENTRY_POINT Notify;
};

typedef
EFI_STATUS
(EFIAPI *EFI_PEIM_NOTIFY_ENTRY_POINT)(
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,                                                                                                                                            
  IN VOID                       *Ppi
  );

-----------------------------------------------------------------------------------------------------------------------------

PeiCore函數分析:

VOID
EFIAPI
PeiCore (
  IN CONST EFI_SEC_PEI_HAND_OFF        *SecCoreDataPtr,
  IN CONST EFI_PEI_PPI_DESCRIPTOR    *PpiList,                                                                                                                             
  IN VOID                              *Data
  )

  1. PEI_CORE_INSTANCE結構的創建,填充成員ServiceTableShadow。爲全局的gPs
  2. PEI_CORE_INSTANCE結構成員Ps=PEI_CORE_INSTANCE結構ServiceTableShadow。
  3. 通過SetPeiServicesTablePointer()保存Ps,以便可以在任何地方檢索它。由全局的gPeiServices維護
  4. 通過ProcessLibraryConstructorList(),傳入Ps指針,初始化PEI核心所鏈接的庫。
  5. 通過InitializeMemoryServices(),傳入PrivateData,    SecCoreData,初始化PEI Core,即根據PeiTemporaryRamBase,和PeiTemporaryRamSize構建一個切換信息表HOB(  一個EFI_HOB_GENERIC_HEADER和一個EFI_HOB_GENERIC_HEADER,這些都在PeiTemporaryRamBase起始位置)。
  6. 初始化PEI核心私有數據緩衝區。
  7. 通過InitializePpiServices()初始化ppi 服務。PEI_PPI_DATABASE     PpiData。
  8. 通過InitializeSecurityServices(),傳入PrivateData.Ps,初始化 安全服務(全局變量mNotifyList)
  9. 通過InitializeDispatcherData(),傳入PrivateData,    SecCoreData,初始化調度程序的數據成員
  10. 通過InitializeImageServices(),傳入PrivateData,   安裝PEI加載PPI文件。
  11. 通過ProcessPpiListFromSec(),如果SEC提供了PpiList,就處理。
  12. 通過PeiDispatcher(),回調PEIM調度員。開展PEIM調度。
  13. 通過PeiServicesLocatePpi(),查找DXE IPL PPI。
  14. 輸入Dxe Ipl來加載Dxe內核。TempPtr.DxeIpl->Entry (TempPtr.DxeIpl,  &PrivateData.Ps,  PrivateData.HobList  );

 

------------------------------------------------------構建一個切換信息表HOB

  • 一個EFI_HOB_GENERIC_HEADER:Hob

  EFI_HOB_GENERIC_HEADER  Header;

    /*UINT16    HobType;  // =EFI_HOB_TYPE_HANDOFF
    /*UINT16    HobLength;    //  =sizeof (EFI_HOB_GENERIC_HEADER)
    /*UINT32    Reserved;     //=0

  UINT32                  Version;  // =EFI_HOB_HANDOFF_TABLE_VERSION
  EFI_BOOT_MODE           BootMode;  // = BOOT_WITH_FULL_CONFIGURATION,
  EFI_PHYSICAL_ADDRESS    EfiMemoryTop;  //PeiTemporaryRamBase+ PeiTemporaryRamSize,
  EFI_PHYSICAL_ADDRESS    EfiMemoryBottom;  // PeiTemporaryRamBase,
  EFI_PHYSICAL_ADDRESS    EfiFreeMemoryTop;  //PeiTemporaryRamBase +PeiTemporaryRamSize,;
  EFI_PHYSICAL_ADDRESS    EfiFreeMemoryBottom;  // (HobEnd + 1)
  EFI_PHYSICAL_ADDRESS    EfiEndOfHobList;   // HobEnd
} EFI_HOB_HANDOFF_INFO_TABLE;           

  • 一個EFI_HOB_GENERIC_HEADER:HobEnd

  UINT16    HobType;  // =EFI_HOB_TYPE_END_OF_HOB_LIST
  UINT16    HobLength;    // =sizeof (EFI_HOB_GENERIC_HEADER)
  UINT32    Reserved;      // =0

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章