我的BIOS之行5-hob的使用
HOB(hand off block)简介
有些时候,我们需要将一些information从PEI阶段传递到DXE阶段,那么这个时候我们就需要hob当做桥梁来给我们进行传递了。总的来说,PEI生产HOB,DXE消费HOB,在这里需要注意HOB只有在PEI阶段是可修改的,在DXE阶段是只读的,每一个Block都有自己的GUID与Struct
运作模式
当PEI阶段的module需要传递信息给DXE时,会Call PEI Service去建立一个HOB的block,并加载在HOB的list上。
HOB使用的实例
在这里我是将上一章所使用的setup的item选项联系起来,在PEI阶段获取item的值,并建立HOB,将item的值进行保存,然后由DXE阶段获取。
具体需要看源码的请移步我的github的homework项目
HOB在PEI阶段
新建pei文件并获取item的值
在sdl文件中加入
TOKEN
Name = "HomeWorkPeim_INF_SUPPORT"
Value = "1"
Help = "Main switch to enable HomeWorkDxe support in Project"
TokenType = Boolean
Token = "HomeWork_SUPPORT" "=" "1"
End
INFComponent
Name = "HomeWorkPeim"
File = "Pei/HomeWorkPeim.inf"
Package = "Homework"
ModuleTypes = "PEIM"
Token = "HomeWorkPeim_INF_SUPPORT" "=" "1"
End
这样就已经将PEI的inf文件定义好了,此时要做的是在module的目录中建立Pei目录并在其中新建HomeWorkPeim.c/HomeWorkPeim.inf
并在inf文件中
[Defines]
INF_VERSION = 0x00010015
BASE_NAME = HomeWorkPeim
FILE_GUID = d133c000-7911-4e7f-abff-71f14f3337a8
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = HomeWorkPeimEntryPoint
定义这个PEI文件的name 与入口参数,还有一些guid,依赖等,这个在后续专门出博客来讲解inf的一些定义,这里主要讲hob,我就不描述了。
注意:这里的入口函数一定要与C文件对应
同时你需要在module建立一个homework.h文件用于建立hob所需要的结构体与GUID
#define HOMEWORK_HOB_GUID \
{0x6ff0434a, 0x9598, 0x42cc, 0xb7, 0x38, 0xad, 0x17, 0x55, 0x48, 0x42, 0x9c}
typedef struct {
EFI_HOB_GUID_TYPE EfiHobGuidType;
UINT8 homeworkdata;
} HOMEWORK_HOB;
如前面所说,hob就是通过guid来获取相关的信息,那么这个GUID就必须可以让PEI阶段的文件抓取的到,有可以让DXE文件抓取的到。
首先要做的是讲setup的值获取到,此时你需要用到的是gEfiPeiReadOnlyVariable2PpiGuid这个PPI。至于什么是PPI请移步我前面发布的一些博客
EFI_GUID SetupGuid = SETUP_GUID;
EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable;
UINTN VariableSize;
SETUP_DATA SetupData;
Status = PeiServicesLocatePpi(&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, &ReadOnlyVariable);
// ASSERT_EFI_ERROR(Status);
VariableSize = sizeof(SETUP_DATA);
Status = ReadOnlyVariable->GetVariable(ReadOnlyVariable, L"Setup", &SetupGuid, NULL, &VariableSize, &SetupData);
if (EFI_ERROR(Status)) {
return Status;
}
通过ReadOnlyVariable->GetVariable方法来获取setup的所有值。
创建一个hob
HOMEWORK_HOB *homeworkhob = NULL;
EFI_GUID homeworkHobGuid = HOMEWORK_HOB_GUID;
Status = (*PeiServices)->CreateHob (
PeiServices,
EFI_HOB_TYPE_GUID_EXTENSION,
sizeof(HOMEWORK_HOB),
&homeworkhob);
if (EFI_ERROR(Status)) {
return Status;
}
仔细看这些code你会发现用到了h文件中定义的GUID与结构体,当然这边只是做了一个简单的数据类型,其实你可以做得更加多的东西。
讲取到的值放入hob中
homeworkhob->EfiHobGuidType.Name=homeworkHobGuid;
homeworkhob->homeworkdata=SetupData.HomeWorkoption;
这里的HomeWorkoption就是我们上一文所加的新选项
HOB在Dxe阶段
新建inf文件
同样的道理需要新建inf文件,加入相关的依赖项
[Defines]
INF_VERSION = 0x00010015
BASE_NAME = HomeWorkDxe
FILE_GUID = 43a12ef5-0372-4119-9f0f-000a8c104c62
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = HomeWorkDxeEntryPoint
新建dxe的 c文件
EFI_GUID GuidHob = HOB_LIST_GUID;
EFI_STATUS Status;
HOMEWORK_HOB *Homeworkhob=NULL;
EFI_GUID HomeworkHobGuid=HOMEWORK_HOB_GUID;
VOID *pHobList = NULL;
pHobList = GetEfiConfigurationTable(SystemTable, &GuidHob);
if (!pHobList) return EFI_NOT_READY;
Homeworkhob = (HOMEWORK_HOB*)pHobList;
while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &Homeworkhob)))
{
if (guidcmp(&(*Homeworkhob).EfiHobGuidType.Name, &HomeworkHobGuid) == 0)
break;
}
if (EFI_ERROR(Status))
{
return EFI_NOT_FOUND;
}else{
OEM_TRACE("data=%d\n",Homeworkhob->homeworkdata);
}
在dxe阶段,你需要通过GetEfiConfigurationTable拿到hob list的hander,也相当与一个链表的头指针,然后通过FindNextHobByType去遍历这个链表,通过比较GUID进行锁定,并把值写出来。
在这里我提醒一下,所谓的OEM_TRACE是我们自主写的一个module用于串口debug的。如果有可能,我会在纯净的UEFI中再做这个module,让大家可以进行自行编译,而不是现在的只能看博客。
出处:http://www.cnblogs.com/samuelwnb/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任