【UEFI基础】HOB介绍

发布时间:2025-12-09 17:03:06 浏览次数:4

综述

HOB的全称是Hand-Off Block,从名字上也可以看出来,它表示的是一种用于交接的数据。按照HOB的使用情况,可以将BIOS的启动阶段分为两个部分:

  • HOB生成阶段(HOB producer phase),用来创建和修改HOB;
  • HOB消费阶段(HOB consumer phase),用来使用HOB,注意此阶段HOB是只读的。

而这里说的“交接”就是从HOB生成阶段像HOB消费阶段交接数据,至于交接的是什么数据,后面会一一介绍。

本文参考《PI_Spec_1_7_A_final_May1.pdf》(后面统称为PI规范),该手册为了将x86的Platform Initialization扩展到更多的平台,已经不再直接使用PEI、DXE等阶段说明HOB的使用情况,不过对于x86架构的BIOS来说,HOB生成阶段其实就是SEC和PEI阶段,而HOB消费阶段就是DXE和BDS阶段。为了方便,本文还是直接使用PEI、DXE等术语。术语的对应关系如下表所示:

Term Used in the HOB SpecificationTerm Used in Other PI Specifications
HOB producer phasePEI phase
HOB consumer phaseDXE phase
executable content in the HOB producer phasePre-EFI Initialization Module (PEIM)
hand-off into the HOB consumer phaseDXE Initial Program Load (IPL) PEIM or
DXE IPL PEIM-to-PEIM Interface (PPI)
platform boot-policy phaseBoot Device Selection (BDS) phase

注意,虽然上表中只有PEI和DXE,但是从实际的情况来看,SEC和BDS也分别可以作为HOB生成阶段和HOB消费阶段。

HOB的构成

HOB在PEI阶段创建,并返回一个列表(称为HOB List,HOB列表),其中的HOB一个个堆叠放置,最终构成如下的形式:

根据HOB中包含的数据的不同可以对HOB进行分类,且HOB列表的第一个必须要是PHIT HOB。PHIT的全称是Phase Handoff Information Table,它是第一个被创建的HOB,对应的指针在PEI的核心数据中:

////// Union of all the possible HOB Types.///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;} EFI_PEI_HOB_POINTERS;////// Forward declaration for PEI_CORE_INSTANCE///typedef struct _PEI_CORE_INSTANCE PEI_CORE_INSTANCE;////// Pei Core private data structure instance///struct _PEI_CORE_INSTANCE {UINTN Signature;////// Point to ServiceTableShadow///EFI_PEI_SERVICES *Ps;PEI_PPI_DATABASE PpiData;/// 其它略。下面就是指向第一个HOB的指针,EFI_PEI_HOB_POINTERS是一个Union,包括各种指针:EFI_PEI_HOB_POINTERS HobList;}

后面的HOB操作接口都是以这里为基础的,比如EFI_PEI_SERVICES中就有接口GetHobList(),其实现:

////// Pei Core Instance Data Macros///#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \CR(a, PEI_CORE_INSTANCE, Ps, PEI_CORE_HANDLE_SIGNATURE)EFI_STATUSEFIAPIPeiGetHobList (IN CONST EFI_PEI_SERVICES **PeiServices,IN OUT VOID **HobList){PEI_CORE_INSTANCE *PrivateData;//// Only check this parameter in debug mode//DEBUG_CODE_BEGIN ();if (HobList == NULL) {return EFI_INVALID_PARAMETER;}DEBUG_CODE_END ();PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);*HobList = PrivateData->HobList.Raw;return EFI_SUCCESS;}

创建PHIT HOB的大致流程如下(不同的平台可能会有不同):

