PEI编程练习 - hob简单练习

2024-01-18 23:40
文章标签 简单 编程 练习 pei hob

本文主要是介绍PEI编程练习 - hob简单练习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、HOB (Hand-off Block) 的认识

详情参考: Platform Initialization (PI) Specification

  • 在PEI Phase 中,使用的数据存储区就叫做HOBs,PEI可以使用HOB向DXE传递信息。
  • 在PEI Phase 中,HOBs是可读可写的,在DXE Phase中,只能读。
  • HOB是系列的连续的内存结构体,可以认为其由三部分构成:第一部分,是 Phase Handoff Information Table (PHIT) 头,它描述了HOB的起始地址以及总的内存使用;第二部分是各个Hob列表,DXE阶段会根据这一部分获取上关资源;第三部分是结束部分。
    在这里插入图片描述
  • The first HOB in the HOB list must be the Phase Handoff Information
  • Table (PHIT) HOB. The last HOB in the HOB list must be the End of HOB List HOB. Only HOB producer phase components are allowed to make
    additions or changes to HOBs. Once the HOB list is passed into the
    HOB consumer phase, it is effectively read only. The ramification of
    a read-only HOB list is that handoff information, such as boot mode,
    must be handled in a distinguished fashion. For example, if the HOB
    consumer phase were to engender a recovery condition, it would not
    update the boot mode but instead would implement the action using a
    special type of reset call.
  • The HOB list contains system state data at the time of HOB producer–to–HOB producer handoff and does not represent the current
    system state during the HOB consumer phase.
  • The HOB list is initially built by the HOB producer phase. The HOB list is created in memory that is present, initialized, and tested.
    Once the initial HOB list has been created, the physical memory
    cannot be remapped, interleaved, or otherwise moved by a subsequent
    software agent.

翻译:

  • 在HOB List中的第一个HOB必须是PHIT HOB(Phase Handoff Information Table),最后一个HOB必须是End of HOB List HOB。
  • 只有PEI Phase才允许增加或改动这些HOBs,当HOB List被传送给DXE Phase之后,他们就是只读的(Read Only)。一个只读的HOB List的延伸就是Handoff 信息,比如Boot Mode,必须以别的方式来处理。比如,DXE
    Phase想要产生一个Recovery条件,它不能update Boot Mode,而是通过使用特殊方式的reset call来实现。
  • 在HOB中包含的系统状态数据(System State Data)是指在PEI to DXE Handoff的时候的系统状态,而不是代表DXE当前的系统状态。
  • HOB list是在PEI Phase被建立的,它存在于已经present,initialized,tested的Memory中。一旦最初的HOB
    List被创建,物理内存就不能被remapped, interleaved, 或者被后来的程序moved。
    HOB在PEI到DXE传送信息的过程遵循one Producer to one
    Consumer的模式,即在PEI阶段,一个PEIM创建一个HOB,在DXE阶段,一个DXE
    Driver使用那个HOB并且把HOB相关的信息传送给其他的需要这些信息的DXE组件。

HOB Construction Rules HOB construction must obey the following rules:

  1. All HOBs must start with a HOB generic header. This requirement allows users to locate the HOBs in which they are interested while
    skipping the rest. See the EFI_HOB_GENERIC_HEADER definition.
  2. HOBs may contain boot services data that is available during the HOB producer and consumer phases only until the HOB consumer phase is
    terminated.
  3. HOBs may be relocated in system memory by the HOB consumer phase. HOBs must not contain pointers to other data in the HOB list,
    including that in other HOBs. The table must be able to be copied
    without requiring internal pointer adjustment.
  4. All HOBs must be multiples of 8 bytes in length. This requirement meets the alignment restrictions of the Itanium ® processor family.
  5. The PHIT HOB must always begin on an 8-byte boundary. Due to this requirement and requirement #4 in this list, all HOBs will begin on an
    8-byte boundary.
  6. HOBs are added to the end of the HOB list. HOBs can only be added to the HOB list during the HOB producer phase, not the HOB consumer
    phase.
  7. HOBs cannot be deleted. The generic HOB header of each HOB must describe the length of the HOB so that the next HOB can be found. A
    private GUIDed HOB may provide a mechanism to mark some or its entire
    contents invalid; however, this mechanism is beyond the scope of this
    document.

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

  1. 每个HOB必须以一个HOB generic header开头(EFI_HOB_GENERIC_HEADER)。
  2. HOBs可以包含boot services data,在DXE Phase结束之前,PEI和DXE都可以调用。
  3. HOBs可以被DXE重新安置在系统内存上,每个HOB都不能包含指向HOB List中其他数据的指针,也不能指向其他的HOB,这个Table必须可以被Copied而不需要任何内部指针的调整。
  4. 所有的HOB在长度上必须是8 bytes的倍数,是alignment的要求。
  5. PHIT HOB必须总是在8 byte处开始。
  6. 增加的HOB总是被加到HOB List的最后,而且只能在PEI Phase(HOB Producer Phase)增加,DXE Phase(HOB Consumer Phase)不能。
  7. HOBs不能被删除。每个HOB的generic header中都会描述这个HOB的长度,这样下一个HOB就很容易被找到。

