Bios实习 学习篇- 7.HOB 表
HOB 表(Hand-Off Block List) 是 UEFI Platform Initialization (PI) 规范中定义的核心数据传递机制,用于在 PEI(Pre-EFI Initialization)阶段结束后,将平台初始化信息(包括 PCIe 相关资源)可靠地“移交”给 DXE(Driver Execution Environment)阶段。它本质上是一个链表式的数据结构表(HOB List),由 PEI 阶段的模块(PEIM)在内存中构建,DXE 阶段的 PCI 总线驱动、PCI Host Bridge 驱动等通过遍历该表获取 PCIe 枚举、资源分配等必要信息。
1. HOB 表的整体结构(链表组织)
HOB 表是一个单向链表,存放在系统内存中(通常是临时内存,后续会重定位)。其结构严格遵循 PI 规范:
- 起始 HOB:必须是 PHIT HOB(Phase Handoff Information Table,类型 EFI_HOB_TYPE_HANDOFF),包含版本、Boot Mode、内存顶/底地址、HOB 列表结束指针等全局信息。
- 中间 HOB:任意数量的各类 HOB(Resource Descriptor、Memory Allocation、Firmware Volume 等)。
- 结束 HOB:必须是 End of HOB List HOB(类型 EFI_HOB_TYPE_END_OF_HOB_LIST),标记链表结束。
2.HOB Header(HOB 头)
每一个 HOB 的“统一前缀”,用来描述这个 HOB 是什么、占多大、怎么找到下一个,它是整个 HOB 机制里最基础、最核心的结构,没有它,HOB 表根本无法被解析。
3.HOB表的生命周期
PEI 阶段
│
├─ PEIM 1: 创建 HOB (Type 0x0001) ← PHIT HOB
├─ PEIM 2: 创建 HOB (Type 0x0004) ← FV HOB
├─ PEIM 3: 创建 HOB (Type 0x0003) ← GUID Extension HOB(自定义数据)
├─ PEIM 4: 创建 HOB (Type 0x0002) ← Memory Allocation HOB
│
└─ PEI Dispatcher 完成后
│
└─ 调用 DXE IPL(Initial Program Load)
│
└─ 将 HOB List 起始地址通过参数传递给 DXE Core
│
└─ DXE 阶段开始
│
├─ DXE Core 遍历 HOB List
├─ 根据 FV HOB 找到其他 DXE 驱动
├─ 根据 Memory HOB 了解内存布局
├─ 根据 GUID HOB 读取特定模块数据
│
└─ HOB List 在整个 DXE 阶段都有效(直到 BDS 阶段结束)
4.常用的 HOB API(EDK II)
PEI 阶段:创建 HOB
// 创建 GUID Extension HOB(最常用)
VOID *
EFIAPI
PeiServicesCreateHob (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN UINT16 Type,
IN UINT16 Length,
OUT VOID **Hob
);
// 更常用的封装(在 PeiLib.h 中)
VOID *
EFIAPI
BuildGuidDataHob (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_GUID *Guid,
IN VOID *Data,
IN UINTN DataLength
);
// 示例:创建一个自定义 HOB
EFI_STATUS
EFIAPI
MyPeimEntryPoint (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
MY_DATA_STRUCT Data = {0};
Data.Value = 0x1234;
BuildGuidDataHob (PeiServices, &gMyCustomGuid, &Data, sizeof(Data));
// 这个 HOB 会被加入 HOB List,DXE 阶段可以读取
}
DXE 阶段:读取 HOB
// 创建 GUID Extension HOB(最常用)
VOID *
EFIAPI
PeiServicesCreateHob (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN UINT16 Type,
IN UINT16 Length,
OUT VOID **Hob
);
// 更常用的封装(在 PeiLib.h 中)
VOID *
EFIAPI
BuildGuidDataHob (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN CONST EFI_GUID *Guid,
IN VOID *Data,
IN UINTN DataLength
);
// 示例:创建一个自定义 HOB
EFI_STATUS
EFIAPI
MyPeimEntryPoint (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
MY_DATA_STRUCT Data = {0};
Data.Value = 0x1234;
BuildGuidDataHob (PeiServices, &gMyCustomGuid, &Data, sizeof(Data));
// 这个 HOB 会被加入 HOB List,DXE 阶段可以读取
}
5. HOB 表存在哪里?
A: HOB List 存储在 临时内存(Temporary RAM) 中,通常是:
- x86 平台:Cache-as-RAM(CAR)或早期初始化的 DRAM
- ARM 平台:SRAM 或早期初始化的 DDR
PEI 阶段结束后,DXE Core 会将 HOB List 复制到永久内存(Permanent RAM) 中继续使用。
6.HOB 和 PPI / Protocol 有什么区别?
7.HOB List 什么时候被释放?
HOB List 在 BDS(Boot Device Selection)阶段结束后通常就不再需要了,但具体释放时机取决于平台实现。有些平台会一直保留到 OS 启动前。
