BIOS开发之HOB

HOB

HOB Hand-Off Blocks )传输信息的载体。相比于其他 Phase 之间的联系,PeiDXE之间联系比较薄弱,PEI一 些初始化硬件、内存的数据等,DXE需要知道,HOB便作为桥梁应运而生。分为两个阶段:

1HOB producer phase (HOB 生产者阶段) 是创建 HOB HOB 列表的预引导阶段。(PEI phase)

2HOB consumer phase HOB 消费者阶段)是预引导阶段,HOB列表传递到该阶段然后被消费。(PEI & DXE phase) HOBPEIDXE传送信息的过程遵循one Producer to one Consumer 的模式,即在PEI阶段,一个PEIM创建一个 HOB,在DXE阶段,一个DXE Driver使用那个HOB并且把HOB相关的信息传送给其他的需要这些信息的DXE组件。

HOB LIST

HOB 列表最初由 HOB 生产者阶段构建。 HOB 列表是在存在、初始化和测试的内存中创建的。

HOB list 是在 PEI Phase 被建立的,它存在于已经presentinitializedtested Memory 中。一旦最初的 HOB List 被创 建,物理内存就不能被remapped, interleaved, 或者被后来的程序moved

1、在PEI Phase 中,使用的数据存储区就叫做HOBsPEI 可以使用HOBDXE传递信息。 2、在PEI Phase 中,HOBs是可读可写的,在DXE Phase 中,只能读。 3HOB是系列的连续的内存结构体 (所有的Hob放在一段连续的内存里面),可以认为其由三部分构成: 第一部分,是 Phase Handoff Information Table (PHIT) 头, 它描述了HOB的起始地址、总的内存使用以及期间发现的 启动模式;

第二部分是各个Hob列表,DXE阶段会根据这一部分获取相关资源;

第三部分是结束部分。

这些在内存中的HOBs的连续的表被称为HOB List

HOB 生产者阶段内存映射和使用:

HOB TYPE

Hoblist 存储在PrivateData ,在 PEI 末阶段传入DXE。所有HOB类型如下:

// 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;

其中 EFI_HOB_GUID_TYPE 允许PEIM将私有数据传递 给DXE驱动程序 (自定义HOB时候会用到的类型,通常用于自己写一些HOB信息。

HOB 实现

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 内数据的格式和大小。 所有 HOB 都必须包含此通用 HOB 标头。

typedef struct {

  // 标识 HOB 数据结构类型。

  UINT16        HobType;

  // HOB 的字节长度。

  UINT16        HobLength; // 该字段必须始终设置为零

  UINT32        Reserved;

} EFI_HOB_GENERIC_HEADER;

// EFI_HOB_HANDOFF_INFO_TABLE 中的版本值。

#define EFI_HOB_HANDOFF_TABLE_VERSION           0x0009

// 包含 HOB 生产者阶段使用的一般状态信息。

// HOB 必须是 HOB 列表中的第一个。

typedef struct {

/// HOB 通用标头。 Header.HobType = EFI_HOB_TYPE_HANDOFF. EFI_HOB_GENERIC_HEADER          Header;

// PHIT HOB 定义有关的版本号。

// 这个值是四个字节的长度,当它与 4 字节的 BootMode 组合 时提供一个 8 字节对齐的条目。

UINT32                                 Version;

// HOB 生产者阶段确定的系统引导模式。

EFI_BOOT_MODE                 BootMode;

// 分配给 HOB 生产者阶段使用的内存的最高地址位置。

//此地址必须对齐 4 KB 以满足 UEFI 的页面限制。

EFI_PHYSICAL_ADDRESS      EfiMemoryTop;

// 分配给 HOB 生产者阶段使用的内存的最低地址位置。

EFI_PHYSICAL_ADDRESS      EfiMemoryBottom;

// 当前可供 HOB 生产者阶段使用的空闲内存的最高地址位置。

EFI_PHYSICAL_ADDRESS      EfiFreeMemoryTop;

// 可供 HOB 生产者阶段使用的空闲内存的最低地址位置。

EFI_PHYSICAL_ADDRESS      EfiFreeMemoryBottom;

// HOB 列表的结尾。

EFI_PHYSICAL_ADDRESS      EfiEndOfHobList;

} EFI_HOB_HANDOFF_INFO_TABLE;

PHIT 初始化

PeiCore -> InitializeMemoryServices -> PeiCoreBuildHobHandoffInfoTable

构造HOB 必须遵循以下的规则:

1、每个HOB必须以一个HOB generic header开头 (EFI_HOB_GENERIC_HEADER)。此要求允许用户在跳 过其余部分时找到他们感兴趣的 HOB

2HOBs可以包含boot services data,在 DXE Phase 结束之前,PEIDXE都可以调用。

3HOBs可以被DXE重新安置在系统内存上,每个HOB 都不能包含指向HOB List中其他数据的指针,也不能指向 其他的HOB,这个Table必须可以被Copied而不需要任何 内部指针的调整。

4、所有的HOB在长度上必须是8 bytes的倍数。此要求符 合 Itanium® 处理器系列的对齐限制。

5PHIT HOB 必须总是在8 byte处开始。由于此要求和此列表中的要求 #4,所有 HOB 都将从 8 字节边界开始。

6、增加的HOB总是被加到HOB List的最后,而且只能在 PEI PhaseHOB Producer Phase)增加,DXE PhaseHOB Consumer Phase)不能。

