----------------------------------------整體流程
- UEFI一個重要特點就是其模塊化設計。PEI也是一個模塊,PEI Image的入口函數位_ModuleEntryPoit,該函數最終調用PEI模塊的入口函數PeiCore。
- 進入PeiCore後,首先根據SEC階段傳進來的信息設置Pei Core Services。
- 信息設置完成後,調用PeiDispatcher執行PEIM;
- 內存初始化。
- 當內存初始化後,系統會發生棧切換並重新進入PeiCore,重新進入到PeiCore後使用的內存是我們熟悉的內存。
- 待所有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
)
- PEI_CORE_INSTANCE結構的創建,填充成員ServiceTableShadow。爲全局的gPs
- PEI_CORE_INSTANCE結構成員Ps=PEI_CORE_INSTANCE結構ServiceTableShadow。
- 通過SetPeiServicesTablePointer()保存Ps,以便可以在任何地方檢索它。由全局的gPeiServices維護
- 通過ProcessLibraryConstructorList(),傳入Ps指針,初始化PEI核心所鏈接的庫。
- 通過InitializeMemoryServices(),傳入PrivateData, SecCoreData,初始化PEI Core,即根據PeiTemporaryRamBase,和PeiTemporaryRamSize構建一個切換信息表HOB( 一個EFI_HOB_GENERIC_HEADER和一個EFI_HOB_GENERIC_HEADER,這些都在PeiTemporaryRamBase起始位置)。
- 初始化PEI核心私有數據緩衝區。
- 通過InitializePpiServices()初始化ppi 服務。PEI_PPI_DATABASE PpiData。
- 通過InitializeSecurityServices(),傳入PrivateData.Ps,初始化 安全服務(全局變量mNotifyList)
- 通過InitializeDispatcherData(),傳入PrivateData, SecCoreData,初始化調度程序的數據成員
- 通過InitializeImageServices(),傳入PrivateData, 安裝PEI加載PPI文件。
- 通過ProcessPpiListFromSec(),如果SEC提供了PpiList,就處理。
- 通過PeiDispatcher(),回調PEIM調度員。開展PEIM調度。
- 通過PeiServicesLocatePpi(),查找DXE IPL PPI。
- 輸入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