----------------------------------------整体流程
- 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