#mermaid-svg-sN68X3qWQEihJvpf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-sN68X3qWQEihJvpf .error-icon{fill:#552222;}#mermaid-svg-sN68X3qWQEihJvpf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sN68X3qWQEihJvpf .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-sN68X3qWQEihJvpf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sN68X3qWQEihJvpf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sN68X3qWQEihJvpf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sN68X3qWQEihJvpf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sN68X3qWQEihJvpf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sN68X3qWQEihJvpf .marker.cross{stroke:#333333;}#mermaid-svg-sN68X3qWQEihJvpf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sN68X3qWQEihJvpf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sN68X3qWQEihJvpf .cluster-label text{fill:#333;}#mermaid-svg-sN68X3qWQEihJvpf .cluster-label span{color:#333;}#mermaid-svg-sN68X3qWQEihJvpf .label text,#mermaid-svg-sN68X3qWQEihJvpf span{fill:#333;color:#333;}#mermaid-svg-sN68X3qWQEihJvpf .node rect,#mermaid-svg-sN68X3qWQEihJvpf .node circle,#mermaid-svg-sN68X3qWQEihJvpf .node ellipse,#mermaid-svg-sN68X3qWQEihJvpf .node polygon,#mermaid-svg-sN68X3qWQEihJvpf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sN68X3qWQEihJvpf .node .label{text-align:center;}#mermaid-svg-sN68X3qWQEihJvpf .node.clickable{cursor:pointer;}#mermaid-svg-sN68X3qWQEihJvpf .arrowheadPath{fill:#333333;}#mermaid-svg-sN68X3qWQEihJvpf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sN68X3qWQEihJvpf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sN68X3qWQEihJvpf .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-sN68X3qWQEihJvpf .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-sN68X3qWQEihJvpf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sN68X3qWQEihJvpf .cluster text{fill:#333;}#mermaid-svg-sN68X3qWQEihJvpf .cluster span{color:#333;}#mermaid-svg-sN68X3qWQEihJvpf p.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sN68X3qWQEihJvpf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}PeiCoreInitializeMemoryServicesPeiCoreBuildHobHandoffInfoTable

在PeiCoreBuildHobHandoffInfoTable()函数中有PHIT HOB的初始化:

EFI_STATUSPeiCoreBuildHobHandoffInfoTable (IN EFI_BOOT_MODE BootMode,IN EFI_PHYSICAL_ADDRESS MemoryBegin,IN UINT64 MemoryLength){EFI_HOB_HANDOFF_INFO_TABLE *Hob;EFI_HOB_GENERIC_HEADER *HobEnd;Hob = (VOID *)(UINTN)MemoryBegin;HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1);Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;Hob->Header.HobLength = (UINT16)sizeof (EFI_HOB_HANDOFF_INFO_TABLE);Hob->Header.Reserved = 0;HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER);HobEnd->Reserved = 0;Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;Hob->BootMode = BootMode;Hob->EfiMemoryTop = MemoryBegin + MemoryLength;Hob->EfiMemoryBottom = MemoryBegin;Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd + 1);Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;return EFI_SUCCESS;}

这里的数据可以跟前面的图对应。有了第一个HOB,之后的HOB就在此基础之上堆叠,最终完成所有需要的HOB。下面介绍目前PI规范中定义的HOB分类。

HOB分类

当前PI规范定义的HOB有如下的几种类型:

每一个HOB都包含一个通用的结构:

////// Describes the format and size of the data inside the HOB./// All HOBs must contain this generic HOB header.///typedef struct {////// Identifies the HOB data structure type.///UINT16 HobType;////// The length in bytes of the HOB.///UINT16 HobLength;////// This field must always be set to zero.///UINT32 Reserved;} EFI_HOB_GENERIC_HEADER;

这里就指定了HOB的类型HobType:

//// HobType of EFI_HOB_GENERIC_HEADER.//#define EFI_HOB_TYPE_HANDOFF 0x0001#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004#define EFI_HOB_TYPE_FV 0x0005#define EFI_HOB_TYPE_CPU 0x0006#define EFI_HOB_TYPE_MEMORY_POOL 0x0007#define EFI_HOB_TYPE_FV2 0x0009#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A#define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B#define EFI_HOB_TYPE_FV3 0x000C#define EFI_HOB_TYPE_UNUSED 0xFFFE#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF

然后是HOB的长度HobLength,通过它就可以知道下一个HOB的位置。

