UEFI開(kāi)發(fā)實(shí)戰(zhàn)用戶(hù)交互界面使用說(shuō)明VFR文件
1. 綜述
UEFI用戶(hù)交互界面的實(shí)現(xiàn)涉及到多種不同類(lèi)型的文件,這里要講的是VFR文件,相比UNI文件它要復(fù)雜得多,理解起來(lái)也更困難。
本文主要參考自《edk-ii-vfr-specification.pdf》(以下簡(jiǎn)稱(chēng)參考文檔)和《UEFI Spec》。
它們可以在EDK II Specifications · tianocore/tianocore.github.io Wiki · GitHub下載到。
文本的代碼示例來(lái)自EDK2017,由于版本更新等原因,示例中的代碼可能跟實(shí)際GIT庫(kù)中的代碼有一定的差異。
2. 作用
在說(shuō)明VFR文件得作用之前,首先需要祭出一張?jiān)谥坝眠^(guò)多次的圖:
在UEFI用戶(hù)交互界面使用說(shuō)明之UNI文件中已經(jīng)介紹過(guò),那些字符串是來(lái)自UNI文件的(其實(shí)并不是全部來(lái)自UNI,也有部分是直接通過(guò)代碼生成的),而整個(gè)窗體的框架部分則是來(lái)自VFR文件的。
在UEFI中,構(gòu)成這樣的窗體的組件大致有四種,分別是Strings,F(xiàn)orms,F(xiàn)onts和Images,如下圖所示:
Strings就是前面講到的UNI文件提供的,F(xiàn)orms就是本文的VFR文件提供的,后面兩者暫時(shí)還未介紹,本文主要介紹的就是這個(gè)Forms,以及構(gòu)成Forms的VFR文件。
關(guān)于Forms的定義,在《UEFI Spec》中有如下的說(shuō)明:
Forms描述了窗體的組織形式,提供了用戶(hù)交互的方式和交互內(nèi)容的存儲(chǔ)方式等。
Forms是以二進(jìn)制的形式提供的,這種二進(jìn)制在EDK框架中被稱(chēng)為IFR(就是上述定義中提到的Internal Forms Representation)。
而IFR通過(guò)編譯VFR來(lái)生成(關(guān)于編譯工具,在EDK源代碼中也有相應(yīng)的源碼,不過(guò)沒(méi)有研究過(guò)不確定怎么用)。
因此,總的來(lái)說(shuō)就是,我們通過(guò)編寫(xiě)VFR文件來(lái)完成對(duì)UEFI交互界面的組織形式和交互方式等相關(guān)內(nèi)容的定義。
3. 語(yǔ)法
參考文檔中給出了VFR的詳細(xì)語(yǔ)法說(shuō)明,這里簡(jiǎn)單介紹下。
3.1 注釋
VFR文件中可以使用“//”來(lái)注釋?zhuān)珻語(yǔ)言和UNI文件。
3.2 預(yù)定義
VFR文件中可以使用幾種預(yù)定義的指令,如#define、#include、#pragma等。
功能同C語(yǔ)言。
下面是一個(gè)例子:
#pragma一般會(huì)在使用#include包含的C語(yǔ)言頭文件中。
3.3 數(shù)據(jù)結(jié)構(gòu)
前文中已經(jīng)看到,VFR文件支持#include來(lái)包含C語(yǔ)言的頭文件,因此C語(yǔ)言頭文件中可以包含的數(shù)據(jù)結(jié)構(gòu)VFR文件也都是支持的。
包括UINT8, UINT16, UINT32, UINT64, BOOLEAN等基本數(shù)據(jù)類(lèi)型,和HII特定的數(shù)據(jù)類(lèi)型,如EFI_STRING_ID, EFI_HII_DATA, EFI_HII_TIME, EFI_HII_REF,還有就是通過(guò)typedef自定義的結(jié)構(gòu)體。
一維的數(shù)組也是支持的,但是不支持枚舉和多維的數(shù)組。
3.4 Forms相關(guān)表達(dá)式總覽
以上的內(nèi)容都是基礎(chǔ)內(nèi)容,且都是屬于C語(yǔ)言的范圍。
下面的內(nèi)容是VFR特有的表達(dá)式。
3.4.1 formset
formset的具體定義沒(méi)有找到。
但是它屬于組成窗口的主體,也是VFR文件中最重要的部分。
它的定義如下(也是使用BNF表達(dá)方式定義的):
下面是一個(gè)例子:
guid就是通過(guò)#define定義的一個(gè)普通的GUID;
title中STRING_TOKE()括號(hào)中的就是在UNI文件中定義的字符串;
help同title;
classguid,class和subclass是可選的,作用不明。下面是class和subclass的一個(gè)例子:
classguid的定義如下:
guidDefinition就是普通的GUID。
class的定義如下:
subclass的定義如下:
3.4.2 formset list
formset內(nèi)部定義了很多的子選項(xiàng),稱(chēng)為formset list,也就是上一節(jié)formset定義中的vfrFormSetList。
前面的例子中用到的form就是其中的一種。
formset list可以有如下的內(nèi)容:
上述的內(nèi)容可以分為幾種不同的類(lèi)型:
- 1. 變量定義,如defaultstore,varstore,efivarstore,namevaluevarstore等;
- 2. 控制語(yǔ)句,它會(huì)做if判斷來(lái)確定其包含的formset list是否會(huì)被使用,主要有disableif,suppressif,grayoutif和goto語(yǔ)句等(上述的語(yǔ)句只在目前只在form類(lèi)型語(yǔ)句中見(jiàn)到過(guò),在其外沒(méi)遇見(jiàn)過(guò),不確定是否可以在它之外);
- 3. form語(yǔ)句,它們是formset里面的主體部分,有form,formmap等;
- 4. 其它語(yǔ)句;
3.5 Form Set List
3.4.2節(jié)中已經(jīng)介紹了Form Set List的大致分類(lèi),本節(jié)將進(jìn)一步介紹各種類(lèi)型的Form Set List。
3.5.1 變量定義
下面是各種變量的定義。
defaultstore:
下面是一個(gè)例子:
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:
第一個(gè)StringIdentifier表示的是類(lèi)型,第二個(gè)表示的是變量名,name和guid連起來(lái)就可以表示該特定的變量。
下面是一個(gè)例子:
它定義的是一個(gè)數(shù)據(jù)結(jié)構(gòu)體變量,類(lèi)型就是DRIVER_SAMPLE_CONFIGURATION。
MyIfrNVData是變量的名稱(chēng),后面的VFR表達(dá)式中會(huì)通過(guò)該名稱(chēng)去引用該變量。
efivarstore:
下面是一個(gè)例子:
這里定義的就是UEFI變量,還可以聲明變量的屬性。
namevaluevarstore:
下面是一個(gè)例子:
3.5.2 控制語(yǔ)句
VFR文件中可以包含如下的控制語(yǔ)句:
DisableIf語(yǔ)句,定義如下:
SuppressIf語(yǔ)句,定義如下:
GrayOutIf語(yǔ)句,定義如下:
下面是一個(gè)例子:
需要注意幾點(diǎn):
1. if條件之后有一個(gè)分號(hào);
2. 最后有一個(gè)endif與之對(duì)應(yīng);
另外還有一個(gè)goto語(yǔ)句,其定義如下:
下面是goto語(yǔ)句的一個(gè)例子:
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;
對(duì)應(yīng)的界面如下:
紅框部分就是4個(gè)goto語(yǔ)句。
3.5.3 Question語(yǔ)句
在goto語(yǔ)句中,有一個(gè)vfrStatementQuestionOptionList需要介紹下。
它的定義如下:
其中的vfrStatementQuestionTag和vfrStatementQuestionOptionTag又是比較大的兩塊內(nèi)容:
順便還提一個(gè):
上述的各個(gè)子元素的定義如下:
vfrStatementSuppressIfQuest:
vfrStatementValue:
vfrStatementDefault:
vfrStatementOptions:
vfrStatementRead:
vfrStatementWrite:
vfrStatementInconsistentIf:
vfrStatementNoSubmitIf:
vfrStatementDisableIfQuest:
vfrStatementRefresh:
vfrStatementVarstoreDevice:
vfrStatementExtension:
無(wú)。
vfrStatementRefreshEvent:
vfrStatementWarningIf:
3.5.4 form語(yǔ)句
VFR文件中包含下述的form語(yǔ)句:
form語(yǔ)句定義:
下面是一個(gè)例子:
formmap語(yǔ)句定義:
下面是一個(gè)例子:
后續(xù)會(huì)較詳細(xì)的介紹forms語(yǔ)句內(nèi)部的定義。
3.6 Forms表達(dá)式
前面提到的formset,form,formmap等,其實(shí)都是抽象的概念,并不會(huì)實(shí)際得顯示出來(lái),而本節(jié)講的是具體的概念,且大部分是能夠看到和操作的內(nèi)容。
3.6.1 vfrStatementImage
Image的定義如下:
目前不確定如何使用。
3.6.2 vfrStatementLocked
Locked的定義如下:
目前也不確定如何使用。
3.6.3 vfrStatementRules
Rules的定義如下:
這個(gè)Rules會(huì)在用戶(hù)輸入的時(shí)候做檢測(cè)(引用StringIdentifier來(lái)完成)。
3.6.4 vfrStatementDefault
無(wú)。
3.6.5 vfrStatementStat
Stat有多種的形式,如下所示:
vfrStatementSubTitle
SubTitle的定義如下:
下面是一個(gè)例子:
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;
對(duì)應(yīng)的界面如下:
紅框部分就是一個(gè)SubTitle。
vfrStatementStaticText
Text的定義如下:
這里的text是獨(dú)立的部分,而不是SubTitle的子元素。
下面是一個(gè)例子:
text help = STRING_TOKEN(STR_CONTINUE_HELP), text = STRING_TOKEN(STR_CONTINUE_PROMPT), flags = INTERACTIVE, key = FRONT_PAGE_KEY_CONTINUE;
對(duì)應(yīng)的界面如下:
vfrStatementCrossReference
Cross Reference的定義如下:
作用不明。
3.6.6 vfrStatementQuestions
Question有多種類(lèi)型,如下所示:
下面說(shuō)明每一種類(lèi)型。
vfrStatementBooleanType
BooleanType有兩種類(lèi)型:
CheckBox的定義如下:
Action的定義如下:
vfrStatementNumericType
Numeric有兩種類(lèi)型:
Numeric的定義如下:
OneOf的定義如下:
vfrStatementStringType
String包含兩個(gè)小類(lèi)型:
其中String的定義如下:
Password的定義如下:
vfrStatementOrderedList
OrderedList的定義如下:
vfrStatementDate
Date的定義如下:
vfrStatementTime
Time的定義如下:
3.6.7 vfrStatementConditional
Conditional語(yǔ)句其實(shí)在之前已經(jīng)介紹過(guò):
這里不再介紹。
3.6.8 vfrStatementLabel
Label是一個(gè)占位符,真正顯示的內(nèi)容是代碼動(dòng)態(tài)產(chǎn)生的。
下面是定義:
下面是一個(gè)例子:
label之后接的是一個(gè)數(shù)值。
label對(duì)應(yīng)到代碼中的結(jié)構(gòu)體如下:
/// /// 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.6.9 vfrStatementBanner
Banner的形式如下圖紅框部分所示:
它是一個(gè)可顯示的字符串,比普通的字符串要顯眼一點(diǎn)。
它的定義如下:
title
是具體顯示的內(nèi)容;
line
表示具體在哪一行顯示;
align
表示字符顯示在行的哪個(gè)位置,又左中右三種情況;
timeout
不能跟line和align合用,作用不明。
banner
對(duì)應(yīng)到代碼中的結(jié)構(gòu)體如下:
/// /// 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.6.10 vfrStatementExtension
Extension的定義如下:
3.6.11 vfrStatementModal
Model的定義如下:
它只能用在form內(nèi)部。
具體意義不明。
3.7 VFR表達(dá)式
VFR表達(dá)式跟C語(yǔ)言差別不大。
下面簡(jiǎn)單說(shuō)明。
3.7.1 常量
常量:
3.7.2 操作符
- OR:或操作,對(duì)應(yīng)到EFI_IFR_OR;
- AND:與操作,對(duì)應(yīng)EFI_IFR_AND;
- |:位或操作,對(duì)應(yīng)EFI_IFR_BITWISE_OR;
- &:位與操作,對(duì)應(yīng)EFI_IFR_BITWISE_AND;
- ~:位反,對(duì)應(yīng)EFI_IFR_BITWISENOT;
- ==:等于操作,對(duì)應(yīng)EFI_IFR_EQUAL;
- !=:不等于操作,對(duì)應(yīng)EFI_IFR_NOT_EQUAL;
- <,<=,>,>=:比較操作,對(duì)應(yīng)EFI_IFR_LESS_THAN,EFI_IFR_LESS_EQUAL,EFI_IFR_IFR_GREATER_EQUAL和EFI_IFR_GREATER_THAN;
- <<,>>:位移操作,對(duì)應(yīng)EFI_IFR_SHIFT_LEFT和EFI_IFR_SHIFT_RIGHT;
- +,-:加減操作,對(duì)應(yīng)EFI_IFR_ADD和EFI_IFR_SUBTRACT;
- *,/,%:乘余除操作,對(duì)應(yīng)EFI_IFR_MULTIPLY,EFI_IFR_MODULO和EFI_IFR_DIVIDE;
- ():括號(hào);
- (UINTX/BOOLEAN):強(qiáng)制轉(zhuǎn)換操作;
3.7.3 內(nèi)置函數(shù)
- dup:復(fù)制操作,對(duì)應(yīng)EFI_IFR_DUP;
- ideqval x==y:判斷x和y的值是否相等,對(duì)應(yīng)EFI_IFR_EQ_ID_VAL;
- ideqid x==y:判斷x和y的ID是否相等,對(duì)應(yīng)EFI_IFR_EQ_ID_ID;
- ideqvallist x==y+:判斷x和y+(表示多個(gè)值)是否相同,對(duì)應(yīng)EFI_IFR_EQ_ID_LIST;
- questionref(x):Question引用,對(duì)應(yīng)EFI_IFR_QUESTION_REF1;
- questionrefval(s):作用不明,對(duì)應(yīng)EFI_IFR_QUESTION_REF2或EFI_IFR_QUESTION_REF2;
- ruleref(x):Rule引用,對(duì)應(yīng)EFI_IFR_RULE_REF;
- stringref(x):字符串引用,對(duì)應(yīng)EFI_IFR_STRING_REF1;
- stringrefval(s):作用不明,對(duì)應(yīng)EFI_IFR_STRING_REF2;
- pushthis:作用不明,對(duì)應(yīng)EFI_IFR_THIS;
- security(x):作用不明,對(duì)應(yīng)EFI_IFR_SECURITY;
- get(x):獲取變量,對(duì)應(yīng)EFI_IFR_GET;
- set(x,y):設(shè)置變量,對(duì)應(yīng)EFI_IFR_SET;
- boolval(s):轉(zhuǎn)BOOLEAN,對(duì)應(yīng)EFI_IFR_TO_BOOLEAN;
- unintval(s):轉(zhuǎn)UINT整型,對(duì)應(yīng)EFI_IFR_TO_UINT;
- tolower(s):字符串變小寫(xiě),對(duì)應(yīng)EFI_IFR_TO_LOWER;
- toupper(s):字符串變大寫(xiě),對(duì)應(yīng)EFI_IFR_TO_UPPER;
- catenate(x,y):字符串連接,對(duì)應(yīng)EFI_IFR_CATENATE;
- cond(x?y:z):就是If (Expr1) then x = Expr3 else Expr2,對(duì)應(yīng)EFI_IFR_CONDITIONAL;
- find(format,s1,s2,x):字符串尋找,對(duì)應(yīng)EFI_IFR_FIND;
- mid(a,b,c):作用不明,對(duì)應(yīng)EFI_IFR_MID;
- token(a,b,c):作用不明,對(duì)應(yīng)EFI_IFR_TOKEN;
- span(flag=x,a,b,c):作用不明,對(duì)應(yīng)EFI_IFR_SPAN;
- map(a:(b)*):作用不明,對(duì)應(yīng)EFI_IFR_MAP;
- match(a,b):字符串比較,對(duì)應(yīng)EFI_IFR_MATCH;
- match2(pattern,string,guid):字符串比較,對(duì)應(yīng)EFI_IFR_MATCH2;
- length(x):字符串長(zhǎng)度計(jì)算;
以上就是VFR文件說(shuō)明的全部?jī)?nèi)容。
由于《參考文檔》也有不少內(nèi)容沒(méi)有解釋清楚,加上個(gè)人能力有限,所以目前對(duì)VFR也只是一個(gè)大致的了解,更多關(guān)于UEFI用戶(hù)交互界面VFR文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
iOS匯編入門(mén)教程之ARM64匯編基礎(chǔ)教程
這篇文章主要介紹了iOS匯編入門(mén)教程之ARM64匯編基礎(chǔ)教程,本文通過(guò)例子給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02從匯編代碼開(kāi)始全面解析synchronized還原最真實(shí)的偏向鎖
這篇文章主要為大家介紹了從模板解釋器匯編源碼開(kāi)始分析還原最真實(shí)的偏向鎖實(shí)現(xiàn),解釋monitorenter字節(jié)碼命令的方法開(kāi)始,從匯編代碼開(kāi)始全面解析synchronized2022-02-02匯編語(yǔ)言功能實(shí)現(xiàn)數(shù)據(jù)復(fù)制實(shí)例詳解
這篇文章主要為大家介紹了匯編語(yǔ)言功能實(shí)現(xiàn)數(shù)據(jù)復(fù)制的實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11匯編程序輸出“Hello world”的實(shí)現(xiàn)
這篇文章主要介紹了匯編程序輸出“Hello world”的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01