7HOBs不能被删除。每个HOBgeneric header中都会 描述这个HOB的长度,这样下一个HOB就很容易被找到。

如下:

edk2\MdeModulePkg\Core\Pei\Hob\Hob.c

/**

构建切换信息表 HOB

@param BootMode - 当前引导模式

@param MemoryBegin - 起始内存地址。

@param MemoryLength - 内存长度。

@return EFI_SUCCESS 总是成功初始化 HOB

**/

EFI_STATUS

PeiCoreBuildHobHandoffInfoTable (

  IN EFI_BOOT_MODE BootMode              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;

}

增加一个新的HOBHOB List

PEI PhaseHOB Producer Phase)肯定包含一个指向 PHIT HOB(这是HOB List的开始)的指针,然后遵循以下的步骤:

1、确定NewHobSize,即确定要创建的HOB的大小(以Byte为单位)。

2、确定是否有足够的空闲内存分配给新的HOB NewHobSize <= (PHIT->EfiFreeMemoryTop - PHIT->EfiFreeMemoryBottom))。

3、在(PHIT->EfiFreeMemoryBottom)处构建 HOB

4、设置PHIT->EfiFreeMemoryBottom = PHIT->EfiFreeMemoryBottom + NewHobSize

/**

将新的 HOB 添加到 HOB 列表。

@param PeiServices 指向 PEI 基金会发布的 EFI_PEI_SERVICES 表的间接指针。

@param Type HOB 的类型。

@param Length 要分配的新 HOB 的长度。

@param Hob 指向新 HOB 的指针。

@return EFI_SUCCESS 成功创建 HOB

@retval EFI_INVALID_PARAMETER 如果 Hob NULL

@retval EFI_NOT_AVAILABLE_YET 如果 HobList 仍然不可用。

@retval EFI_OUT_OF_RESOURCES 如果没有更多内存来增长 Hoblist

**/

EFI_STATUS

EFIAPI

PeiCreateHob (

  IN CONST EFI_PEI_SERVICES   **PeiServices,

  IN UINT16                               Type,      

  IN UINT16                               Length,

  IN OUT VOID                          **Hob

  )

{

  EFI_STATUS                                       Status;

  EFI_HOB_HANDOFF_INFO_TABLE      *HandOffHob;

  EFI_HOB_GENERIC_HEADER               *HobEnd;

  EFI_PHYSICAL_ADDRESS                     FreeMemory;

  Status = PeiGetHobList (PeiServices, Hob);

  if (EFI_ERROR(Status)) {

    return Status;

 }

  HandOffHob = *Hob;

  //

  // Check Length to avoid data overflow.

  //

  if (0x10000 - Length <= 0x7) {

    return EFI_INVALID_PARAMETER;

  }

Length = (UINT16)((Length + 0x7) & (~0x7));

FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;

if (FreeMemory < Length) {

DEBUG ((EFI_D_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));

DEBUG ((EFI_D_ERROR, " FreeMemoryTop (UINTN)HandOffHob->EfiFreeMemoryTop)); - 0x%08x\n",

DEBUG ((EFI_D_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));

return EFI_OUT_OF_RESOURCES;

}

*Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;

((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type;

((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0;

HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);

HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;

HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;

HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);

HobEnd->Reserved = 0;

HobEnd++;

HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;

return EFI_SUCCESS;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值