UEFI开发实战用户交互界面使用说明VFR文件

目录

  • 1. 综述
  • 2. 作用
  • 3. 语法
    • 3.1 注释
    • 3.2 预定义
    • 3.3 数据结构
    • 3.4 Forms相关表达式总览
      • 3.4.1 formset
      • 3.4.2 formset list
    • 3.5 Form Set List
      • 3.5.1 变量定义
      • 3.5.2 控制语句
      • 3.5.3 Question语句
      • 3.5.4 form语句
    • 3.6 Forms表达式
      • 3.6.1 vfrStatementImage
      • 3.6.2 vfrStatementLocked
      • 3.6.3 vfrStatementRules
      • 3.6.4 vfrStatementDefault
      • 3.6.5 vfrStatementStat
      • 3.5.6 vfrStatementQuestions
      • 3.5.8 vfrStatementLabel
      • 3.5.9 vfrStatementBanner
      • 3.5.10 vfrStatementExtension
      • 3.5.11 vfrStatementModal
    • 3.6 VFR表达式
      • 3.6.1 常量
      • 3.6.2 操作符
      • 3.6.3 内置函数

1. 综述 UEFI用户交互界面的实现涉及到多种不同类型的文件,这里要讲的是VFR文件,相比UNI文件它要复杂得多,理解起来也更困难。
本文主要参考自《edk-ii-vfr-specification.pdf》(以下简称参考文档)和《UEFI Spec》。
它们可以在EDK II Specifications · tianocore/tianocore.github.io Wiki · GitHub下载到。
文本的代码示例来自EDK2017,由于版本更新等原因,示例中的代码可能跟实际GIT库中的代码有一定的差异。

2. 作用 在说明VFR文件得作用之前,首先需要祭出一张在之前用过多次的图:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

在【UEFI实战】UEFI用户交互界面使用说明之UNI文件中已经介绍过,那些字符串是来自UNI文件的(其实并不是全部来自UNI,也有部分是直接通过代码生成的),而整个窗体的框架部分则是来自VFR文件的。
在UEFI中,构成这样的窗体的组件大致有四种,分别是Strings,Forms,Fonts和Images,如下图所示:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

Strings就是前面讲到的UNI文件提供的,Forms就是本文的VFR文件提供的,后面两者暂时还未介绍,本文主要介绍的就是这个Forms,以及构成Forms的VFR文件。
关于Forms的定义,在《UEFI Spec》中有如下的说明:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

Forms描述了窗体的组织形式,提供了用户交互的方式和交互内容的存储方式等。
Forms是以二进制的形式提供的,这种二进制在EDK框架中被称为IFR(就是上述定义中提到的Internal Forms Representation)。
而IFR通过编译VFR来生成(关于编译工具,在EDK源代码中也有相应的源码,不过没有研究过不确定怎么用)。
因此,总的来说就是,我们通过编写VFR文件来完成对UEFI交互界面的组织形式和交互方式等相关内容的定义。

3. 语法 参考文档中给出了VFR的详细语法说明,这里简单介绍下。

3.1 注释
VFR文件中可以使用“//”来注释,同C语言和UNI文件。

3.2 预定义
VFR文件中可以使用几种预定义的指令,如#define、#include、#pragma等。
功能同C语言。
下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

UEFI开发实战用户交互界面使用说明VFR文件
文章图片

#pragma一般会在使用#include包含的C语言头文件中。

3.3 数据结构
前文中已经看到,VFR文件支持#include来包含C语言的头文件,因此C语言头文件中可以包含的数据结构VFR文件也都是支持的。
包括UINT8, UINT16, UINT32, UINT64, BOOLEAN等基本数据类型,和HII特定的数据类型,如EFI_STRING_ID, EFI_HII_DATA, EFI_HII_TIME, EFI_HII_REF,还有就是通过typedef自定义的结构体。
一维的数组也是支持的,但是不支持枚举和多维的数组。

3.4 Forms相关表达式总览
以上的内容都是基础内容,且都是属于C语言的范围。
下面的内容是VFR特有的表达式。

3.4.1 formset formset的具体定义没有找到。
但是它属于组成窗口的主体,也是VFR文件中最重要的部分。
它的定义如下(也是使用BNF表达方式定义的):
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

guid就是通过#define定义的一个普通的GUID;
title中STRING_TOKE()括号中的就是在UNI文件中定义的字符串;
help同title;
classguid,class和subclass是可选的,作用不明。下面是class和subclass的一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

classguid的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

guidDefinition就是普通的GUID。
class的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

subclass的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片


3.4.2 formset list formset内部定义了很多的子选项,称为formset list,也就是上一节formset定义中的vfrFormSetList。
前面的例子中用到的form就是其中的一种。
formset list可以有如下的内容:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

上述的内容可以分为几种不同的类型:
  • 1. 变量定义,如defaultstore,varstore,efivarstore,namevaluevarstore等;
  • 2. 控制语句,它会做if判断来确定其包含的formset list是否会被使用,主要有disableif,suppressif,grayoutif和goto语句等(上述的语句只在目前只在form类型语句中见到过,在其外没遇见过,不确定是否可以在它之外);
  • 3. form语句,它们是formset里面的主体部分,有form,formmap等;
  • 4. 其它语句;

3.5 Form Set List
3.4.2节中已经介绍了Form Set List的大致分类,本节将进一步介绍各种类型的Form Set List。

3.5.1 变量定义 下面是各种变量的定义。
defaultstore:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

attribute的值如下:
//// Default Identifier of default store //#define EFI_HII_DEFAULT_CLASS_STANDARD0x0000#define EFI_HII_DEFAULT_CLASS_MANUFACTURING0x0001#define EFI_HII_DEFAULT_CLASS_SAFE0x0002#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000#define EFI_HII_DEFAULT_CLASS_PLATFORM_END0x7fff#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000#define EFI_HII_DEFAULT_CLASS_HARDWARE_END0xbfff#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END0xffff

varstore:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

第一个StringIdentifier表示的是类型,第二个表示的是变量名,name和guid连起来就可以表示该特定的变量。
下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

它定义的是一个数据结构体变量,类型就是DRIVER_SAMPLE_CONFIGURATION。
MyIfrNVData是变量的名称,后面的VFR表达式中会通过该名称去引用该变量。
efivarstore:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

这里定义的就是UEFI变量,还可以声明变量的属性。
namevaluevarstore:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片


3.5.2 控制语句 VFR文件中可以包含如下的控制语句:
DisableIf语句,定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

SuppressIf语句,定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

GrayOutIf语句,定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

需要注意几点:
1. if条件之后有一个分号;
2. 最后有一个endif与之对应;
另外还有一个goto语句,其定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是goto语句的一个例子:
form formid = FORM_BOOT_SETUP_ID,title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); goto FORM_MAIN_ID,prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),help = STRING_TOKEN(STR_FORM_GOTO_MAIN); //flags = INTERACTIVE,//key = FORM_MAIN_ID; goto FORM_BOOT_SETUP_ID,prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),flags = INTERACTIVE,key = FORM_BOOT_ADD_ID; goto FORM_BOOT_DEL_ID,prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP),flags = INTERACTIVE,key = FORM_BOOT_DEL_ID; goto FORM_BOOT_CHG_ID,prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),help = STRING_TOKEN(STR_FORM_BOOT_IMMEDIATE_HELP),flags = INTERACTIVE,key = FORM_BOOT_CHG_ID; endform;

对应的界面如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

红框部分就是4个goto语句。

3.5.3 Question语句 在goto语句中,有一个vfrStatementQuestionOptionList需要介绍下。
它的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

其中的vfrStatementQuestionTag和vfrStatementQuestionOptionTag又是比较大的两块内容:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

UEFI开发实战用户交互界面使用说明VFR文件
文章图片

顺便还提一个:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

上述的各个子元素的定义如下:
vfrStatementSuppressIfQuest:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementValue:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementDefault:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementOptions:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementRead:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementWrite:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementInconsistentIf:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementNoSubmitIf:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementDisableIfQuest:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementRefresh:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementVarstoreDevice:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementExtension:
无。
vfrStatementRefreshEvent:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementWarningIf:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片


3.5.4 form语句 VFR文件中包含下述的form语句:
form语句定义:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

formmap语句定义:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

后续会较详细的介绍forms语句内部的定义。

3.6 Forms表达式
前面提到的formset,form,formmap等,其实都是抽象的概念,并不会实际得显示出来,而本节讲的是具体的概念,且大部分是能够看到和操作的内容。

3.6.1 vfrStatementImage Image的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

目前不确定如何使用。

3.6.2 vfrStatementLocked Locked的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

目前也不确定如何使用。

3.6.3 vfrStatementRules Rules的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

这个Rules会在用户输入的时候做检测(引用StringIdentifier来完成)。

3.6.4 vfrStatementDefault 无。

3.6.5 vfrStatementStat Stat有多种的形式,如下所示:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementSubTitle
SubTitle的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
form formid = DEVICE_MANAGER_FORM_ID,title= STRING_TOKEN(STR_EDKII_MENU_TITLE); subtitle text = STRING_TOKEN(STR_DEVICES_LIST); label LABEL_DEVICES_LIST; label LABEL_END;

【UEFI开发实战用户交互界面使用说明VFR文件】对应的界面如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

红框部分就是一个SubTitle。
vfrStatementStaticText
Text的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

这里的text是独立的部分,而不是SubTitle的子元素。
下面是一个例子:
texthelp= STRING_TOKEN(STR_CONTINUE_HELP),text= STRING_TOKEN(STR_CONTINUE_PROMPT),flags= INTERACTIVE,key= FRONT_PAGE_KEY_CONTINUE;

对应的界面如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementCrossReference
Cross Reference的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

作用不明。

3.5.6 vfrStatementQuestions Question有多种类型,如下所示:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面说明每一种类型。
vfrStatementBooleanType
BooleanType有两种类型:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

CheckBox的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

Action的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementNumericType
Numeric有两种类型:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

Numeric的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

OneOf的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementStringType
String包含两个小类型:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

其中String的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

Password的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementOrderedList
OrderedList的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementDate
Date的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

UEFI开发实战用户交互界面使用说明VFR文件
文章图片

vfrStatementTime
Time的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

UEFI开发实战用户交互界面使用说明VFR文件
文章图片

3.5.7 vfrStatementConditional
Conditional语句其实在之前已经介绍过:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

这里不再介绍。

3.5.8 vfrStatementLabel Label是一个占位符,真正显示的内容是代码动态产生的。
下面是定义:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

下面是一个例子:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

label之后接的是一个数值。
label对应到代码中的结构体如下:
////// Label opcode.///typedef struct _EFI_IFR_GUID_LABEL {EFI_IFR_OP_HEADERHeader; ////// EFI_IFR_TIANO_GUID.///EFI_GUIDGuid; ////// EFI_IFR_EXTEND_OP_LABEL.///UINT8ExtendOpCode; ////// Label Number.///UINT16Number; } EFI_IFR_GUID_LABEL;


3.5.9 vfrStatementBanner Banner的形式如下图红框部分所示:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

它是一个可显示的字符串,比普通的字符串要显眼一点。
它的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

title是具体显示的内容;
line表示具体在哪一行显示;
align表示字符显示在行的哪个位置,又左中右三种情况;
timeout不能跟line和align合用,作用不明。
banner对应到代码中的结构体如下:
////// Banner opcode.///typedef struct _EFI_IFR_GUID_BANNER {EFI_IFR_OP_HEADERHeader; ////// EFI_IFR_TIANO_GUID.///EFI_GUIDGuid; ////// EFI_IFR_EXTEND_OP_BANNER///UINT8ExtendOpCode; EFI_STRING_IDTitle; ///< The string token for the banner title.UINT16LineNumber; ///< 1-based line number.UINT8Alignment; ///< left, center, or right-aligned.} EFI_IFR_GUID_BANNER;


3.5.10 vfrStatementExtension Extension的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片