下面介绍一些常用的HOB。

PHIT HOB

前面已经介绍了PHIT HOB,它的结构体如下:

////// Contains general state information used by the HOB producer phase./// This HOB must be the first one in the HOB list.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_HANDOFF.///EFI_HOB_GENERIC_HEADER Header;////// The version number pertaining to the PHIT HOB definition./// This value is four bytes in length to provide an 8-byte aligned entry/// when it is combined with the 4-byte BootMode.///UINT32 Version;////// The system boot mode as determined during the HOB producer phase.///EFI_BOOT_MODE BootMode;////// The highest address location of memory that is allocated for use by the HOB producer/// phase. This address must be 4-KB aligned to meet page restrictions of UEFI.///EFI_PHYSICAL_ADDRESS EfiMemoryTop;////// The lowest address location of memory that is allocated for use by the HOB producer phase.///EFI_PHYSICAL_ADDRESS EfiMemoryBottom;////// The highest address location of free memory that is currently available/// for use by the HOB producer phase.///EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop;////// The lowest address location of free memory that is available for use by the HOB producer phase.///EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom;////// The end of the HOB list.///EFI_PHYSICAL_ADDRESS EfiEndOfHobList;} EFI_HOB_HANDOFF_INFO_TABLE;

里面主要有包含两个部分,一个用来描述启动模式,另一个用来描述HOB内存的分布,这个也已经在前文的图中说明。

Memory Allocation HOB

PHIT HOB之后是Memory Allocation HOB,它对应结构体:

////// Describes all memory ranges used during the HOB producer/// phase that exist outside the HOB list. This HOB type/// describes how memory is used, not the physical attributes of memory.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.///EFI_HOB_GENERIC_HEADER Header;////// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the/// various attributes of the logical memory allocation.///EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;//// Additional data pertaining to the "Name" Guid memory// may go here.//} EFI_HOB_MEMORY_ALLOCATION;

EFI_HOB_MEMORY_ALLOCATION_HEADER结构体的构成:

////// EFI_HOB_MEMORY_ALLOCATION_HEADER describes the/// various attributes of the logical memory allocation. The type field will be used for/// subsequent inclusion in the UEFI memory map.///typedef struct {////// A GUID that defines the memory allocation region's type and purpose, as well as/// other fields within the memory allocation HOB. This GUID is used to define the/// additional data within the HOB that may be present for the memory allocation HOB./// Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0/// specification.///EFI_GUID Name;////// The base address of memory allocated by this HOB. Type/// EFI_PHYSICAL_ADDRESS is defined in AllocatePages() in the UEFI 2.0/// specification.///EFI_PHYSICAL_ADDRESS MemoryBaseAddress;////// The length in bytes of memory allocated by this HOB.///UINT64 MemoryLength;////// Defines the type of memory allocated by this HOB. The memory type definition/// follows the EFI_MEMORY_TYPE definition. Type EFI_MEMORY_TYPE is defined/// in AllocatePages() in the UEFI 2.0 specification.///EFI_MEMORY_TYPE MemoryType;////// Padding for Itanium processor family///UINT8 Reserved[4];} EFI_HOB_MEMORY_ALLOCATION_HEADER;

这里也有一个MemoryType表示类型,这里指的是UEFI下的内存使用类型,比如存放Boot Service的代码和数据的内存类型,Runtime的代码和数据的内存类型,等等。它们有如下的可选值:

////// Enumeration of memory types introduced in UEFI.///typedef enum {////// Not used.///EfiReservedMemoryType,////// The code portions of a loaded application./// (Note that UEFI OS loaders are UEFI applications.)///EfiLoaderCode,////// The data portions of a loaded application and the default data allocation/// type used by an application to allocate pool memory.///EfiLoaderData,////// The code portions of a loaded Boot Services Driver.///EfiBootServicesCode,////// The data portions of a loaded Boot Serves Driver, and the default data/// allocation type used by a Boot Services Driver to allocate pool memory.///EfiBootServicesData,////// The code portions of a loaded Runtime Services Driver.///EfiRuntimeServicesCode,////// The data portions of a loaded Runtime Services Driver and the default/// data allocation type used by a Runtime Services Driver to allocate pool memory.///EfiRuntimeServicesData,////// Free (unallocated) memory.///EfiConventionalMemory,////// Memory in which errors have been detected.///EfiUnusableMemory,////// Memory that holds the ACPI tables.///EfiACPIReclaimMemory,////// Address space reserved for use by the firmware.///EfiACPIMemoryNVS,////// Used by system firmware to request that a memory-mapped IO region/// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.///EfiMemoryMappedIO,////// System memory-mapped IO region that is used to translate memory/// cycles to IO cycles by the processor.///EfiMemoryMappedIOPortSpace,////// Address space reserved by the firmware for code that is part of the processor.///EfiPalCode,////// A memory region that operates as EfiConventionalMemory,/// however it happens to also support byte-addressable non-volatility.///EfiPersistentMemory,////// A memory region that describes system memory that has not been accepted/// by a corresponding call to the underlying isolation architecture.///EfiUnacceptedMemoryType,EfiMaxMemoryType} EFI_MEMORY_TYPE;

此外,还有几个特别的EFI_HOB_MEMORY_ALLOCATION:

  • EFI_HOB_MEMORY_ALLOCATION_STACK
////// Describes the memory stack that is produced by the HOB producer/// phase and upon which all post-memory-installed executable/// content in the HOB producer phase is executing.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.///EFI_HOB_GENERIC_HEADER Header;////// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the/// various attributes of the logical memory allocation.///EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;} EFI_HOB_MEMORY_ALLOCATION_STACK;

从名称可以看出来它描述的是BSP执行所需的堆对应内存,通过BuildStackHob()创建,对应的流程:

#mermaid-svg-08Rp9BeQfGVmaAzB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .error-icon{fill:#552222;}#mermaid-svg-08Rp9BeQfGVmaAzB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-08Rp9BeQfGVmaAzB .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-08Rp9BeQfGVmaAzB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-08Rp9BeQfGVmaAzB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-08Rp9BeQfGVmaAzB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-08Rp9BeQfGVmaAzB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-08Rp9BeQfGVmaAzB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-08Rp9BeQfGVmaAzB .marker.cross{stroke:#333333;}#mermaid-svg-08Rp9BeQfGVmaAzB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-08Rp9BeQfGVmaAzB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .cluster-label text{fill:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .cluster-label span{color:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .label text,#mermaid-svg-08Rp9BeQfGVmaAzB span{fill:#333;color:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .node rect,#mermaid-svg-08Rp9BeQfGVmaAzB .node circle,#mermaid-svg-08Rp9BeQfGVmaAzB .node ellipse,#mermaid-svg-08Rp9BeQfGVmaAzB .node polygon,#mermaid-svg-08Rp9BeQfGVmaAzB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-08Rp9BeQfGVmaAzB .node .label{text-align:center;}#mermaid-svg-08Rp9BeQfGVmaAzB .node.clickable{cursor:pointer;}#mermaid-svg-08Rp9BeQfGVmaAzB .arrowheadPath{fill:#333333;}#mermaid-svg-08Rp9BeQfGVmaAzB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-08Rp9BeQfGVmaAzB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-08Rp9BeQfGVmaAzB .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-08Rp9BeQfGVmaAzB .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-08Rp9BeQfGVmaAzB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-08Rp9BeQfGVmaAzB .cluster text{fill:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB .cluster span{color:#333;}#mermaid-svg-08Rp9BeQfGVmaAzB p.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-08Rp9BeQfGVmaAzB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}PeiCorePeiDispatcherPeiCheckAndSwitchStackBuildStackHob

函数实现的主要代码:

CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid);Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;Hob->AllocDescriptor.MemoryLength = Length;Hob->AllocDescriptor.MemoryType = EfiBootServicesData;

DXE阶段会进一步的使用该HOB。

  • EFI_HOB_MEMORY_ALLOCATION_BSP_STORE
