9

UEFI开发探索60-VFR文件和其他资源文件1(在BIOS setup上增加项)

 3 years ago
source link: http://yiiyee.cn/blog/2020/06/27/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a260-vfr%e6%96%87%e4%bb%b6%e5%92%8c%e5%85%b6%e4%bb%96%e8%b5%84%e6%ba%90%e6%96%87%e4%bb%b61%ef%bc%88%e5%9c%a8bios-setup%e4%b8%8a%e5%a2%9e%e5%8a%a0%e9%a1%b9/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

UEFI开发探索60-VFR文件和其他资源文件1(在BIOS setup上增加项)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

如何使用VFR文件,是我这一段时间比较感兴趣的课题。包括VFR文件在内,UNI文件、IDF文件,都属于资源文件。UNI文件的使用,在之前Hii的例子中,已经讨论过了。而如何使用VFR文件,一直没有涉及到。

接下来的几篇博客,将以修改BIOS Setup(当然,还是以OvmfPkg编译的镜像来做BIOS文件)为例,演示如何使用VFR文件和相关的资源文件。

图1 OVMF镜像的BIOS界面

本篇的例子以Intel提供的示例驱动MyWizardDriver为基础,添加了字符串和窗体,修改步骤如下。

1 修改MyWizardDriverNVDataStruc.h

增加GUID的声明(MYWIZARDDRIVER_FORMSET_GUID):

#define MYWIZARDDRIVER_FORMSET_GUID { 0x5411db09, 0xe5f7, 0x4158, {0xa5, 0xc5, 0x2d, 0xbe, 0xa4,0x95, 0x34, 0xff} }

在示例的修改中,都以“robin add”的方式标记了修改部分,如果是多行修改,则添加了“begin”和“end”的注释。

2 修改MyWizardDriver.vfr

将VFR文件中其他的内容全部删除,并添加自定义的窗体定义,内容如下:

#include “MyWizardDriverNVDataStruc.h”
formset
  guid = MYWIZARDDRIVER_FORMSET_GUID,
  ……
endform;
endformset;

VFR文件中的定义,在程序演示之后,再描述其语法及如何与显示的对应关系。

3 修改MyWizardDriver.uni

添加自定义的字符串,在之前的博客中描述过UNI文件和字符串定义,这里就不详细解释了。

#string STR_SAMPLE_FORM_SET_TITLE #language en “My Wizard DriverSample Formset”
#string STR_SAMPLE_FORM_SET_HELP #language en “Help for SampleFormset”
……

4 修改MyWizardDriver.h

添加头文件:

#include <Protocol/HiiConfigRouting.h>
#include <Protocol/FormBrowser2.h>
#include <Protocol/HiiString.h>
#include <Library/DevicePathLib.h>

并增加自定义的数据结构,代码添加后如下图:

图2 MyWizardDriver.h 代码添加

5 修改MyWizardDriver.c

添加全局变量定义:

图3 源文件全局变量添加

修改函数MyWizardDriverDriverEntryPoint()。修改的内容较多,注意查看源代码。最主要的代码,是通过SetVariable()把窗体添加到了BIOS Setup中。

代码准备完毕,需要将其编译,同时必须编译OVMF镜像。代码仍旧放在RobinPkg中,编译命令如下:

build -p RobinPkg\RobinPkg.dsc -m RobinPkg\Drivers\MyWizardDriver\MyWizardDriver.inf -a X64

以及编译OVMF镜像:

build -p OvmfPkg\OvmfPkgX64.dsc -a X64

奇怪的是,我编译出来的几个OVMF镜像都有点问题,测试的时候不正常,用以前编译的某个OVMF镜像可以正常测试。现在搞不清楚到底是什么原因导致的,在文末所提供的链接中,我把测试环境全部给出了,包括OVMF镜像和批处理。

把编译好的MyWizardDriver.efi拷贝到指定的文件夹hd-contents中,启动Qemu模拟环境:

qemu-system-x86_64.exe   -bios OVMF.fd -hda fat:rw:hda-contents -net none

