【UEFI基础】HOB介绍

news2024/11/25 14:41:10

综述

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_STATUS
EFIAPI
PeiGetHobList (
  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的大致流程如下(不同的平台可能会有不同):

PeiCore
InitializeMemoryServices
PeiCoreBuildHobHandoffInfoTable

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

EFI_STATUS
PeiCoreBuildHobHandoffInfoTable (
  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()创建,对应的流程:

PeiCore
PeiDispatcher
PeiCheckAndSwitchStack
BuildStackHob

函数实现的主要代码:

  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入口,创建的流程:

DxeLoadCore
BuildModuleHob

对应的代码:

  //
  // 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这个HOB
  DxeCoreHob.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);
  }

  // 获取到DxeCoreEntryPoint
  DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
  DxeCoreImageLength      = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
  DxeCoreEntryPoint       = (VOID *)(UINTN)DxeCoreHob.MemoryAllocationModule->EntryPoint;
  gDxeCoreFileName        = &DxeCoreHob.MemoryAllocationModule->ModuleName;

  // 安装Image Handle
  Image = &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.

**/
VOID
EFIAPI
BuildResourceDescriptorHob (
  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_STATUS
EFIAPI
HobProviderEntry (
  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_STATUS
EFIAPI
HobConsumerEntry (
  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手册。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/403380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PMP项目管理项目质量管理

目录1 项目质量管理概述2 规划质量管理3 管理质量4 控制质量1 项目质量管理概述 项目质量管理包括把组织的质量政策应用于规则、管理、控制项目和产品质量要求&#xff0c;以满足相关方目标的各个过程。项目质量管理还将以组织的名义支持过程的持续改进活动。 核心概念 质量是…

Elasticsearch:集群管理

在今天的文章中&#xff0c;我们应该学习如何管理我们的集群。 备份和分片分配是我们应该能够执行的基本任务。 分片分配过滤 Elasticsearch 将索引配到一个或多个分片中&#xff0c;我们可以将这些分片保存在特定的集群节点中。 例如&#xff0c;假设你有多个数据集群节点&am…

感应电机数学模型(电机控制应用基础系列)

电机在工业控制中的地位不言而喻&#xff0c;所以对电机模型的了解是我们理解各种算法的基础。这篇博客帮大家整理总结。张力控制离不开电机控制&#xff0c;有关张力控制的详细内容请参看下面的文章链接&#xff1a; PLC张力控制&#xff08;开环闭环算法分析&#xff09;_张…

字符函数和字符串函数详解(1)

目录前言strlen函数strlensizeofstrcpy函数strcat函数strcmp函数总结前言 最近要调整状态&#xff0c;写的文章质量不佳让大家失望&#xff0c;我现在也在反思我在做什么&#xff0c;我会什么&#xff0c;我学了什么。等我想明白的那天&#xff0c;我一定能跟大家顶峰相见的&a…

身份推理桌游

目录 sha人游戏&#xff08;天黑请闭眼&#xff09; &#xff08;1&#xff09;入门版 &#xff08;2&#xff09;标准版 &#xff08;3&#xff09;延伸版——百度百科 待更新 &#xff08;4&#xff09;延伸版——推理学院 待更新 狼人杀 1&#xff0c;基本玩法 2&am…

Android 12.0 Launcher3 app图标长按去掉应用信息按钮

1.前言 在12.0的rom定制化开发中,在Launcher3定制化开发中,对Launcher3的定制化功能中,在Launcher3的app列表页会在长按时,弹出微件和应用信息两个按钮,点击对应的按钮跳转到相关的功能页面, 现在由于产品需求要求禁用应用信息,不让进入到应用信息页面所以要去掉应用信息…

QT入门基础(一)

文章目录零.Qt背景1.什么是Qt2.Qt的发展史3.Qt的优势4.Qt应用一.第一个Qt程序0.项目创建1.main函数文件2.类头文件3.pro文件4.qt命名规范二.Qt按钮1.按钮创建和父子关系2.按钮常用api3.Qt窗口坐标体系4.对象树模型零.Qt背景 1.什么是Qt Qt是一个跨平台的C图形用户界面应用程序…

快速排序/快速选择算法

一.快速排序 1.基本介绍 快速排序&#xff08;Quicksort〉是对冒泡排序的一种改进,都属于交换排序。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分(每次选择中轴值)&#xff0c;中轴值左边的元素小于中轴值,中轴值右边的元素全部大于中轴值(但不要求有序)&#x…

Canvas详细使用方法(一)

Canvas Canvas的注意事项 < canvas > 和 < img > 元素很相像&#xff0c;唯一的不同就是它并没有 src 和 alt 属性。 -< canvas > 标签只有两个属性——width和height( 单位默认为px )。当没有设置宽度和高度时&#xff0c;canvas 会初始化宽为 300px 和高…

C#基础之面向对象编程(二)

总目录 文章目录总目录前言一、概述1. 定义2. 面向对象的三大特性二、封装1. 定义2. 属性三、继承1. 定义2. 继承的使用3. base 和this四、多态1. 定义2. 重写和重载3. 多态性的实现1、静态多态性2、动态多态性4. 向上转型和向下转型1、定义2、语法格式3、案例结语前言 本文主…

Docker常用项目实战演练

docker镜像源的修改 linux环境下编辑 /etc/docker/daemon.json vi /etc/docker/daemon.json #如添加如下网易镜像源 { "registry-mirrors": ["http://hub-mirror.c.163.com"] }docker run命令详细解释 日常工作中用的比较多的是docker run命令&#xff…

[ROC-RK3399-PC Pro] 手把手教你移植主线Buildroot(基于2023.02-rc3版本)

&#x1f347; 博主主页&#xff1a;Systemcall小酒屋&#x1f347; 博主简介&#xff1a;Neutionwei&#xff0c;C站嵌入式领域新星创作者之一&#xff0c;一枚热爱开源技术、喜欢分享技术心得的极客&#xff0c;注重简约风格&#xff0c;热衷于用简单的案例讲述复杂的技术&am…

机械学习 - 基础概念 - scikit-learn - 数据预处理 - 1

目录安装 scikit-learn术语理解1. 特征&#xff08;feature &#xff09;和样本&#xff08; sample / demo&#xff09;的区别&#xff1f;2. 关于模型的概念一、机械学习概念1. 监督学习总结&#xff1a;2. 非监督学习总结&#xff1a;3. 强化学习总结&#xff1a;三种学习的…

硬件基础常识【1】--如何让BJT工作在深度饱和区

引言BJT饱和的概念差不多的比喻特性曲线说明记忆NPN和PNP的小技巧- -保证一辈子不忘简单估算总结引言 学过模电或者做过一些电子作品的人都知道三极管这个器件&#xff0c;虽然是个小玩意&#xff0c;但在电路设计过程中承担了巨大的作用。BJT叫做双极结型三极管&#xff0c;可…

浏览器并发行为记录

使用nodejs koa起一个服务&#xff0c;使请求延时返回。 服务端代码 /** 延时 */ exports.timeoutTestData async function (ctx) {console.log(get query:, ctx.request.query);const query ctx.request.query;let timeout query.timeout || 2000;await new Promise(res…

vue专项练习

一、循环实现一个列表的展示及删除功能 1.1 列表展示 1、背景&#xff1a; 完成一个这样的列表展示。使用v-for 循环功能 id接口名称测试人员项目名项目ID描述信息创建时间用例数1首页喵酱发财项目a1case的描述信息2019/11/6 14:50:30102个人中心张三发财项目a1case的描述信…

Redis学习(13)之Lua脚本【环境准备】

文章目录一 Lua入门环境准备1.1 Lua简介1.2 Linux 系统安装Lua1.2.1 Lua 下载1.2.2 Lua 安装1.3 Hello World1.3.1 命令行模式1.3.2 脚本文件模式1.3.3 两种脚本运行方式1.4 Win安装Lua1.4.1 LuaForWindows的安装1.4.2 SciTE修改字体大小1.4.3 SciTE中文乱码1.4.4 SciTE快捷键工…

aws ecs 使用copilot快速创建ecs集群环境并部署服务

参考资料 https://github.com/aws/copilot-cli https://aws.github.io/copilot-cli/ https://github.com/aws-samples/amazon-ecs-cli-sample-app https://ecsworkshop.com/microservices/frontend/#deploy-frontend-0 ecs的服务部署从头开始需要进行以下操作 创建vpc等网…

JS中的事件、DOM操作

一、事件1.1 事件介绍事件: 就是发生在浏览器(页面)上一件事,键盘事件,鼠标事件,表单事件,加载事件等等1.2 事件绑定方式事件要想发生,就得将事件和标签先绑定一个完整的事件有三部分事件源(标签)什么事(事件)响应(动作效果)事件绑定,其实就是事件和标签绑定方式1: 事件源,事件…

IBM Semeru Windows 下的安装 JDK 17

要搞清楚下载那个版本&#xff0c;请参考文章&#xff1a;来聊聊 OpenJDK 和 JVM 虚拟机下载地址semeru 有认证版和非认证版&#xff0c;主要是因为和 OpenJ9 的关系和操作系统的关系而使用不同的许可证罢了&#xff0c;本质代码是一样的。在 Windows 下没有认证版&#xff0c;…