【UEFI实战】HII之vfr文件
vfr文件
HII的实现涉及到多种不同类型的文件,vfr文件是其中最重要的一种,它构成了界面的结构样式。本文主要参考自《edk-ii-vfr-specification.pdf》,后面简称为参考文档。
UEFI代码操作UI界面,并不是直接使用vfr文件,而是称为IFR(Internal Forms Representation)的二进制,vfr文件只是IFR的字符串表示,方便通过可识别的字符串作为代码来编写界面,然后通过VFR编译器编译出IFR二进制,最终给UEFI代码使用。
以前面出现过的Front Page为例,图中界面的结构依赖于vfr文件MdeModulePkg\Application\UiApp\FrontPageVfr.Vfr,它构建了Front Page页面的骨架,该文件内容如下:
#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }#define FRONT_PAGE_FORM_ID 0x1000#define LABEL_FRANTPAGE_INFORMATION 0x1000
#define LABEL_END 0xffffformsetguid = FORMSET_GUID,title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),help = STRING_TOKEN(STR_EMPTY_STRING ),classguid = FORMSET_GUID,form formid = FRONT_PAGE_FORM_ID,title = STRING_TOKEN(STR_FRONT_PAGE_TITLE);bannertitle = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),line 1,align left;bannertitle = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),line 2,align left;bannertitle = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),line 2,align right;bannertitle = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),line 3,align left;bannertitle = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),line 3,align right;bannertitle = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE4_LEFT),line 4,align left;bannertitle = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE4_RIGHT),line 4,align right;bannertitle = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE5_LEFT),line 5,align left;bannertitle = STRING_TOKEN(STR_CUSTOMIZE_BANNER_LINE5_RIGHT),line 5,align right;label LABEL_FRANTPAGE_INFORMATION;//// This is where we will dynamically add a Action type op-code to show// the platform information.//label LABEL_END;endform;
它构成的结构基本样式如下:
STR_FRONT_PAGE_COMPUTER_MODEL
STR_FRONT_PAGE_CPU_MODEL STR_FRONT_PAGE_CPU_SPEED
STR_FRONT_PAGE_BIOS_VERSION STR_FRONT_PAGE_MEMORY_SIZE
STR_CUSTOMIZE_BANNER_LINE4_LEFT STR_CUSTOMIZE_BANNER_LINE4_RIGHT
STR_CUSTOMIZE_BANNER_LINE5_LEFT STR_CUSTOMIZE_BANNER_LINE5_RIGHT
LABEL_FRANTPAGE_INFORMATION
LABEL_END
对应到Front Page界面中(第四、五行没有使用):
红色字体部分是vfr文件中定义的标记,而显示的字符串有一部分是在uni文件中定义的,而红框部分是通过代码实现的,所以vfr文件构成了界面的静态框架,而代码又可以通过vfr文件中定义的标记来动态修改。
vfr文件通过特定的VFR编译器编译,最终得到的是中间文件。该中间文件是一个c文件(FrontPageVfr.c)或者hpk文件,里面就是一个变量用来表示VFR资源:
unsigned char FrontPageVfrBin[] = {// ARRAY LENGTH,0x143加上下述的头部长度,就是0x1470x47, 0x01, 0x00, 0x00, // PACKAGE HEADER,对应的是EFI_HII_FORM_PACKAGE_HDR,0x13F加上下述的头部长度,就是0x143,占据3个字节;第4个字节0x02表示HII类型Form0x43, 0x01, 0x00, 0x02, // PACKAGE DATA,319个字节,十六进制就是0x13F,注释已经加上// 第1个操作码,对应结构体EFI_IFR_FORM_SET0x0E, // EFI_IFR_FORM_SET_OP,它的值就是0xE0xA7, // 前面7位表示长度,即0x27=39个字节,总长度到第二个FORMSET_GUID为止刚好39个字节;第8位表示的是scope,该位为1则表示开始一个新的scope// Guid: FORMSET_GUID0xBC, 0x30, 0x0C, 0x9E, 0x06, 0x3F, 0xA6, 0x4B, 0x82, 0x88, 0x09, 0x17, 0x9B, 0x85, 0x5D, 0xBE, 0x02, 0x00, // FormSetTitle:字符串Token,在AutoGen中定义,对应的是STR_FRONT_PAGE_TITLE,值就是0x00020x0C, 0x00, // Help:字符串Token,在AutoGen中定义,对应的是STR_EMPTY_STRING,值就是0x000C0x01, // Flags:// ClassGuid: FORMSET_GUID0xBC, 0x30, 0x0C, 0x9E, 0x06, 0x3F, 0xA6, 0x4B, 0x82, 0x88, 0x09, 0x17, 0x9B, 0x85, 0x5D, 0xBE,// 第2个操作码,对应结构体EFI_IFR_DEFAULTSTORE0x5C, // 操作码EFI_IFR_DEFAULTSTORE_OP0x06, // 长度6个字节0x00, 0x00, // DefaultName:字符串Token,似乎并不存在0x00, 0x00, // DefaultId:表示EFI_HII_DEFAULT_CLASS_STANDARD// 第3个操作码,对应结构体EFI_IFR_DEFAULTSTORE0x5C, // 操作码EFI_IFR_DEFAULTSTORE_OP0x06, // 长度6个字节0x00, 0x00, // DefaultName:字符串Token,似乎并不存在0x01, 0x00, // DefaultId:表示EFI_HII_DEFAULT_CLASS_MANUFACTURING// 前面两个操作码并没有在vfr文件中声明,但是却创建了。// 第4个操作码,对应结构体EFI_IFR_FORM0x01, // 操作码示EFI_IFR_FORM_OP0x86, // 长度6个字节,新建scope0x00, 0x10, // FormId:对应FRONT_PAGE_FORM_ID0x02, 0x00, // FormTitle:对应字符串Token,STR_FRONT_PAGE_TITLE// 第5个操作码,对应结构体EFI_IFR_GUID_BANNER0x5F, // 操作码示EFI_IFR_GUID_OP0x18, // 长度24个字节,其中16个是GUID// EFI_IFR_TIANO_GUID,表示GUIDed opcodes defined for EDKII implementation,定义在MdeModulePkg\Include\Guid\MdeModuleHii.h0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, // ExtendOpCode,0x01表示EFI_IFR_EXTEND_OP_BANNER0x03, 0x00, // Title,对应字符串Token,0x0003对应的是STR_FRONT_PAGE_COMPUTER_MODEL0x01, 0x00, // LineNumber0x00, // Alignment0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x04, 0x00, 0x02, 0x00, 0x00, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x05, 0x00, 0x02, 0x00, 0x02, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x07, 0x00, 0x03, 0x00, 0x00, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x06, 0x00, 0x03, 0x00, 0x02, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x0E, 0x00, 0x04, 0x00, 0x00, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x0F, 0x00, 0x04, 0x00, 0x02, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x10, 0x00, 0x05, 0x00, 0x00, 0x5F, 0x18, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x01, 0x11, 0x00, 0x05, 0x00, 0x02, // 第14个操作码,对应结构体EFI_IFR_GUID_LABEL0x5F, // 操作码示EFI_IFR_GUID_OP0x15, // 长度21个字节,其中16个是GUID// EFI_IFR_TIANO_GUID,表示GUIDed opcodes defined for EDKII implementation,定义在MdeModulePkg\Include\Guid\MdeModuleHii.h0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x00, // ExtendOpCode,0x00表示EFI_IFR_EXTEND_OP_LABEL0x00, 0x10, // Label Number.0x5F, 0x15, 0x35, 0x17, 0x0B, 0x0F, 0xA0, 0x87, 0x93, 0x41, 0xB2, 0x66, 0x53, 0x8C, 0x38, 0xAF, 0x48, 0xCE, 0x00, 0xFF, 0xFF, 0x29, 0x02, 0x29, 0x02
};
这些数据就是IFR二进制,它们通过HiiAddPackages()
安装:
//// Publish our HII data//gFrontPagePrivate.HiiHandle = HiiAddPackages (&mFrontPageGuid,gFrontPagePrivate.DriverHandle,FrontPageVfrBin,UiAppStrings,NULL);
这样就可以通过gFrontPagePrivate.HiiHandle
来访问安装的资源了。
跟uni文件一样,vfr文件也有两种使用方式,一种是定义中间文件的变量,另一种是直接定义二进制。以上的代码使用的是中间文件的方式,除去前面的4个字节,剩余的部分对应到一个结构体:
///
/// The header found at the start of each package.
///
typedef struct {UINT32 Length:24;UINT32 Type:8;// UINT8 Data[...];
} EFI_HII_PACKAGE_HEADER;
///
/// The Form package is used to carry form-based encoding data.
///
typedef struct _EFI_HII_FORM_PACKAGE_HDR {EFI_HII_PACKAGE_HEADER Header;// EFI_IFR_OP_HEADER OpCodeHeader;// More op-codes follow
} EFI_HII_FORM_PACKAGE_HDR;
EFI_HII_PACKAGE_HEADER
的Type
有如下的类型,它表示的是所有HII的类型,比如结构、字体、字符串等:
//
// Value of HII package type
//
#define EFI_HII_PACKAGE_TYPE_ALL 0x00
#define EFI_HII_PACKAGE_TYPE_GUID 0x01
#define EFI_HII_PACKAGE_FORMS 0x02
#define EFI_HII_PACKAGE_STRINGS 0x04
#define EFI_HII_PACKAGE_FONTS 0x05
#define EFI_HII_PACKAGE_IMAGES 0x06
#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07
#define EFI_HII_PACKAGE_DEVICE_PATH 0x08
#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09
#define EFI_HII_PACKAGE_ANIMATIONS 0x0A
#define EFI_HII_PACKAGE_END 0xDF
#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0
#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF
对于vfr文件描述的结构来说,其类型当然是EFI_HII_PACKAGE_FORMS
,值是2。
头部之后的内容就是一个个的操作码,其结构体如下:
typedef struct _EFI_IFR_OP_HEADER {UINT8 OpCode;UINT8 Length:7;UINT8 Scope:1;
} EFI_IFR_OP_HEADER;
该结构体也是不定长的,之后跟有数据,根据不同的操作码,数据也不一样,如下图所示:
操作码已经在IFR操作码列出;长度包含整个不定长结构体,即也包含头部的长度;Scope
如果是1就表示开启了一个新的Scope,直到遇到EFI_IFR_END_OP
为止。
语言基础
vfr
文件也使用EBNF来描述,这里就不再多介绍,只是简单说明基本语言基础。
- 通过
//
来注释; - 支持预定义指令:
#define
:跟c语言中的使用差不多,就是定义宏;#include
:可以包含c语言头文件;#pragma
:c语言头文件中会使用到,比如对于头文件中的结构体,可以设置其对齐方式。
- 支持基本数据类型和HII特定的数据类型,也支持结构体:
UINT8
、UINT16
、UINT32
、UINT64
、BOOLEAN
等;EFI_STRING_ID
、EFI_HII_DATA
、EFI_HII_TIME
、EFI_HII_REF
等。
VFR组件
本文介绍常用的组件,比如按钮、选择框、标签等等,这些将结合IFR操作码说明,本节说明VFR的最基础组件。
formset
每个vfr文件中都有且只有一个formset
,它构成了界面的主体,其它的界面组件都在它内部,其结构如下:
formsetguid = TCG_CONFIG_FORM_SET_GUID, // GUIDtitle = STRING_TOKEN(STR_TPM_TITLE), // uni文件中定义的标记help = STRING_TOKEN(STR_TPM_HELP), // uni文件中定义的标记classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, // GUID,可选class = EFI_NETWORK_DEVICE_CLASS, // 数值,可选subclass = 0x03, // 数值,可选// 剩余组件写在这里endformset;
剩余组件可以是图片、变量、DisableIf、SuppressIf、扩展等,用BNF表示就是:
vfrFormSetList ::=
(vfrFormDefinition| vfrFormMapDefinition| vfrStatementImage| vfrStatementVarStoreLinear| vfrStatementVarStoreEfi| vfrStatementVarStoreNameValue| vfrStatementDefaultStore| vfrStatementDisableIfFormSet| vfrStatementSuppressIfFormSet| vfrStatementExtension
)*
formset
和endformset
配对使用。
具体的层级关系如下(目前的源代码中能够找到的vfr组件):
注意这里只包含了当前EDK代码中存在的组件,还有很多没有列举。
form
formset
内可以有若干个form
,下面是一个例子:
form formid = FORM_MAIN_ID,title = STRING_TOKEN(STR_FORM_MAIN_TITLE);endform;
formid
在一个formset
中必须是唯一的;title
来自uni文件中的标记。
变量
VFR使用的变量有3种,分别是varstore
、efivarstore
和namevaluevarstore
,下面是示例:
//// Define a Buffer Storage (EFI_IFR_VARSTORE)//varstore DRIVER_SAMPLE_CONFIGURATION, // 数据结构,在头文件中定义varid = CONFIGURATION_VARSTORE_ID, // 变量ID,可选,在创建操作码的函数中会用到,比如HiiCreateOneOfOpCode()name = MyIfrNVData, // 变量名,CHAR16 VariableName[] = L"MyIfrNVData";guid = DRIVER_SAMPLE_FORMSET_GUID; // 变量GUID,跟变量名共同确定了UEFI变量//// Define a EFI variable Storage (EFI_IFR_VARSTORE_EFI)//efivarstore MY_EFI_VARSTORE_DATA, // 数据结构,在头文件中定义attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, // UEFI变量属性name = MyEfiVar, // 变量名,CHAR16 MyEfiVar[] = L"MyEfiVar";guid = DRIVER_SAMPLE_FORMSET_GUID; // 变量GUID,跟变量名共同确定了UEFI变量//// Define a Name/Value Storage (EFI_IFR_VARSTORE_NAME_VALUE)//namevaluevarstore MyNameValueVar, // Define storage reference name in vfrname = STRING_TOKEN(STR_NAME_VALUE_VAR_NAME0), // Define Name list of this storage, refer it by MyNameValueVar[0]name = STRING_TOKEN(STR_NAME_VALUE_VAR_NAME1), // Define Name list of this storage, refer it by MyNameValueVar[1]name = STRING_TOKEN(STR_NAME_VALUE_VAR_NAME2), // Define Name list of this storage, refer it by MyNameValueVar[2]guid = DRIVER_SAMPLE_FORMSET_GUID; // GUID of this Name/Value storage
上述的变量可以设置默认值,且默认值也可以不同,这通过defaultstore
来实现:
defaultstore MyStandardDefault,prompt = STRING_TOKEN(STR_STANDARD_DEFAULT_PROMPT),attribute = 0x0000; // Default ID: 0000 standard defaultdefaultstore MyManufactureDefault,prompt = STRING_TOKEN(STR_MANUFACTURE_DEFAULT_PROMPT),attribute = 0x0001; // Default ID: 0001 manufacture default
使用示例,可以在上述3中变量中使用:
numeric varid = MyIfrNVData.HowOldAreYouInYears, // varstoreprompt = STRING_TOKEN(STR_NUMERIC_STEP_PROMPT),help = STRING_TOKEN(STR_NUMERIC_HELP2),minimum = 0,maximum = 243,step = 1,default = 18, defaultstore = MyStandardDefault, // This is standard default valuedefault = 19, defaultstore = MyManufactureDefault, // This is manufacture default valueendnumeric; numeric varid = MyEfiVar.Field8, // Reference of EFI variable storagequestionid = 0x1111,prompt = STRING_TOKEN(STR_TALL_HEX_PROMPT),help = STRING_TOKEN(STR_NUMERIC_HELP1),flags = DISPLAY_UINT_HEX | INTERACTIVE, // Display in HEX format (if not specified, default is in decimal format)minimum = 0,maximum = 250,default = 18, defaultstore = MyStandardDefault, // This is standard default valuedefault = 19, defaultstore = MyManufactureDefault, // This is manufacture default valueendnumeric;//// Define numeric using Name/Value Storage//numeric varid = MyNameValueVar[0], // This numeric take NameValueVar0 as storageprompt = STRING_TOKEN(STR_NAME_VALUE_VAR_NAME0),help = STRING_TOKEN(STR_NAME_VALUE_VAR_NAME0_HELP),//// Size should be defined for numeric when use Name/Value storage// Valid value for numerice size are: NUMERIC_SIZE_1, NUMERIC_SIZE_2, NUMERIC_SIZE_4 and NUMERIC_SIZE_8//flags = NUMERIC_SIZE_1, // Size of this numeric is 1 byteminimum = 0,maximum = 0xff,step = 0,locked,default = 16, defaultstore = MyStandardDefault, // This is standard default valuedefault = 17, defaultstore = MyManufactureDefault, // This is manufacture default valueendnumeric;
控制
有如下的3种控制显示的语句:
disableif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2;orderedlistvarid = MyIfrNVData.OrderedList,prompt = STRING_TOKEN(STR_TEST_OPCODE),help = STRING_TOKEN(STR_TEXT_HELP),flags = RESET_REQUIRED,option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 3, flags = 0;option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 2, flags = 0;option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 1, flags = 0;default = {1,2,3},endlist;endif;grayoutif NOT ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;suppressif questionref(MyOneOf) == 0x0;checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),help = STRING_TOKEN(STR_CHECK_BOX_HELP),//// CHECKBOX_DEFAULT indicate this checkbox is marked with EFI_IFR_CHECKBOX_DEFAULT// CHECKBOX_DEFAULT_MFG indicate EFI_IFR_CHECKBOX_DEFAULT_MFG.//flags = CHECKBOX_DEFAULT | CHECKBOX_DEFAULT_MFG,default = TRUE,endcheckbox;endif;endif;
disableif
表示不用,suppressif
表示不显示,grayoutif
表示显示但是不能操作(不能选中)。
还有控制跳转的语句:
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;
FORM_BOOT_DEL_ID
对应到一个form
的formid
:
form formid = FORM_BOOT_DEL_ID,title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);label FORM_BOOT_DEL_ID;label LABEL_END;endform;
表达式
VFR中可以包含表达式,比如OR
、AND
、NOT
等等,作用跟c语言中类似。
IFR操作码
操作码 | 值 | 描述 |
---|---|---|
EFI_IFR_FORM_OP | 0x01 | Form |
EFI_IFR_SUBTITLE_OP | 0x02 | Subtitle statement |
EFI_IFR_TEXT_OP | 0x03 | Static text/image statement |
EFI_IFR_IMAGE_OP | 0x04 | Static image |
EFI_IFR_ONE_OF_OP | 0x05 | One-of question |
EFI_IFR_CHECKBOX_OP | 0x06 | Boolean question |
EFI_IFR_NUMERIC_OP | 0x07 | Numeric question |
EFI_IFR_PASSWORD_OP | 0x08 | Password string question |
EFI_IFR_ONE_OF_OPTION_OP | 0x09 | Option |
EFI_IFR_SUPPRESS_IF_OP | 0x0A | Suppress if conditional |
EFI_IFR_LOCKED_OP | 0x0B | Marks statement/question as locked |
EFI_IFR_ACTION_OP | 0x0C | Button question |
EFI_IFR_RESET_BUTTON_OP | 0x0D | Reset button statement |
EFI_IFR_FORM_SET_OP | 0x0E | Form set |
EFI_IFR_REF_OP | 0x0F | Cross-reference statement |
EFI_IFR_NO_SUBMIT_IF_OP | 0x10 | Error checking conditional |
EFI_IFR_INCONSISTENT_IF_OP | 0x11 | Error checking conditional |
EFI_IFR_EQ_ID_VAL_OP | 0x12 | Return true if question value equals UINT16 |
EFI_IFR_EQ_ID_ID_OP | 0x13 | Return true if question value equals another question value |
EFI_IFR_EQ_ID_VAL_LIST_OP | 0x14 | Return true if question value is found in list of UINT16s |
EFI_IFR_AND_OP | 0x15 | Push true if both sub-expressions returns true |
EFI_IFR_OR_OP | 0x16 | Push true if either sub-expressions returns true |
EFI_IFR_NOT_OP | 0x17 | Push false if sub-expression returns true, otherwise return true |
EFI_IFR_RULE_OP | 0x18 | Create rule in current form |
EFI_IFR_GRAY_OUT_IF_OP | 0x19 | Nested statements, questions or options will not be selectable if expression returns true |
EFI_IFR_DATE_OP | 0x1A | Date question |
EFI_IFR_TIME_OP | 0x1B | Time question |
EFI_IFR_STRING_OP | 0x1C | String question |
EFI_IFR_REFRESH_OP | 0x1D | Interval for refreshing a question |
EFI_IFR_DISABLE_IF_OP | 0x1E | Nested statements, questions or options will not be processed if expression returns true |
EFI_IFR_ANIMATION_OP | 0x1F | Animation associated with question statement, form or form set |
EFI_IFR_TO_LOWER_OP | 0x20 | Convert a string on the expression stack to lower case |
EFI_IFR_TO_UPPER_OP | 0x21 | Convert a string on the expression stack to upper case |
EFI_IFR_MAP_OP | 0x22 | Convert one value to another by selecting a match from a list |
EFI_IFR_ORDERED_LIST_OP | 0x23 | Set question |
EFI_IFR_VARSTORE_OP | 0x24 | Define a buffer-style variable storage |
EFI_IFR_VARSTORE_NAME_VALUE_OP | 0x25 | Define a name/value style variable storage |
EFI_IFR_VARSTORE_EFI_OP | 0x26 | Define a UEFI variable style variable storage |
EFI_IFR_VARSTORE_DEVICE_OP | 0x27 | Specify the device path to use for variable storage |
EFI_IFR_VERSION_OP | 0x28 | Push the revision level of the UEFI Specification to which this Forms Processor is compliant |
EFI_IFR_END_OP | 0x29 | Marks end of scope |
EFI_IFR_MATCH_OP | 0x2A | Push TRUE if string matches a pattern |
EFI_IFR_GET_OP | 0x2B | Return a stored value |
EFI_IFR_SET_OP | 0x2C | Change a stored value |
EFI_IFR_READ_OP | 0x2D | Provides a value for the current question or default |
EFI_IFR_WRITE | 0x2E | Change a value for the current question |
EFI_IFR_EQUAL_OP | 0x2F | Push TRUE if two expressions are equal |
EFI_IFR_NOT_EQUAL_OP | 0x30 | Push TRUE if two expressions are not equal |
EFI_IFR_GREATER_THAN_OP | 0x31 | Push TRUE if one expression is greater than another expression |
EFI_IFR_GREATER_EQUAL_OP | 0x32 | Push TRUE if one expression is greater than or equal to another expression |
EFI_IFR_LESS_THAN_OP | 0x33 | Push TRUE if one expression is less than another expression |
EFI_IFR_LESS_EQUAL_OP | 0x34 | Push TRUE if one expression is less than or equal to another expression |
EFI_IFR_BITWISE_AND_OP | 0x35 | Bitwise-AND two unsigned integers and push the result |
EFI_IFR_BITWISE_OR_OP | 0x36 | Bitwise-OR two unsigned integers and push the result |
EFI_IFR_BITWISE_NOT_OP | 0x37 | Bitwise-NOT an unsigned integer and push the result |
EFI_IFR_SHIFT_LEFT_OP | 0x38 | Shift an unsigned integer left by a number of bits and push the result |
EFI_IFR_SHIFT_RIGHT_OP | 0x39 | Shift an unsigned integer right by a number of bits and push the result |
EFI_IFR_ADD_OP | 0x3A | Add two unsigned integers and push the result |
EFI_IFR_SUBTRACT_OP | 0x3B | Subtract two unsigned integers and push the result |
EFI_IFR_MULTIPLY_OP | 0x3C | Multiply two unsigned integers and push the result |
EFI_IFR_DIVIDE_OP | 0x3D | Divide one unsigned integer by another and push the result |
EFI_IFR_MODULO_OP | 0x3E | Divide one unsigned integer by another and push the remainder |
EFI_IFR_RULE_REF_OP | 0x3F | Evaluate a rule |
EFI_IFR_QUESTION_REF1_OP | 0x40 | Push a question’s value |
EFI_IFR_QUESTION_REF2_OP | 0x41 | Push a question’s value |
EFI_IFR_UINT8_OP EFI_IFR_UINT16_OP EFI_IFR_UINT32_OP EFI_IFR_UINT64_OP |
0x42 0x43 0x44 0x45 |
Push an 8-bit/16-bit/32-bit/64-bit unsigned integer |
EFI_IFR_TRUE_OP | 0x46 | Push a boolean TRUE. |
EFI_IFR_FALSE_OP | 0x47 | Push a boolean FALSE |
EFI_IFR_TO_UINT_OP | 0x48 | Convert expression to an unsigned integer |
EFI_IFR_TO_STRING_OP | 0x49 | Convert expression to a string |
EFI_IFR_TO_BOOLEAN_OP | 0x4A | Convert expression to a boolean |
EFI_IFR_MID_OP | 0x4B | Extract portion of string or buffer |
EFI_IFR_FIND_OP | 0x4C | Find a string in a string |
EFI_IFR_TOKEN_OP | 0x4D | Extract a delimited byte or character string from buffer or string |
EFI_IFR_STRING_REF1_OP | 0x4E | Push a string |
EFI_IFR_STRING_REF2_OP | 0x4F | Push a string |
EFI_IFR_CONDITIONAL_OP | 0x50 | Duplicate one of two expressions depending on result of the first expression |
EFI_IFR_QUESTION_REF3_OP | 0x51 | Push a question’s value from a different form |
EFI_IFR_ZERO_OP | 0x52 | Push a zero |
EFI_IFR_ONE_OP | 0x53 | Push a one |
EFI_IFR_ONES_OP | 0x54 | Push a 0xFFFFFFFFFFFFFFFF |
EFI_IFR_UNDEFINED_OP | 0x55 | Push Undefined |
EFI_IFR_LENGTH_OP | 0x56 | Push length of buffer or string |
EFI_IFR_DUP_OP | 0x57 | Duplicate top of expression stack |
EFI_IFR_THIS_OP | 0x58 | Push the current question’s value |
EFI_IFR_SPAN_OP | 0x59 | Return first matching/non-matching character in a string |
EFI_IFR_VALUE_OP | 0x5A | Provide a value for a question |
EFI_IFR_DEFAULT_OP | 0x5B | Provide a default value for a question |
EFI_IFR_DEFAULTSTORE_OP | 0x5C | Define a Default Type Declaration |
EFI_IFR_FORM_MAP_OP | 0x5D | Create a standards-map form |
EFI_IFR_CATENATE_OP | 0x5E | Push concatenated buffers or strings |
EFI_IFR_GUID_OP | 0x5F | An extensible GUIDed op-code |
EFI_IFR_SECURITY_OP | 0x60 | Returns whether current user profile contains specified setup access privileges |
EFI_IFR_MODAL_TAG_OP | 0x61 | Specify current form is modal |
EFI_IFR_REFRESH_ID_OP | 0x62 | Establish an event group for refreshing a forms-based element |
EFI_IFR_WARNING_IF | 0x63 | Warning conditional |
EFI_IFR_MATCH2_OP | 0x64 | Push TRUE if string matches a Regular Expression pattern |
安装层级结构描述上述的操作码,结构如下:
安装表达式来描述上述的操作符,有如下的结构:
每种类型都有对应的结构体。对应的类型宏和结构体定义在MdePkg\Include\Uefi\UefiInternalFormRepresentation.h中。另外还需要特别关注下面这种:
#define EFI_IFR_GUID_OP 0x5F
其结构体定义如下:
typedef struct _EFI_IFR_GUID {EFI_IFR_OP_HEADER Header;EFI_GUID Guid;//Optional Data Follows
} EFI_IFR_GUID;
可以看到它实际上也不是完整的版本,真正完整版本定义在MdeModulePkg\Include\Guid\MdeModuleHii.h,它有不同的种类:
///
/// GUIDed opcodes defined for EDKII implementation.
///
#define EFI_IFR_TIANO_GUID \{ 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }///
/// EDKII implementation extension opcodes, new extension can be added here later.
///
#define EFI_IFR_EXTEND_OP_LABEL 0x0
#define EFI_IFR_EXTEND_OP_BANNER 0x1
#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2
#define EFI_IFR_EXTEND_OP_CLASS 0x3
#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4
定义的Guid
目前只有EFI_IFR_TIANO_GUID
,后面的数据根据不同的类型值不同,对应的结构体也不同。
【UEFI实战】HII之vfr文件相关推荐
- UEFI实战--------HII之uni文件
uni文件 HII的实现涉及到多种不同类型的文件,uni文件是其中最简单的一种,它用来存放各种语言的字符串以实现本地化.本节主要参考自<edk-ii-uni-specification.pdf& ...
- 【UEFI实战】HII之常用函数
资源安装 HiiAddPackages 函数原型: /**Registers a list of packages in the HII Database and returns the HII Ha ...
- 【UEFI实战】HII之FrontPage
写在前面 UEFI有自己的用户交互界面,它的实现基础被称为HII(Human Interface Infrastructure),本文是一系列介绍HII实现的第一篇.这里从开源EDK代码中的界面(称为 ...
- 浅谈UEFI中VFR文件开发
废话不谈,通过三个实际的开发项目,分享一下VFR开发过程中的心得和应该注意的问题: 1.Set Data And Time 龙芯4000上的实现的原理: 之前4000上是在BdsDxe中实现的,熟悉L ...
- 【UEFI实战】EDK的编译流程说明
前言 使用EDK进行UEFI开发,开始的时候很容易遇到的问题就是编译不过,并非代码的问题,而是编译环境存在异常. 本文主要介绍EDK是如何进行编译的,使用的平台是Windows.这里还想说一点,事实上 ...
- 【UEFI实战】LinuxBoot
综述 LinuxBoot是一个开源的固件,用来替代UEFI BIOS加载Linux的系统. 官网是LinuxBoot. 对应的代码库位于LinuxBoot · GitHub. 另外,本文是在[UEFI ...
- 【UEFI实战】UART的初始化
说明 UART全称是Universal Asynchronous Receiver/Transmitter,这里它表示的是一种实现串口通信的芯片,在整个串口系统中它的位置如下图所示: RS232 +- ...
- 【UEFI实战】FSP简介
说明 在[UEFI实战]SlimBootloader简介中有说到,编译Slim Bootloader的时候需要使用到FSP,本文就是用来介绍FSP是什么,它的作用,以及如何编译等内容. 什么是FSP ...
- 云计算Python自动化运维开发实战 三、python文件类型
为什么80%的码农都做不了架构师?>>> 云计算Python自动化运维开发实战 三.python文件类型 导语: python常用的有3种文件类型 1. 源代码 py ...
最新文章
- 荣耀手机现在是鸿蒙,荣耀适配鸿蒙最新消息出现,华为不会让大家失望的
- 单链表-删除并释放以L为表头指针的单链表的所有结点(双指针法)
- “cvSnakeImage”: 找不到标识符
- 【linux学习笔记三】链接命令
- 自己定义WinXP的时间校正服务器
- GAN对抗生成网络原始论文理解笔记
- Linux中断(interrupt)子系统之五:软件中断(softIRQ)
- POJ 1183 反正切函数的应用(数学代换,基本不等式)
- git clone 分支_Git 小团队的协作 (二)
- nofollow标签_网站Nofollow标签的应用场景
- Auto.js 如何WIFI连接VS Code插件
- 【thinkphp3.x】ThinkPHP/Lib/Core/Model.class.php文件分析
- vue状态管理存取数据_Vue中的数据通信和状态管理
- now.js 0.1.0 发布了
- Python网络爬虫第一弹《Python网络爬虫相关基础概念》
- DataGridView分页
- 教你怎样打领带(附图)绝对实用哦!!!【实用】
- 关于一些初级ACM竞赛题目的分析和题解(三)。
- linux网络服务配置说课,说课稿 LINUX.ppt
- 车道线检测预处理(1)------ 融合白线黄线+高斯