进入UEFI Shell,执行如下命令:

Shell> FS0:
FS0:\> load MyWizardDriver.efi
FS0:\> exit

进入到BIOS Setup中,依次选择Device Manager-My Wizard DriverSample Formset,可以看到如图4所示的界面,表示添加窗体成功:

图4 窗体添加示意图

可以使用空格或者回车键,修改选项。修改选项的时候,右下角会出现“Configuration changed”的黄色字符串。

More: VFR文件语法

窗体(Forms)是用户交互的组织形式,最终是以IFR(Internal Forms Representation)的二进制形式进入到EDK2的框架中的。IFR是由VFR文件生成的,类似于obj文件相对于源文件的关系。从平台框架的角度,窗体处于交互的中心位置:

图5 平台架构的人机交互结构图

站在程序员的角度,所有资源文件,最终都是用户UI的一部分,其结构图如下:

图6 资源文件

VFR文件采用的是BNF语法,与DSC文件采用“#”作为注释标志不同,它使用“//”作为注释标志。另外还有两个关键字是“#define”和“#include”,用来定义和包含头文件的,类似于C的语法。

formset是VFR文件中最重要的部分,用来组成窗体的最常用的结构。其示例如下:

formset
guid     = {0xcc5ebb4f, 0xf562, 0x11e7, {0x92, 0x11, 0xf4, 0x8c, 0x50, 0x49, 0xe3, 0xa4}},
title    = STRING_TOKEN(STR_SAMPLE_FORM_SET_TITLE),
help     = STRING_TOKEN(STR_SAMPLE_FORM_SET_HELP),
  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID
form formid = 1, title = STRING_TOKEN(STR_SAMPLE_FORM1_TITLE);
  …
endform;
endformset;

formset是关键字,用来标志整个窗体的开始,与标志窗体结束的endformset成对出现。其中各关键字的含义为:

guid: 标志本formset的GUID值;
title:在界面中标志本formset的字符串标题;
help:在界面上显示本formset的帮助信息;
classguid: 本formaset所挂载页面的GUID值。

本formset的选择项,在最初始页面的Device Manager下,如图7所示。

图7 VFR文件中定义的formset

在formaset的集合中,可以用“form”和“endform”定义一个完整的页面,比如这篇博客中给出的示例(RobinPkg\Drivers\MyWizardDriver\MyWizardDriver.vfr):

form formid = 1, title = STRING_TOKEN(STR_SAMPLE_FORM1_TITLE); // “My Wizard Driver”
  subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT); //”My Wizard DriverConfiguration”
  subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2); //”Device XYZ Configuration”
  checkbox varid =MWD_IfrNVData.MyWizardDriverChooseToEnable,
      prompt =STRING_TOKEN(STR_CHECK_BOX_PROMPT),  //”Enable My XYZ Device”
      help = STRING_TOKEN(STR_CHECK_BOX_HELP), //”This is the help message …
      flags = CHECKBOX_DEFAULT ,
      key = 0,
      default = 1,
    endcheckbox;
  endform;

在界面上是这样的:

图8 VFR文件中定义的form

VFR文件的内容比较多,特别是其使用方法,需要仔细研究UEFI spec中Hii部分,才能大致掌握。我在日常的开发中,基本不会用到VFR文件,这些相对比较新的知识,很能让我沉迷其中。

后续还会不定期研究VFR文件、UNI文件和IDF文件的用法,特别是我最关心的本地化显示部分。

另外,由于原来提供代码的百度云,所取的名字比较不雅观(女儿当时乱按的,我没注意……),我会逐渐将代码转移到gitee上去。

本篇的代码:
Gitee地址:
https://gitee.com/luobing4365/uefi-exolorer
项目代码位于:/RobinPkg/Drivers/ MyWizardDriver
其他工具和测试环境:/60 VFR file and other Res

1,161 total views, 2 views today

210c9a4d410d265665667a36fbe0f529?s=49&d=identicon&r=g作者 罗冰(Robin)发布于 2020年6月27日2020年6月27日分类 BIOS/UEFI


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK