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实战】UEFI用户交互界面使用说明之UNI文件中已经介绍过,那些字符串是来自UNI文件的(其实并不是全部来自UNI,也有部分是直接通过代码生成的),而整个窗体的框架部分则是来自VFR文件的。

在UEFI中,构成这样的窗体的组件大致有四种,分别是StringsFormsFontsImages,如下图所示:

Strings就是前面讲到的UNI文件提供的,Forms就是本文的VFR文件提供的,后面两者暂时还未介绍,本文主要介绍的就是这个Forms,以及构成Forms的VFR文件。

关于Forms的定义,在《UEFI Spec》中有如下的说明:

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语言。

下面是一个例子:

#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表达方式定义的):

下面是一个例子:

guid就是通过#define定义的一个普通的GUID;

title中STRING_TOKE()括号中的就是在UNI文件中定义的字符串;

help同title;

classguid,class和subclass是可选的,作用不明。下面是class和subclass的一个例子:

classguid的定义如下:

guidDefinition就是普通的GUID。

class的定义如下:

subclass的定义如下:

3.4.2 formset list

formset内部定义了很多的子选项,称为formset list,也就是上一节formset定义中的vfrFormSetList。

前面的例子中用到的form就是其中的一种。

formset list可以有如下的内容:

上述的内容可以分为几种不同的类型:

  • 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

下面是一个例子:

attribute的值如下:

//
// Default Identifier of default store
//
#define EFI_HII_DEFAULT_CLASS_STANDARD       0x0000
#define EFI_HII_DEFAULT_CLASS_MANUFACTURING  0x0001
#define EFI_HII_DEFAULT_CLASS_SAFE           0x0002
#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000
#define EFI_HII_DEFAULT_CLASS_PLATFORM_END   0x7fff
#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000
#define EFI_HII_DEFAULT_CLASS_HARDWARE_END   0xbfff
#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000
#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END   0xffff

varstore

第一个StringIdentifier表示的是类型,第二个表示的是变量名,name和guid连起来就可以表示该特定的变量。

下面是一个例子:

它定义的是一个数据结构体变量,类型就是DRIVER_SAMPLE_CONFIGURATION。

MyIfrNVData是变量的名称,后面的VFR表达式中会通过该名称去引用该变量。

efivarstore

下面是一个例子:

这里定义的就是UEFI变量,还可以声明变量的属性。

namevaluevarstore

下面是一个例子:

3.5.2 控制语句

VFR文件中可以包含如下的控制语句:

DisableIf语句,定义如下:

SuppressIf语句,定义如下:

GrayOutIf语句,定义如下:

下面是一个例子:

需要注意几点:

1. if条件之后有一个分号;

2. 最后有一个endif与之对应;

另外还有一个goto语句,其定义如下:

下面是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;

对应的界面如下:

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

3.5.3 Question语句

在goto语句中,有一个vfrStatementQuestionOptionList需要介绍下。

它的定义如下:

其中的vfrStatementQuestionTag和vfrStatementQuestionOptionTag又是比较大的两块内容:

顺便还提一个:

上述的各个子元素的定义如下:

vfrStatementSuppressIfQuest

vfrStatementValue

vfrStatementDefault

vfrStatementOptions

vfrStatementRead

vfrStatementWrite

vfrStatementInconsistentIf

vfrStatementNoSubmitIf

vfrStatementDisableIfQuest

vfrStatementRefresh

vfrStatementVarstoreDevice

vfrStatementExtension

无。

vfrStatementRefreshEvent

vfrStatementWarningIf

3.5.4 form语句

VFR文件中包含下述的form语句:

form语句定义:

下面是一个例子:

formmap语句定义:

下面是一个例子:

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

3.6 Forms表达式

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

3.6.1 vfrStatementImage

Image的定义如下:

目前不确定如何使用。

3.6.2 vfrStatementLocked

Locked的定义如下:

目前也不确定如何使用。

3.6.3 vfrStatementRules

Rules的定义如下:

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

3.6.4 vfrStatementDefault

无。

3.6.5 vfrStatementStat

Stat有多种的形式,如下所示:

vfrStatementSubTitle

SubTitle的定义如下:

下面是一个例子:

  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;

对应的界面如下:

红框部分就是一个SubTitle。

vfrStatementStaticText

Text的定义如下:

这里的text是独立的部分,而不是SubTitle的子元素。

下面是一个例子:

    text
      help    = STRING_TOKEN(STR_CONTINUE_HELP),
      text    = STRING_TOKEN(STR_CONTINUE_PROMPT),
      flags   = INTERACTIVE,
      key     = FRONT_PAGE_KEY_CONTINUE;

对应的界面如下:

vfrStatementCrossReference

Cross Reference的定义如下:

作用不明。

3.5.6 vfrStatementQuestions

Question有多种类型,如下所示:

下面说明每一种类型。

vfrStatementBooleanType

BooleanType有两种类型:

CheckBox的定义如下:

Action的定义如下:

vfrStatementNumericType

Numeric有两种类型:

Numeric的定义如下:

OneOf的定义如下:

vfrStatementStringType

String包含两个小类型:

其中String的定义如下:

Password的定义如下:

vfrStatementOrderedList

OrderedList的定义如下:

vfrStatementDate

Date的定义如下:

vfrStatementTime

Time的定义如下:

3.5.7 vfrStatementConditional

Conditional语句其实在之前已经介绍过:

这里不再介绍。

3.5.8 vfrStatementLabel

Label是一个占位符,真正显示的内容是代码动态产生的。

下面是定义:

下面是一个例子:

label之后接的是一个数值。

label对应到代码中的结构体如下:

///
/// Label opcode.
///
typedef struct _EFI_IFR_GUID_LABEL {
  EFI_IFR_OP_HEADER   Header;
  ///
  /// EFI_IFR_TIANO_GUID.
  ///
  EFI_GUID            Guid;
  ///
  /// EFI_IFR_EXTEND_OP_LABEL.
  ///
  UINT8               ExtendOpCode;
  ///
  /// Label Number.
  ///
  UINT16              Number;
} EFI_IFR_GUID_LABEL;

3.5.9 vfrStatementBanner

Banner的形式如下图红框部分所示:

它是一个可显示的字符串,比普通的字符串要显眼一点。

它的定义如下:

title是具体显示的内容;

line表示具体在哪一行显示;

align表示字符显示在行的哪个位置,又左中右三种情况;

timeout不能跟line和align合用,作用不明。

banner对应到代码中的结构体如下:

///
/// Banner opcode.
///
typedef struct _EFI_IFR_GUID_BANNER {
  EFI_IFR_OP_HEADER   Header;
  ///
  /// EFI_IFR_TIANO_GUID.
  ///
  EFI_GUID            Guid;
  ///
  /// EFI_IFR_EXTEND_OP_BANNER
  ///
  UINT8               ExtendOpCode;
  EFI_STRING_ID       Title;        ///< The string token for the banner title.
  UINT16              LineNumber;   ///< 1-based line number.
  UINT8               Alignment;    ///< left, center, or right-aligned.
} EFI_IFR_GUID_BANNER;

3.5.10 vfrStatementExtension

Extension的定义如下:

3.5.11 vfrStatementModal

Model的定义如下:

它只能用在form内部。

具体意义不明。

3.6 VFR表达式

VFR表达式跟C语言差别不大。

下面简单说明。

3.6.1 常量

常量:

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文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • UEFI开发基础汇编代码的使用

    UEFI中使用汇编代码 EDK代码中包含一部分汇编代码,目前支持的有.S..asm和.nasm格式的汇编(第一个是AT&T汇编,后两个是Intel汇编,只是使用的汇编样式稍有不同,.nasm是开源和免费的,更加的通用),如果是在Windows下编译,一般使用的是NASM编译器,所以会使用.nasm格式的汇编文件,而编译工具也是免费的,可以在https://www.nasm.us/下载,并放到C:\Nasm目录,之后就可以在EDK代码中使用. 下面是一个示例,它是一个库模块: 首先创建inf文件:

  • UEFI开发基础HII代码示例

    目录 代码示例 模块 formset form subtitle oneof string numeric text checkbox goto label 代码示例 代码 https://gitee.com/jiangwei0512/edk2-beni 模块 BeniPkg\DynamicCommand\SetupDynamicCommand\SetupDynamicCommand.inf. 这里通过一个命令setup来打开图形界面.图形界面的form在Page.vfr中,还有若干的uni文件

  • 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

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

    综述 UEFI用户交互界面的实现涉及到多种不同类型的文件,这里要讲的是UNI文件,它也是其中最简单的一种.本文主要参考自<edk-ii-uni-specification.pdf>(以下简称参考文档).它可以在EDK II Specifications · tianocore/tianocore.github.io Wiki · GitHub下载到.文本的代码示例来自EDK2017,由于版本更新等原因,示例中的代码可能跟实际GIT库中的代码有一定的差异. 作用 关于UNI文件的作用,在参考文档

  • UEFI开发实战用户交互界面基础说明

    目录 前言 启动 UiApp模块 字体 字符串 UI Entry 前言 本文以vUDK2017: https://github.com/tianocore/edk2.git Tag vUDK2017.中的代码为例说明UEFI用户交互界面的实现. 这里UEFI用户交互界面的实现载体是OVMF(使用QEMU启动),其形式如下: 它一般被叫做Front Page(后面将以该名称来称呼上述的界面),其下还包括Setup,Boot Manager,Device Manager等选项. 相比Legacy B

  • UEFI开发实战SlimBootloader中调用FSP

    目录 综述 编译 PostBuild Build PostBuild FSP二进制组成分析 使用 Stage1B Stage2 综述 FSP的全称是Firmware Support Package.FSP有以下的特性: FSP提供了Intel重要组件(包括处理器.内存控制器.芯片组等)的初始化: FSP被编译成独立的二进制,并可以集成到Bootloader中,这里说的Bootloader可以是Slim Bootloader,coreboot,UEFI等等: FSP的优点有免费.方便集成.可减少开

  • 微信公众平台开发实战Java版之微信获取用户基本信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同). 公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称.头像.性别.所在城市.语言和关注时间. 开发者可通过OpenID来获取用户基本信息.请使用https协议. 我们可以看看官方的文档:获取用户的基本信息. 接口调用请求说明 http请求方式: GET https://api.weixin.qq.com/cgi-b

  • JavaScript使用DeviceOne开发实战(二) 生成调试安装包

    在上篇文章给大家介绍了JavaScript使用DeviceOne开发实战(一) 配置和起步,本篇文章继续给大家介绍关于javascript实战相关内容,一起学习吧. 生成调试安装包 首先需要说明的是,这个步骤并不是每次调试App都必须的,大部分情况生成一次调试安装包,安装到手机上之后就可以忽略整个这个步骤.因为调试安装包包含了很多原生组件,都是可以定制勾选的,如果你需要额外增加一些原生组件,则需要勾选更多的组件并要重新生成调试安装包. 点击调试程序的菜单里的"Build Debug Versio

  • JavaScript使用DeviceOne开发实战(四)仿优酷视频应用

    大家没有进行开发之前首先需要考虑系统的差异性,比如说IOS手机有没有回退键,所以在开发时一定要考虑二级解密需要有回退键,否则ios的手机就会陷入到这个页面回不去. 安卓系统有回退键,针对这个情况需要要求用户在3秒钟之内连续按回退键两次才退出系统,以此防止用户误按回退键,具体代码实现如下: [mw_shl_code=javascript,true]page.on("back", function(){ if (canBack) { global.exit(); } else { nf.t

  • JavaScript使用DeviceOne开发实战(一) 配置和起步

    2015 年 9 月 底,DeviceOne Release发布.至此,DeviceOne 基本完成了对多端的支持.基于 DeviceOne 可以: HTML5.Android.iOS.Windows 多端代码一次编写,各处复用: 实时简单部署. 本地化UI 在接下来的时间,我会通过一系列文章来介绍 DeviceOne.本文介绍环境配置以及如何建立一个简单的项目.(注:本篇文章 iOS 和 Android和Windows 开发都适用.) 目前使用 DeviceOne 开发可以在Windows 或

  • C#实现微信跳一跳小游戏的自动跳跃助手开发实战

    一.前言: 前段时间微信更新了新版本后,带来的一款H5小游戏"跳一跳"在各朋友圈里又火了起来,类似以前的"打飞机"游戏,这游戏玩法简单,但加上了积分排名功能后,却成了"装逼"的地方,于是很多人花钱花时间的刷积分抢排名.后来越来越多的聪明的"程序哥们"弄出了不同方式不同花样的跳一跳助手(外挂?),有用JS实现的.有JAVA实现的.有Python实现的,有直接物理模式的.有机械化的.有量尺子的等等,简直是百花齐放啊-- 赶一下潮流

  • Python3网络爬虫开发实战之极验滑动验证码的识别

    上节我们了解了图形验证码的识别,简单的图形验证码我们可以直接利用 Tesserocr 来识别,但是近几年又出现了一些新型验证码,如滑动验证码,比较有代表性的就是极验验证码,它需要拖动拼合滑块才可以完成验证,相对图形验证码来说识别难度上升了几个等级,本节来讲解下极验验证码的识别过程. 1. 本节目标 本节我们的目标是用程序来识别并通过极验验证码的验证,其步骤有分析识别思路.识别缺口位置.生成滑块拖动路径,最后模拟实现滑块拼合通过验证. 2. 准备工作 本次我们使用的 Python 库是 Selen

随机推荐