HOB的全称是Hand-Off Block,从名字上也可以看出来,它表示的是一种用于交接的数据。按照HOB的使用情况,可以将BIOS的启动阶段分为两个部分:
HOB生成阶段(HOB producer phase),用来创建和修改HOB;
HOB消费阶段(HOB consumer phase),用来使用HOB,注意此阶段HOB是只读的。
手册为了将x86的Platform Initialization扩展到更多的平台,已经不再直接使用PEI、DXE等阶段说明HOB的使用情况,不过对于x86架构的BIOS来说,HOB生成阶段其实就是SEC和PEI阶段,而HOB消费阶段就是DXE和BDS阶段。为了方便,本文还是直接使用PEI、DXE等术语。术语的对应关系如下表所示HOB的构成
HOB在PEI阶段创建,并返回一个列表(称为HOB List,HOB列表),其中的HOB一个个堆叠放置,最终构成如下的形式:
根据HOB中包含的数据的不同可以对HOB进行分类,且HOB列表的第一个必须要是PHIT HOB。PHIT的全称是Phase Handoff Information Table,它是第一个被创建的HOB,对应的指针在PEI的核心数据中:
HOB列表的最后是一个End of HOB,它有特定了类型EFI_HOB_TYPE_END_OF_HOB_LIST,在PHIT HOB中就有一个成员EfiEndOfHobList指向它。
Hob的类型:
//
// 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操作接口都是以这里为基础的,比如EFI_PEI_SERVICES中就有接口GetHobList()
创建PHIT HOB的大致流程如下(不同的平台可能会有不同):
Pei和Dxe阶段的HOB传递在代码中的体现为PeiMain中:HobList
TempPtr.DxeIpl->Entry (
TempPtr.DxeIpl,
&PrivateData.Ps,
PrivateData.HobList
);
DxeMain中:HobStart
DxeMain (IN VOID *HobStart)
注意:Dxe阶段只会读取Hob,不会改写Hob;
HOB结构的实现分为三部分,PHIT头,描述Hob的其实位置和内存使用信息;各种Hob的列表,Dxe从该列表上获取资源,传参为Hob Type和guid;最后时Hob结束部分;
第一次进入PeiCore的时候,还是Car阶段,内存没有初始化,InitializeMemoryServices 中调用PeiCoreBuildHobHandoffInfoTable开启HOB创建;位置在Car中;
CAR:Cache As Ram,CPU内缓存当临时memory使用,此时实际的memory未完成初始化;
每一个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 通过比对Hob type解析Hob表,还有一种扩展GUID的hob可以通过匹配Guid来查找hob表,
EFI_HOB_TYPE_GUID_EXTENSION
EFI_HOB_GUID_TYPE;这种类型结构体在hob中加入了guid 作为匹配信息、
HOB在HOB List里是连续创建的,在HOB header(EFI_HOB_GENERIC_HEADER)中描述了HOB的长度和Type,创建后的HOB是不能删除的,否则无法查找下一个HOB。
HOB的长度都是8字节对齐的;
Page是从高地址往低地址分配的,同时要创建一个HOB描述该Page。(调用allocatePages完成的工作)
Top要大于Bottom,否则无资源。
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;
/// The code portions of a loaded Boot Services Driver.
EfiBootServicesCode, //3
///
/// 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, //4
EDKii中打印Hob信息: