一、 编写源代码
-
编写UEFI PEI 驱动
代码C:\edkii\OvmfPkg\MyHelloWorldPEIMHob\MyHelloWorldPEIMHob.c,EFI_GUID gMyHelloWorldPEIGUID = { 0xbdb38129, 0x4d65, 0x39f4, { 0x72, 0x12, 0x68, 0xcf, 0x5a, 0x19, 0xa, 0xf8 }}; EFI_STATUS EFIAPI MyHelloWorldPEIMHobEntry( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status = EFI_SUCCESS; DEBUG ((EFI_D_ERROR, "[MyHelloWorldHob] MyHelloWorldPEIMHobEntry Start..\n")); CHAR8 *Hob = NULL; PeiServices = GetPeiServicesTablePointer(); Status = PeiServicesCreateHob ( EFI_HOB_TYPE_MEMORY_ALLOCATION, 64, &Hob ); CHAR8 *HobEnd = (Hob + sizeof (EFI_HOB_GENERIC_HEADER)); EfiCommonLibCopyMem(HobEnd, &gMyHelloWorldPEIGUID, sizeof(gMyHelloWorldPEIGUID)); CHAR16 StrHob[] = L"CSDN HOB Data ..."; // EfiCommonLibCopyMem(HobEnd+16,StrHob,2*MyStrlen(StrHob,128)); EfiCommonLibCopyMem(HobEnd+16,StrHob,2*17); DEBUG ((EFI_D_ERROR, "[MyHelloWorldHob] MyHelloWorldPEIMHobEntry End..\n")); return Status; }
-
编写UEFI DXE 驱动
代码C:\edkii\OvmfPkg\MyHelloWorldDXEHob\MyHelloWorldDXEHob.c,EFI_GUID gMyHelloWorldPEIGUID = { 0xbdb38129, 0x4d65, 0x39f4, { 0x72, 0x12, 0x68, 0xcf, 0x5a, 0x19, 0xa, 0xf8 }}; EFI_STATUS EFIAPI MyHelloWorldDXEHobEntry( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status = EFI_SUCCESS; DEBUG ((EFI_D_ERROR , "[MyHelloWorldHob] MyHelloWorldDXEHobEntry Start..\n")); EFI_PEI_HOB_POINTERS Hob; UINT8 *HobEnd = NULL; Hob.Raw = GetHobList(); while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { // // Compare FileGuid both. // if (CompareGuid (&gMyHelloWorldPEIGUID, &Hob.MemoryAllocation->AllocDescriptor.Name) ) { DEBUG ((EFI_D_ERROR, "[MyHelloWorldHob] MyHelloWorldDXEHobEntry Guid:0x%x\n",Hob.MemoryAllocation->AllocDescriptor.Name.Data1)); HobEnd = (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + 16); DEBUG ((EFI_D_ERROR, "[MyHelloWorldHob] MyHelloWorldDXEHobEntry content:%s\n", (CHAR16 *)HobEnd)); return EFI_SUCCESS; } Hob.Raw = GET_NEXT_HOB (Hob); } DEBUG ((EFI_D_ERROR , "[MyHelloWorldHob] MyHelloWorldDXEHobEntry End..\n")); return Status; }
二、 编译生成EFI文件
运行edksetup.bat
编译整个OvmfPkg Package
三、 运行 DXE Driver MyHelloWorldDXEHob
与PEI Driver MyHelloWorldPEIMHob
- 拷贝
C:\edkii\Build\OvmfX64\DEBUG_VS2013x86\FV\OVMF.fd
到C:\qemu
; - 执行
setup-qemu-x64.bat
| findstr MyHelloWorldHob
, 然后在UEFI SHELL
中执行MyHelloWorldAppProtocol.efi
,结果如下,
- 如果需要
dump
所有的PEI阶段创建的Hob
,可以使用以下code
Hob.Raw = GetHobList ();
for (; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
DEBUG((DEBUG_ERROR, "[Csdn] Guid:%g Type:0x%x Length:%x\n",
Hob.Guid,
Hob.Header->HobType,
Hob.Header->HobLength
));
}
四、 小结
UEFI提供了HOB(Hand-Off-Block)机制,即在PEI阶段将数据打包成数据块存放在一段连续的内存中,数据块的标识为GUID,DXE阶段可以通过该GUID在HOB中找到对应数据块。
HOB 是非常重要数据结构,在CAR时期将会初始化好,UEFI的早期的堆栈都基于HOB,
PEI Phase会创建大量的HOB,包含板级数据(UBA), silicon Hob(Memmap, RC resource),Setup,当进入PEI PostMem phase后,CAR里的HOB会shadown到Mem, 当进入DXE(调用TempPtr.DxeIpl->Entry)后,
这些HOB会被DXE driver大量采用, 用来创建Protocol或者其他初始化。
注意:
HOB 在PEI阶段会被修改,在DXE和SMM中会被使用,原则上不推介SMM修改HOB。创建的单个HOB
Size最大为64K(ASSERT (DataLength <= (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE))); // Make sure that data length is not too long.
),需要大数据量的HOB需要注意。
HOB 创建的接口除了上文还有如下通用做法,
Opt1:
MyHelloWorldPtr = AllocateZeroPool (TableLength);
(HELLOWROD_HOB *)MyHelloWorldPtr->xxx = xxx;
...
BuildGuidDataHob (&gMyHelloWorldPEIGUID, MyHelloWorldPtr, TotalLength);
Opt2:
MyHelloWorldPtr = BuildGuidHob (&mVpdBinHobGuid, TotalLength);
(HELLOWROD_HOB *)MyHelloWorldPtr->xxx = xxx;