本文主要是介绍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:
- 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.- HOBs may contain boot services data that is available during the HOB producer and consumer phases only until the HOB consumer phase is
terminated.- 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.- All HOBs must be multiples of 8 bytes in length. This requirement meets the alignment restrictions of the Itanium ® processor family.
- 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.- 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.- 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必须遵循以下的规则:
- 每个HOB必须以一个HOB generic header开头(EFI_HOB_GENERIC_HEADER)。
- HOBs可以包含boot services data,在DXE Phase结束之前,PEI和DXE都可以调用。
- HOBs可以被DXE重新安置在系统内存上,每个HOB都不能包含指向HOB List中其他数据的指针,也不能指向其他的HOB,这个Table必须可以被Copied而不需要任何内部指针的调整。
- 所有的HOB在长度上必须是8 bytes的倍数,是alignment的要求。
- PHIT HOB必须总是在8 byte处开始。
- 增加的HOB总是被加到HOB List的最后,而且只能在PEI Phase(HOB Producer Phase)增加,DXE Phase(HOB Consumer Phase)不能。
- 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:
- Determine NewHobSize, where NewHobSize is the size in bytes of the HOB to be created.
- 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).- Construct the HOB at PHIT->EfiFreeMemoryBottom.
- Set PHIT->EfiFreeM
翻译:
增加新的HOB到HOB List中 PEI Phase(HOB Producer Phase)肯定包含一个指向PHIT
HOB(这是HOB List的开始)的指针,然后遵循以下的步骤:
- 确定NewHobSize,即确定要创建的HOB的大小(以Byte为单位)。
- 确定是否有足够的空闲内存分配给新的HOB(NewHobSize <= (PHIT->EfiFreeMemoryTop - PHIT->EfiFreeMemoryBottom))。
- 在(PHIT->EfiFreeMemoryBottom)处构建HOB。
- 设置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简单练习
- 在PEI Phase建一个GUID类型的hob
- 在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简单练习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!