EFI_SEC_PEI_HAND_OFF
EFI_SEC_PEI_HAND_OFF结构保存着PEI核心运行环境的信息,如临时RAM的位置大小、堆栈位置和BFV位置。
typedef struct _EFI_SEC_PEI_HAND_OFF {
/// 数据结构的大小
UINT16 DataSize;
/// 指向引导固件卷的第一个字节,PEI Dispatcher应该搜索PEI模块。
VOID *BootFirmwareVolumeBase;
/// 引导固件卷的大小,以字节为单位。
UINTN BootFirmwareVolumeSize;
/// 指向临时RAM的第一个字节。
VOID *TemporaryRamBase;
/// 临时RAM的大小,以字节为单位。
UINTN TemporaryRamSize;
/// 指向PEI Foundation可使用的临时RAM的第一个字节。由PeiTemporaryRamBase和PeiTemporaryRamSize描述的区域
/// 不能超出由TemporaryRamBase和TemporaryRamSize描述的区域。这个区域不应该与StackBase和StackSize报告的区域重叠。
VOID *PeiTemporaryRamBase;
/// 可供PEI Foundation使用的可用临时RAM的大小,以字节为单位。
UINTN PeiTemporaryRamSize;
///指向堆栈的第一个字节。这可能是由TemporaryRamBase和TemporaryRamSize描述的内存的一部分,也可能是一个完全独立的区域。
VOID *StackBase;
/// 堆栈的大小,以字节为单位。
UINTN StackSize;
} EFI_SEC_PEI_HAND_OFF;
PEI_PPI_DATABASE
这是PeiMain 的内部数据结构,定义了一个数组用来存储所有安装的PEI PPI.每个安装PPI 及通知PPI 都会保存在这个结构中的一个数组单元。由于PEI 早期阶段内存还没有初始化,没有足够的内存可以使用,所以此数据结构的大小是不可能动态调整的,只能保存一定数量的PPI,最大的个数由固定类型的PciPeiCoreMaxPpiSupported 的值来起决定,用户可以通过配置此PCD来允许系统安装更多的PPI。
/// PEI_PPI_DATABAASE的PpiListPtrs存储了所有安装的PPi和通知PPI。
/// PPI数据库结构中包含两个链接:PpiList和NotifyList。
/// PpiList在PpiListPtrs数组的头,notify在PpiListPtrs数组的尾。
///
typedef struct {
///
/// PpiList链表结束索引。
/// PpiListEnd 记录了最后一个安装的PPI的数组索引,PPI的索引是从零开始递增的,
///
INTN PpiListEnd;
///
/// notify链表结束索引。
/// NotfifyListEnd记录了最后一个安装的通知PPI的数组索引,通知PPI 的索引是从最大值开始递减的,
/// 一旦PpiListEnd等于NotifyListEnd,则说明安装的PPI数量超出了最大允许的安装个数,
/// 新的PPI 无法安装,可能会导致系统出错。
INTN NotifyListEnd;
///
/// 已发送notify列表的索引。
///
INTN DispatchListEnd;
///
/// 在PpiList链接列表中最后安装的Ppi描述的索引。
///
INTN LastDispatchedInstall;
///
/// 在notify链表中最后一次发送notify的索引。
///
INTN LastDispatchedNotify;
///
/// Ppi数据库有pcdpeicoremaxppissupported的entries。
///
PEI_PPI_LIST_POINTERS *PpiListPtrs;
} PEI_PPI_DATABASE;
PEI_CORE_FV_HANDLE
此数据结构用来记录一个PeiMain识别的FV空间的数据信息,包括其的起始地址、数据格式解析的PPI 、自己的句柄以及所包含的每个PEI模块的派遣状态和每个文件的句柄,最后一个标识符号记录这个FV是否已经被解析。这个数据结构支持的最大文件个数是由PcdPeiCoreMaxPeimPerFv的值决定。如果一个FV空间包含的文件个数大于此PCD的值,PEIMain将无法记录其的完整信息,可能会导致系统出错。些数据结构定义在PeiMain.h
//用来记录一个PEIMain识别的FV空间的数据信息,包括起始位置,数据格式解析的PPI,自己的句柄
typedef struct {
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
EFI_PEI_FV_HANDLE FvHandle;
//
// Ponter to the buffer with the PcdPeiCoreMaxPeimPerFv number of Entries.
// 每个PEI模块的派遣状态
//
UINT8 *PeimState;
//
// Ponter to the buffer with the PcdPeiCoreMaxPeimPerFv number of Entries.
// 每个文件的句柄
//
EFI_PEI_FILE_HANDLE *FvFileHandles;
BOOLEAN ScanFv;
UINT32 AuthenticationStatus;
} PEI_CORE_FV_HANDLE;
EFI_PEI_SERVICES
///
/// EFI_PEI_SERVICES是一个函数集合,其实现由PEI Foundation提供.
/// 这些服务分为不同的类别,包括:
/// - 管理启动方式
/// - 同时分配早期和永久内存
/// - 支持固件文件系统(FFS)
/// - 抽象PPI数据库抽象
/// - 创建HOB(HOBs)。
///
struct _EFI_PEI_SERVICES {
///
/// PEI Services表的表头。
///
EFI_TABLE_HEADER Hdr;
//
// PPI相关功能函数
//
EFI_PEI_INSTALL_PPI InstallPpi;
EFI_PEI_REINSTALL_PPI ReInstallPpi;
EFI_PEI_LOCATE_PPI LocatePpi;
EFI_PEI_NOTIFY_PPI NotifyPpi;
//
// Boot Mode(引导模式)相关功能函数
//
EFI_PEI_GET_BOOT_MODE GetBootMode;
EFI_PEI_SET_BOOT_MODE SetBootMode;
//
// HOB 相关功能函数
//
EFI_PEI_GET_HOB_LIST GetHobList;
EFI_PEI_CREATE_HOB CreateHob;
//
// Firmware Volume (FV)相关功能函数
//
EFI_PEI_FFS_FIND_NEXT_VOLUME2 FfsFindNextVolume;
EFI_PEI_FFS_FIND_NEXT_FILE2 FfsFindNextFile;
EFI_PEI_FFS_FIND_SECTION_DATA2 FfsFindSectionData;
//
// PEI 内存相关功能函数
//
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;
//
// Status Code 状态码
//
EFI_PEI_REPORT_STATUS_CODE ReportStatusCode;
//
// Reset 重置
//
EFI_PEI_RESET_SYSTEM ResetSystem;
//
// (the following interfaces are installed by publishing PEIM)I/O Abstractions
// (通过发布PEIM来安装以下接口)I/O 抽象接口
//
EFI_PEI_CPU_IO_PPI *CpuIo;
EFI_PEI_PCI_CFG2_PPI *PciCfg;
//
// Future Installed Services
//
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;
};
PEI_CORE_INSTANCE
///
/// Pei核心私有数据结构实例 PrivateData
/// 该结构叫做PeiMain的内部数据结构,维护运行PEI阶段所有需要的数据信息,包括PEI服务,FV数据空间,PEI模块的dispatch 状态,
/// 可使用的内存空间等等,由于pei 早期没有内存可用,PeiMain定义了一个该数据的局部变量,把其存储在PeiMain入口函数的栈上,
/// 而PeiMain 的入口函数在整个PEI 阶段并不会退出,所以栈上的数据可作为全局数据使用,
/// 但是全局变量的地址需要函数参数在不同的函数之间传递。
///
struct _PEI_CORE_INSTANCE {
UINTN Signature;
///
/// 指向ServiceTableShadow
/// PEI_CORE_INSTANCE结构的创建,填充成员ServiceTableShadow。为全局的gPs
///
EFI_PEI_SERVICES *Ps;
PEI_PPI_DATABASE PpiData;
///
/// 包含FFS且可以由PeiCore发送的FVs计数。
///
UINTN FvCount;
///
/// 指向带有PcdPeiCoreMaxFvSupported entries的缓冲区的指针。
/// 每个entry都是针对一个FV的,它包含FFS,可以被PeiCore发送。
/// 通过SetPeiServicesTablePointer()保存Ps,以便可以在任何地方检索它。由全局的gPeiServices维护
///
PEI_CORE_FV_HANDLE *Fv;
///
/// 指向带有PcdPeiCoreMaxFvSupported entries的缓冲区的指针。
/// 每个entry是针对PeiCore无法发送的FV的。
/// 通过ProcessLibraryConstructorList(),传入Ps指针,初始化PEI核心所链接的库。
///
PEI_CORE_UNKNOW_FORMAT_FV_INFO *UnknownFvInfo;
UINTN UnknownFvInfoCount;
///
/// 指向带有PcdPeiCoreMaxPeimPerFv entries的缓冲区的指针。
/// 通过InitializeMemoryServices(),传入PrivateData, SecCoreData,初始化PEI Core,
/// 即根据PeiTemporaryRamBase,和PeiTemporaryRamSize构建一个切换信息表HOB
/// (一个EFI_HOB_GENERIC_HEADER和一个EFI_HOB_GENERIC_HEADER,这些都在PeiTemporaryRamBase起始位置)。
///
EFI_PEI_FILE_HANDLE *CurrentFvFileHandles;
UINTN AprioriCount;
UINTN CurrentPeimFvCount;
UINTN CurrentPeimCount;
EFI_PEI_FILE_HANDLE CurrentFileHandle;
BOOLEAN PeimNeedingDispatch;
BOOLEAN PeimDispatchOnThisPass;
BOOLEAN PeimDispatcherReenter;
///
/// 初始化PEI核心私有数据缓冲区。
///
EFI_PEI_HOB_POINTERS HobList;
BOOLEAN SwitchStackSignal;
BOOLEAN PeiMemoryInstalled;
VOID *CpuIo;
EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi;
EFI_PEI_SERVICES ServiceTableShadow;
EFI_PEI_PPI_DESCRIPTOR *XipLoadFile;
EFI_PHYSICAL_ADDRESS PhysicalMemoryBegin;
UINT64 PhysicalMemoryLength;
EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop;
UINTN HeapOffset;
BOOLEAN HeapOffsetPositive;
UINTN StackOffset;
BOOLEAN StackOffsetPositive;
PEICORE_FUNCTION_POINTER ShadowedPeiCore;
CACHE_SECTION_DATA CacheSection;
//
// 在加载固定地址功能的模块时,将运行时代码、启动时代码和PEI内存的顶部地址缓存在下面。
// 请注意,这个字段和Ps之间的偏移量不应该被改变,因为也许用户可以通过使用Ps的偏移量得到这个顶部地址。
//
EFI_PHYSICAL_ADDRESS LoadModuleAtFixAddressTopAddress;
//
// 该字段是为加载固定地址的模块来跟踪PEI代码内存范围的使用而定义的。
// 它是一个位映射数组,其中的每个位都表示相应的内存页是否可用。
//
UINT64 *PeiCodeMemoryRangeUsageBitMap;
//
// This field points to the shadowed image read function
// 这个字段指向阴影图像读取函数
//
PE_COFF_LOADER_READ_FILE ShadowedImageRead;
//
// 指向临时缓冲区的指针,entry为PcdPeiCoreMaxPeimPerFv + 1。
//
EFI_PEI_FILE_HANDLE *FileHandles;
//
// 指向临时缓冲区的指针,包含PcdPeiCoreMaxPeimPerFv条目数 entries。
// 通过InitializePpiServices()初始化ppi 服务。PEI_PPI_DATABASE PpiData。
//
EFI_GUID *FileGuid;
//
// PeiTempMem和Stack没有覆盖临时内存范围。
// 这些内存范围将被迁移到物理内存中。
//
HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER];
};
参考博文:https://blog.csdn.net/robinsongsog/article/details/102653826