Adding to the HOB List

To add a HOB to the HOB list, HOB consumer phase software must obtain a pointer to the PHIT HOB (start of the HOB
list) and follow these steps:

  1. Determine NewHobSize, where NewHobSize is the size in bytes of the HOB to be created.
  2. Check free memory to ensure that there is enough free memory to allocate the new HOB. This test is performed by checking that
    NewHobSize <= PHIT->EfiFreeMemoryTop - PHIT->EfiFreeMemoryBottom).
  3. Construct the HOB at PHIT->EfiFreeMemoryBottom.
  4. Set PHIT->EfiFreeM

翻译:
增加新的HOB到HOB List中 PEI Phase(HOB 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 。

代码中表示:

EDK/edk2/MdePkg/Include/Pi/PiHob.h 中:
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;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;//
// 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简单练习

  1. 在PEI Phase建一个GUID类型的hob
  2. 在DXE Phase去使用这个hob

BuildGuidHob

c文件

PATH:

edk2/EmulatorPkg/TestByMy/PeiTest/MyFirstPeiHob/MyFirstHob.c

code:

/*++ @fileCopyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2011, Apple Inc. All rights reserved.**/
#include <Uefi.h>
#include <Uefi/UefiBaseType.h>
#include <Pi/PiPeiCis.h>
#include <Ppi/MemoryDiscovered.h>#include <Library/DebugLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/HobLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/MemoryAllocationLib.h>/**This funtion is  printf  str in debug@return status
**/
EFI_STATUS
EFIAPI
PrintMesg (VOID)
{DEBUG ((DEBUG_INFO, "Mesg for in pei hob!\n"));return EFI_SUCCESS;
}/**This funtion is  printf  str in debug@return status
**/
typedef 
EFI_STATUS 
(EFIAPI *PEI_HOB_MESSG) (VOID);typedef struct {INT32  number;PEI_HOB_MESSG  PrintMesg;
}TEST_STR;extern EFI_GUID gMyFirstHobGuid;EFI_STATUS
EFIAPI
MyFirstHobEntry(IN       EFI_PEI_FILE_HANDLE  FileHandle,IN CONST EFI_PEI_SERVICES     **PeiServices
)/*++
creat a hob for guid
Arguments:FfsHeader   - General purpose data available to every PEIMPeiServices - General purpose services available to every PEIM.Returns:None
**/
{EFI_STATUS                     Status;// EFI_HOB_MEMORY_ALLOCATION      *Hob; IN UINTN                       DataLength;TEST_STR                       *Data;TEST_STR                       *HobData;UINTN                           Temp;for(Temp = 0; Temp <= 5; Temp++) {DEBUG ((DEBUG_INFO, "\n"));}DEBUG ((DEBUG_INFO, "Peim creat hob is start!..\n"));DataLength = sizeof(TEST_STR);Status = (*PeiServices)->AllocatePool (PeiServices, DataLength, (VOID **)&Data);ASSERT (!EFI_ERROR (Status));Data->number=123;Data->PrintMesg=PrintMesg;HobData = BuildGuidHob (&gMyFirstHobGuid, DataLength);ASSERT (HobData != NULL);CopyMem (HobData, Data, DataLength);//*NewData = (UINTN)NewBase;/*(*PeiServices)->CreateHob (PeiServices,EFI_HOB_TYPE_MEMORY_ALLOCATION,sizeof (EFI_HOB_MEMORY_ALLOCATION),(VOID **)&Hob);Status = (*PeiServices)->AllocatePool (PeiServices, DataLength, (VOID **)&Data);ASSERT (!EFI_ERROR (Status));Data->number=123;Data->PrintMesg=PrintDxeMesg;Hob->AllocDescriptor.Name = gMyFirstHobGuid;Hob->AllocDescriptor.MemoryBaseAddress = (EFI_MEMORY_TYPE)Data;Hob->AllocDescriptor.MemoryLength = DataLength;Hob->AllocDescriptor.MemoryType = EfiMemoryMappedIO;*/DEBUG ((DEBUG_INFO, "Peim creat hob is end!..\n"));return Status;
}

inf文件

PATH:

edk2/EmulatorPkg/TestByMy/PeiTest/MyFirstPeiHob/MyFistHob.inf

code:

## @file
# for creat hob
#
#  
#
#
##[Defines]INF_VERSION                    = 0x00010005BASE_NAME                      = MyFirstHobFILE_GUID                      = 2D6F6B11-9681-8E11-8579-B57DCD006011MODULE_TYPE                    = PEIMVERSION_STRING                 = 1.0ENTRY_POINT                    = MyFirstHobEntry[Sources]MyFirstHob.c[Packages]MdePkg/MdePkg.decMdeModulePkg/MdeModulePkg.decEmulatorPkg/EmulatorPkg.dec[LibraryClasses]PeiServicesTablePointerLibPeiServicesLibHobLibBaseMemoryLibBaseLibPeimEntryPointDebugLibMemoryAllocationLib[Guids]gMyFirstHobGuid[Depex]TRUE

dec文件

把对应使用的gMyFirstHobGuid加入到全局变量
PATH:

edk2/EmulatorPkg/EmulatorPkg.dec

code:

[Guids]gMyFirstHobGuid            = { 0xf2bdaa96, 0x89a5, 0x11db, { 0x87, 0x19, 0x00, 0x40, 0xd0, 0x2b, 0x18, 0x35 } }  

dsc文件

加入到编译中
PATH:

edk2/EmulatorPkg/EmulatorPkg.dsc

code:

  ###  PEI Phase modules##EmulatorPkg/TestByMy/PeiTest/MyFirstPeiHob/MyFistHob.inf

fdf文件

加入到fd中
PATH:

edk2/EmulatorPkg/EmulatorPkg.fdf

code:

#
#  PEI Phase modules
#
INF  EmulatorPkg/TestByMy/PeiTest/MyFirstPeiHob/MyFistHob.inf  

LocateGuidHob

c文件

PATH:

edk2/EmulatorPkg/TestByMy/PeiTest/MyLocateMyHob/DxeDriverLocateMyHob.c

code:

#include <Uefi.h>#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/HobLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>#include <PiPei.h>
#include <Guid/MemoryAllocationHob.h>
#include <Pi/PiHob.h>/**This funtion is  printf  str in debug@return status
**/
typedef 
EFI_STATUS 
(EFIAPI * PEI_HOB_MESSG) (VOID);typedef struct {INT32  number;PEI_HOB_MESSG  PrintMesg;
}TEST_STR;extern EFI_GUID gMyFirstHobGuid;EFI_STATUS
EFIAPI
LocateMyHobEntry(IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable
)
/**a Dxe Drier to locate my hob.@param ImageHandle     Image handle this driver.@param SystemTable     Pointer to SystemTable.@retval EFI_SUCESS     This function always complete successfully.**/
{EFI_STATUS               Status;UINTN                    Temp;TEST_STR                 *PacketHeader;EFI_PEI_HOB_POINTERS      HobPointer;for(Temp = 0; Temp <= 5; Temp++) {DEBUG ((EFI_D_ERROR, "\n"));}DEBUG ((DEBUG_INFO, "dxe locate hob is start!..\n"));HobPointer.Raw = GetFirstGuidHob (&gMyFirstHobGuid);PacketHeader = (TEST_STR *) GET_GUID_HOB_DATA (HobPointer.Guid);PacketHeader->PrintMesg();/*HobPointer.Raw = GetHobList ();while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION,HobPointer.Raw)) != NULL) {if(CompareGuid(&(HobPointer.MemoryAllocation->AllocDescriptor.Name), &gMyFirstHobGuid)){Data = (TEST_STR *)HobPointer.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;DEBUG ((EFI_D_ERROR, "number is:%d\n",Data->number));Data->PrintMesg();return EFI_SUCCESS;}HobPointer.Raw = GET_NEXT_HOB (HobPointer);}*/DEBUG ((DEBUG_INFO, "dxe locate hob is end!..\n"));Status=EFI_SUCCESS;return Status;
}

inf文件

PATH:

edk2/EmulatorPkg/TestByMy/PeiTest/MyLocateMyHob/DxeDriverLocateMyHob.inf

code:

## @file
#  locate my hob
#
#
#
#
##[Defines]INF_VERSION                    = 0x00010005BASE_NAME                      = LocateMyHobFILE_GUID                      = 69879123-ED74-44db-AE97-1FA5E4ED2116MODULE_TYPE                    = UEFI_DRIVERVERSION_STRING                 = 1.0ENTRY_POINT                    = LocateMyHobEntry[Sources]DxeDriverLocateMyHob.c[Packages]MdePkg/MdePkg.decMdeModulePkg/MdeModulePkg.decEmulatorPkg/EmulatorPkg.dec[LibraryClasses]DebugLibUefiDriverEntryPointBaseLibBaseMemoryLibDevicePathLibUefiBootServicesTableLibMemoryAllocationLibUefiLibHobLib[Guids]gMyFirstHobGuid[Depex]TRUE

dsc文件

PATH:

edk2/EmulatorPkg/EmulatorPkg.dsc

code:

  #  DXE Phase modules###EmulatorPkg/TestByMy/PeiTest/MyLocateMyHob/DxeDriverLocateMyHob.inf

fdf文件

#
#  DXE Phase modules
#
INF  EmulatorPkg/TestByMy/PeiTest/MyLocateMyHob/DxeDriverLocateMyHob.inf

结果

在这里插入图片描述在这里插入图片描述

这篇关于PEI编程练习 - hob简单练习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/620636

相关文章

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要