3.5.11 vfrStatementModal Model的定义如下:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片

它只能用在form内部。
具体意义不明。

3.6 VFR表达式
VFR表达式跟C语言差别不大。
下面简单说明。

3.6.1 常量 常量:
UEFI开发实战用户交互界面使用说明VFR文件
文章图片


3.6.2 操作符 OR:或操作,对应到EFI_IFR_OR;
AND:与操作,对应EFI_IFR_AND;
|:位或操作,对应EFI_IFR_BITWISE_OR;
&:位与操作,对应EFI_IFR_BITWISE_AND;
~:位反,对应EFI_IFR_BITWISENOT;
==:等于操作,对应EFI_IFR_EQUAL;
!=:不等于操作,对应EFI_IFR_NOT_EQUAL;
<,<=,>,>=:比较操作,对应EFI_IFR_LESS_THAN,EFI_IFR_LESS_EQUAL,EFI_IFR_IFR_GREATER_EQUAL和EFI_IFR_GREATER_THAN;
<<,>>:位移操作,对应EFI_IFR_SHIFT_LEFT和EFI_IFR_SHIFT_RIGHT;
+,-:加减操作,对应EFI_IFR_ADD和EFI_IFR_SUBTRACT;
*,/,%:乘余除操作,对应EFI_IFR_MULTIPLY,EFI_IFR_MODULO和EFI_IFR_DIVIDE;
():括号;
(UINTX/BOOLEAN):强制转换操作;

3.6.3 内置函数 dup:复制操作,对应EFI_IFR_DUP;
ideqval x==y:判断x和y的值是否相等,对应EFI_IFR_EQ_ID_VAL;
ideqid x==y:判断x和y的ID是否相等,对应EFI_IFR_EQ_ID_ID;
ideqvallist x==y+:判断x和y+(表示多个值)是否相同,对应EFI_IFR_EQ_ID_LIST;
questionref(x):Question引用,对应EFI_IFR_QUESTION_REF1;
questionrefval(s):作用不明,对应EFI_IFR_QUESTION_REF2或EFI_IFR_QUESTION_REF2;
ruleref(x):Rule引用,对应EFI_IFR_RULE_REF;
stringref(x):字符串引用,对应EFI_IFR_STRING_REF1;
stringrefval(s):作用不明,对应EFI_IFR_STRING_REF2;
pushthis:作用不明,对应EFI_IFR_THIS;
security(x):作用不明,对应EFI_IFR_SECURITY;
get(x):获取变量,对应EFI_IFR_GET;
set(x,y):设置变量,对应EFI_IFR_SET;
boolval(s):转BOOLEAN,对应EFI_IFR_TO_BOOLEAN;
unintval(s):转UINT整型,对应EFI_IFR_TO_UINT;
tolower(s):字符串变小写,对应EFI_IFR_TO_LOWER;
toupper(s):字符串变大写,对应EFI_IFR_TO_UPPER;
catenate(x,y):字符串连接,对应EFI_IFR_CATENATE;
cond(x?y:z):就是If (Expr1) then x = Expr3 else Expr2,对应EFI_IFR_CONDITIONAL;
find(format,s1,s2,x):字符串寻找,对应EFI_IFR_FIND;
mid(a,b,c):作用不明,对应EFI_IFR_MID;
token(a,b,c):作用不明,对应EFI_IFR_TOKEN;
span(flag=x,a,b,c):作用不明,对应EFI_IFR_SPAN;
map(a:(b)*):作用不明,对应EFI_IFR_MAP;
match(a,b):字符串比较,对应EFI_IFR_MATCH;
match2(pattern,string,guid):字符串比较,对应EFI_IFR_MATCH2;
length(x):字符串长度计算;
以上就是VFR文件说明的全部内容。
由于《参考文档》也有不少内容没有解释清楚,加上个人能力有限,所以目前对VFR也只是一个大致的了解。
以上就是UEFI开发实战用户交互界面使用说明VFR文件的详细内容,更多关于UEFI用户交互界面VFR文件的资料请关注脚本之家其它相关文章!

    推荐阅读