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 启动前。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务