UEFI開發(fā)實戰(zhàn)用戶交互界面使用說明VFR文件
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用戶交互界面使用說明之UNI文件中已經介紹過,那些字符串是來自UNI文件的(其實并不是全部來自UNI,也有部分是直接通過代碼生成的),而整個窗體的框架部分則是來自VFR文件的。
在UEFI中,構成這樣的窗體的組件大致有四種,分別是Strings,Forms,Fonts和Images,如下圖所示:
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,也就是上一節(jié)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節(jié)中已經介紹了Form Set List的大致分類,本節(jié)將進一步介紹各種類型的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語句定義:
下面是一個例子:
后續(xù)會較詳細的介紹forms語句內部的定義。
3.6 Forms表達式
前面提到的formset,form,formmap等,其實都是抽象的概念,并不會實際得顯示出來,而本節(jié)講的是具體的概念,且大部分是能夠看到和操作的內容。
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.6.6 vfrStatementQuestions
Question有多種類型,如下所示:
下面說明每一種類型。
vfrStatementBooleanType
BooleanType有兩種類型:
CheckBox的定義如下:
Action的定義如下:
vfrStatementNumericType
Numeric有兩種類型:
Numeric的定義如下:
OneOf的定義如下:
vfrStatementStringType
String包含兩個小類型:
其中String的定義如下:
Password的定義如下:
vfrStatementOrderedList
OrderedList的定義如下:
vfrStatementDate
Date的定義如下:
vfrStatementTime
Time的定義如下:
3.6.7 vfrStatementConditional
Conditional語句其實在之前已經介紹過:
這里不再介紹。
3.6.8 vfrStatementLabel
Label是一個占位符,真正顯示的內容是代碼動態(tài)產生的。
下面是定義:
下面是一個例子:
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.6.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.6.10 vfrStatementExtension
Extension的定義如下:
3.6.11 vfrStatementModal
Model的定義如下:
它只能用在form內部。
具體意義不明。
3.7 VFR表達式
VFR表達式跟C語言差別不大。
下面簡單說明。
3.7.1 常量
常量:
3.7.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.7.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文件的資料請關注腳本之家其它相關文章!
相關文章
從匯編代碼開始全面解析synchronized還原最真實的偏向鎖
這篇文章主要為大家介紹了從模板解釋器匯編源碼開始分析還原最真實的偏向鎖實現,解釋monitorenter字節(jié)碼命令的方法開始,從匯編代碼開始全面解析synchronized2022-02-02