////// Defines the location of the boot-strap/// processor (BSP) BSPStore ("Backing Store Pointer Store")./// This HOB is valid for the Itanium processor family only/// register overflow store.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.///EFI_HOB_GENERIC_HEADER Header;////// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the/// various attributes of the logical memory allocation.///EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;} EFI_HOB_MEMORY_ALLOCATION_BSP_STORE;

该HOB主要在Itanium平台的CPU上使用,这里就不再说明。

  • EFI_HOB_MEMORY_ALLOCATION_MODULE
////// Defines the location and entry point of the HOB consumer phase.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION.///EFI_HOB_GENERIC_HEADER Header;////// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the/// various attributes of the logical memory allocation.///EFI_HOB_MEMORY_ALLOCATION_HEADER MemoryAllocationHeader;////// The GUID specifying the values of the firmware file system name/// that contains the HOB consumer phase component.///EFI_GUID ModuleName;////// The address of the memory-mapped firmware volume/// that contains the HOB consumer phase firmware file.///EFI_PHYSICAL_ADDRESS EntryPoint;} EFI_HOB_MEMORY_ALLOCATION_MODULE;

它描述的其实是DXE入口,创建的流程:

#mermaid-svg-TBSILIjYbLeyn0fI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .error-icon{fill:#552222;}#mermaid-svg-TBSILIjYbLeyn0fI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TBSILIjYbLeyn0fI .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-TBSILIjYbLeyn0fI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TBSILIjYbLeyn0fI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TBSILIjYbLeyn0fI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TBSILIjYbLeyn0fI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TBSILIjYbLeyn0fI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TBSILIjYbLeyn0fI .marker.cross{stroke:#333333;}#mermaid-svg-TBSILIjYbLeyn0fI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TBSILIjYbLeyn0fI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .cluster-label text{fill:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .cluster-label span{color:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .label text,#mermaid-svg-TBSILIjYbLeyn0fI span{fill:#333;color:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .node rect,#mermaid-svg-TBSILIjYbLeyn0fI .node circle,#mermaid-svg-TBSILIjYbLeyn0fI .node ellipse,#mermaid-svg-TBSILIjYbLeyn0fI .node polygon,#mermaid-svg-TBSILIjYbLeyn0fI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TBSILIjYbLeyn0fI .node .label{text-align:center;}#mermaid-svg-TBSILIjYbLeyn0fI .node.clickable{cursor:pointer;}#mermaid-svg-TBSILIjYbLeyn0fI .arrowheadPath{fill:#333333;}#mermaid-svg-TBSILIjYbLeyn0fI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TBSILIjYbLeyn0fI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TBSILIjYbLeyn0fI .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-TBSILIjYbLeyn0fI .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-TBSILIjYbLeyn0fI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TBSILIjYbLeyn0fI .cluster text{fill:#333;}#mermaid-svg-TBSILIjYbLeyn0fI .cluster span{color:#333;}#mermaid-svg-TBSILIjYbLeyn0fI p.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TBSILIjYbLeyn0fI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}DxeLoadCoreBuildModuleHob

对应的代码:

//// Load the DXE Core from a Firmware Volume.//Instance = 0;do {Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **)&LoadFile);//// These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.//ASSERT_EFI_ERROR (Status);Status = LoadFile->LoadFile (LoadFile,FileHandle,&DxeCoreAddress,&DxeCoreSize,&DxeCoreEntryPoint,&AuthenticationState);} while (EFI_ERROR (Status));//// Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.//Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);ASSERT_EFI_ERROR (Status);//// Add HOB for the DXE Core//BuildModuleHob (&DxeCoreFileInfo.FileName,DxeCoreAddress,ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),DxeCoreEntryPoint);

BuildModuleHob()的核心代码:

CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;Hob->MemoryAllocationHeader.MemoryLength = ModuleLength;Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode;

可以看到代码其实就是从FV中获取DXE核心入口,并根据它的值创建HOB,根据它可以创建DXE核心的Image Hand了,对应的操作位于函数CoreInitializeImageServices():

// 获取EFI_HOB_MEMORY_ALLOCATION_MODULE这个HOBDxeCoreHob.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);}// 获取到DxeCoreEntryPointDxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreHob.MemoryAllocationModule->EntryPoint;gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;// 安装Image HandleImage = &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.SystemTable = gDxeCoreST;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);

Resource Descriptor HOB

该HOB定义物理内存的属性,其结构:

////// Describes the resource properties of all fixed,/// nonrelocatable resource ranges found on the processor/// host bus during the HOB producer phase.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR.///EFI_HOB_GENERIC_HEADER Header;////// A GUID representing the owner of the resource. This GUID is used by HOB/// consumer phase components to correlate device ownership of a resource.///EFI_GUID Owner;////// The resource type enumeration as defined by EFI_RESOURCE_TYPE.///EFI_RESOURCE_TYPE ResourceType;////// Resource attributes as defined by EFI_RESOURCE_ATTRIBUTE_TYPE.///EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;////// The physical start address of the resource region.///EFI_PHYSICAL_ADDRESS PhysicalStart;////// The number of bytes of the resource region.///UINT64 ResourceLength;} EFI_HOB_RESOURCE_DESCRIPTOR;

这样的HOB一般有很多个,它们通过BuildResourceDescriptorHob()函数创建:

/**Builds a HOB that describes a chunk of system memory.This function builds a HOB that describes a chunk of system memory.If there is no additional space for HOB creation, then ASSERT().@param ResourceType The type of resource described by this HOB.@param ResourceAttribute The resource attributes of the memory described by this HOB.@param PhysicalStart The 64 bit physical address of memory described by this HOB.@param NumberOfBytes The length of the memory described by this HOB in bytes.**/VOIDEFIAPIBuildResourceDescriptorHob (IN EFI_RESOURCE_TYPE ResourceType,IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,IN EFI_PHYSICAL_ADDRESS PhysicalStart,IN UINT64 NumberOfBytes){EFI_HOB_RESOURCE_DESCRIPTOR *Hob;Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));ASSERT (Hob != NULL);Hob->ResourceType = ResourceType;Hob->ResourceAttribute = ResourceAttribute;Hob->PhysicalStart = PhysicalStart;Hob->ResourceLength = NumberOfBytes;}

该HOB包含的类型:

//// Value of ResourceType in EFI_HOB_RESOURCE_DESCRIPTOR.//#define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000#define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001#define EFI_RESOURCE_IO 0x00000002#define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005#define EFI_RESOURCE_IO_RESERVED 0x00000006//// BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED is defined for unaccepted memory.// But this defitinion has not been officially in the PI spec. Base// on the code-first we define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED at// MdeModulePkg/Include/Pi/PrePiHob.h and update EFI_RESOURCE_MAX_MEMORY_TYPE// to 8. After BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED is officially published// in PI spec, we will re-visit here.//// #define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000008

包含的属性:

//// These types can be ORed together as needed.//// The following attributes are used to describe settings//#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080//// This is typically used as memory cacheability attribute today.// NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED// as Physical write protected attribute, and EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED// means Memory cacheability attribute: The memory supports being programmed with// a writeprotected cacheable attribute.//#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200#define EFI_RESOURCE_ATTRIBUTE_PERSISTENT 0x00800000//// The rest of the attributes are used to describe capabilities//#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000//// This is typically used as memory cacheability attribute today.// NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE// as Memory capability attribute: The memory supports being protected from processor// writes, and EFI_RESOURCE_ATTRIBUTE_WRITE_PROTEC TABLE means Memory cacheability attribute:// The memory supports being programmed with a writeprotected cacheable attribute.//#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000#define EFI_RESOURCE_ATTRIBUTE_PERSISTABLE 0x01000000#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED 0x00040000#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE 0x00080000//// Physical memory relative reliability attribute. This// memory provides higher reliability relative to other// memory in the system. If all memory has the same// reliability, then this bit is not used.//#define EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE 0x02000000

在内存初始化完成之后,会调用该接口来定义内存的属性,比如:

//// Report first 640KB of memory//BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,MEM_TESTED_ATTR,(EFI_PHYSICAL_ADDRESS) (0),(UINT64) (0xA0000));//// Report first 0A0000h - 0FFFFFh as RESERVED memory//BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_RESERVED,MEM_TESTED_ATTR,(EFI_PHYSICAL_ADDRESS) (0xA0000),(UINT64) (0x60000));//// Report first 0x100000 - FSP reserved memory as system memory//BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,MEM_TESTED_ATTR,(EFI_PHYSICAL_ADDRESS) (0x100000),(UINT64) (PeiMemBase - 0x100000));

在DXE阶段会收集这些HOB并初始化GDC(Global Coherency Domain)映射表。

GUID Extension HOB

该HOB术语自定义类型,如果我们需要自己创建从PEI阶段到DXE阶段传递数据的HOB,就可以使用这种类型,这也是BIOS开发时最可能用到的HOB,其结构体:

////// Allows writers of executable content in the HOB producer phase to/// maintain and manage HOBs with specific GUID.///typedef struct {////// The HOB generic header. Header.HobType = EFI_HOB_TYPE_GUID_EXTENSION.///EFI_HOB_GENERIC_HEADER Header;////// A GUID that defines the contents of this HOB.///EFI_GUID Name;//// Guid specific data goes here//} EFI_HOB_GUID_TYPE;

它是一个不定长的结构体,Name之后还可以有自定义的数据。这个的Name是一个唯一的GUID,后续DXE阶段通过该GUID来找到自定义的数据。

下面是一个示例,首选是HOB的创建,它位于PEI阶段,对应代码模块BeniPkg\Pei\HobProvider\HobProvider.inf:

EFI_STATUSEFIAPIHobProviderEntry (IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES **PeiServices){BENI_HOB_DATA *Hob = NULL;UINT8 Index = 0;DEBUG ((EFI_D_ERROR, "Creating HOB ...\n"));Hob = BuildGuidHob (&gBeniHobGuid, sizeof (BENI_HOB_DATA));if (NULL == Hob) {DEBUG ((EFI_D_ERROR, "[%a][%d] BuildGuidHob failed.\n", __FUNCTION__, __LINE__));return EFI_OUT_OF_RESOURCES;}for (Index = 0; Index < BENI_HOB_DATA_LEN; Index++) {Hob->Data[Index] = Index;}DEBUG ((EFI_D_ERROR, "Done\n"));return EFI_SUCCESS;}

然后在DXE阶段就可以使用,对应模块BeniPkg\Dxe\HobConsumer\HobConsumer.inf:

EFI_STATUSEFIAPIHobConsumerEntry (IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){EFI_PEI_HOB_POINTERS Hob;UINTN Index = 0;UINT8 *Data = NULL;Hob.Raw = GetFirstGuidHob (&gBeniHobGuid);if (NULL == Hob.Raw) {DEBUG ((EFI_D_ERROR, "[%a][%d] Failed. - %r\n", __FUNCTION__, __LINE__, EFI_NOT_FOUND));return EFI_NOT_FOUND;}Data = (UINT8 *)(GET_GUID_HOB_DATA (Hob.Raw));DEBUG ((EFI_D_ERROR, "BENI Hob data:\n"));for (Index = 0; Index < BENI_HOB_DATA_LEN; Index++) {DEBUG ((EFI_D_ERROR, "0x%02x ", *(Data + Index)));}DEBUG ((EFI_D_ERROR, "\n"));return EFI_SUCCESS;}

End of HOB List

HOB列表的最后是一个End of HOB,它有特定了类型EFI_HOB_TYPE_END_OF_HOB_LIST,在PHIT HOB中就有一个成员EfiEndOfHobList指向它。

其它

还有跟FV、CPU、SMRAM相关的HOB,这里就不再介绍了,有兴趣的可以直接看PI手册。

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477