<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
UEFI使用者互動介面的實現涉及到多種不同型別的檔案,這裡要講的是UNI檔案,它也是其中最簡單的一種。本文主要參考自《edk-ii-uni-specification.pdf》(以下簡稱參考檔案)。它可以在EDK II Specifications · tianocore/tianocore.github.io Wiki · GitHub下載到。文字的程式碼範例來自EDK2017,由於版本更新等原因,範例中的程式碼可能跟實際GIT庫中的程式碼有一定的差異。
關於UNI檔案的作用,在參考檔案中做了如下的說明:
就是說,UNI提供了一系列的標記(Token)用來表示文字,這些文字可以有不同的實現(比如可以使用不同的語言,不同的編碼格式),但是在程式碼呼叫中都可以使用統一的標記來表示。以之前在UEFI使用者互動介面使用說明中的圖示為例:
這裡的Select Language就是一個在UNI檔案中定義的標記(具體在FrontPageStrings.uni檔案中):
可以看到,這裡實際上支援兩種語言,一種是英語一種是法語,所以我們的Front Page中可以進行切換:
而在我們的程式碼中,實際上使用的是STR_LANGUAGE_SELECT這個標記:
HiiCreateOneOfOpCode ( StartOpCodeHandle, FRONT_PAGE_KEY_LANGUAGE, 0, 0, STRING_TOKEN (STR_LANGUAGE_SELECT), STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), EFI_IFR_FLAG_CALLBACK, EFI_IFR_NUMERIC_SIZE_1, OptionsOpCodeHandle, NULL );
至於具體如何切換,這裡暫不深入。
關於UNI檔案中的語法,在參考檔案中做了比較詳細的說明(也有沒說明白的地方)。但是因為使用了BNF的表示方法(包括BNF的擴充套件方法),所以初看起來還是有一些吃力,這裡做簡要的介紹。關於BNF以及它的擴充套件版本,可以通過連結檢視,或者在其它的地方找到具體的使用說明。
首先是一些需要了解的基本定義:
UNI檔案中需要指明LanguageCodes,它是表示語言的標記,比如美式英語是en-US,法語是fr-FR,中文是zh-CN等等,它們在rfc4646中定義。
UNI檔案中使用的字串可以包含EscChar,全稱是Escape Character,中文翻譯是跳脫字元,基本聽到中文名懂程式設計的都知道是什麼意思了。
UNI檔案中使用的標記可以包含陣列,英文大小寫,下劃線(_)和折線(-)。UNI檔案中可以包含其它的檔案,使用include表示式。還有在UNI檔案中會用到的基本表示式的BNF表示:
簡單來說,::=左側的是表示式,右側是字串定義。比如<US>這個表示式是最基本的,它就表示一個空格,它也會在::=的右側用到,來組成更復雜的標記;比如<MS>,它的定義是<US>+,就表示多個空格;再比如<ME>,它的定義是<MS>{<EOL>},<EOL>表示的是End Of Line,所以<ME>表示式實際上就是多個空格組成的一行。
以此類推,構成了UNI(其實也是其它一切用BNF或者它的擴充套件版本表示的)檔案的語法基礎,正是上述的基本語法闡述了一個UNI檔案應該如何實現。
UNI檔案的基本語法如下:
以一個實際的例子做對比:
這裡就可以很明確的看到各個部分。不過上述例子中還有一部分沒有包含進去,就是
/=#
它應該屬於<Content>的一部分,稱為ControlRefactor,不過目前不清楚它的作用,並且不是所有的UNI檔案中都包含它,另外<LanguageDefs>也不是所有的UNI檔案都包含,關於這些,在參考檔案中並沒有特別說明原因。
<CommentLine>和<LanguageDefs>兩部分都比較簡單,這裡主要說明下<Content>,它的定義如下:
1. 它也可以包含<CommentLine>,事實上註釋可以出現在任何的位置,關於註釋的表示式,在之前的基本定義中已經說明過,就是以//開頭的行;
2. 空白行也隨時可以出現;
3. <UnicodeLines>是以#string開頭的一個字串(中間可以換行),它算是<Content>中最重要的部分,包含了真正用來定義並在其它檔案中使用的標記;
4. <ControlRefactor>在前面的紅色字型中已有說明,含義不明;
5. <LanguageDefs>也可以出現在<Content>中;
6. <SecurityLines>同樣含義不明;
7. <IncludeLines>也在之前提到過,就是用來包含其它UNI檔案的,像下面那樣:
#include "MiscBaseBoardManufacturer.uni" #include "MiscBiosVendor.uni" #include "MiscChassisManufacturer.uni" #include "MiscOemString.uni" #include "MiscPortInternalConnectorDesignator.uni" #include "MiscSystemLanguageString.uni" #include "MiscSystemManufacturer.uni" #include "MiscSystemOptionString.uni" #include "MiscSystemSlotDesignation.uni"
上述<Content>的定義中,除了兩個標紅的不知道作用,最重要的就是<UnicodeLines>了,它的定義如下:
下面是一個具體的例子:
對於<FontId>沒有找到具體的例子。這裡說明下它的定義:
然後定義的Identifier就會被用在<UnicodeLines>中。
本文的最後介紹下UNI檔案的使用。
首先在C程式碼中要使用UNI檔案,對應模組的INF檔案中需要包含該檔案,以Front Page對應的UiApp.inf為例:
在模組編譯的過程中,編譯工具(其實是Python指令碼)將它們轉換成對應的Unicode位元組,放到AutoGen.c檔案中的某個陣列中。然後在C程式碼中要使用的話,需要先包含該UNI,使用的函數如下:
/** Registers a list of packages in the HII Database and returns the HII Handle associated with that registration. If an HII Handle has already been registered with the same PackageListGuid and DeviceHandle, then NULL is returned. If there are not enough resources to perform the registration, then NULL is returned. If an empty list of packages is passed in, then NULL is returned. If the size of the list of package is 0, then NULL is returned. The variable arguments are pointers which point to package header that defined by UEFI VFR compiler and StringGather tool. #pragma pack (push, 1) typedef struct { UINT32 BinaryLength; EFI_HII_PACKAGE_HEADER PackageHeader; } EDKII_AUTOGEN_PACKAGES_HEADER; #pragma pack (pop) @param[in] PackageListGuid The GUID of the package list. @param[in] DeviceHandle If not NULL, the Device Handle on which an instance of DEVICE_PATH_PROTOCOL is installed. This Device Handle uniquely defines the device that the added packages are associated with. @param[in] ... The variable argument list that contains pointers to packages terminated by a NULL. @retval NULL A HII Handle has already been registered in the HII Database with the same PackageListGuid and DeviceHandle. @retval NULL The HII Handle could not be created. @retval NULL An empty list of packages was passed in. @retval NULL All packages are empty. @retval Other The HII Handle associated with the newly registered package list. **/ EFI_HII_HANDLE EFIAPI HiiAddPackages ( IN CONST EFI_GUID *PackageListGuid, IN EFI_HANDLE DeviceHandle OPTIONAL, ... )
該函數將UNI檔案提供的字串最終放到HII資料庫中,該HII資料庫中還包含影象,表單(Form),字型等內容。下面是一個具體的例子:
// // Publish our HII data // gFrontPagePrivate.HiiHandle = HiiAddPackages ( &mFrontPageGuid, gFrontPagePrivate.DriverHandle, FrontPageVfrBin, UiAppStrings, NULL );
這裡的UiAppStrings引數對應的就是UiApp.uni,對應關係是“BASE_NAME”+Strings對應到字元陣列,這裡的BASE_NAME的值來自inf。同時xxxStrings也是AutoGen.c中轉換後得到的陣列變數名。以上述的UiAppStrings為例(這裡擷取部分程式碼):
// //Unicode String Pack Definition // unsigned char UiAppStrings[] = { // STRGATHER_OUTPUT_HEADER 0xB2, 0x03, 0x00, 0x00, // PACKAGE HEADER 0x7B, 0x01, 0x00, 0x04, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x6E, 0x2D, 0x55, 0x53, 0x00, // PACKAGE DATA // 0x0001: $PRINTABLE_LANGUAGE_NAME:0x0001 0x14, 0x45, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x00, 0x00,
在UiApp.uni中定義的第一個標記是:
在上述的位元組中(PACKAGE DATA部分),第一個0x14有其它的含義(見EFI_HII_SIBT_STRING_UCS2),後面的每兩個位元組就表示一個Unicode字元的英文或者法文(上圖是英文,法文在陣列的後面,這裡沒有列出),可以看到0x0045表示的是Unicode的E,0x006E表示的是Unicode的n(具體的轉換可以看這裡),以此類推。
之後就可以通過對應的GUID使用到定義在UNI中的標記了,使用的方式是
STRING_TOKEN (標記)
這裡的標記最終會被定義成一個宏,放到跟AutoGen.c同一層目錄下的xxxStrDefs.h檔案中,這裡的xxx就是模組的名稱。這個STRING_TOKEN(標記)會被當成一個宏,對應到一個整數,通過這個整數可以找到上述陣列中對應Unicode字串的位置。這個宏最終會被EFI_HII_STRING_PROTOCOL中的GetString()函數使用並解析成字串:
/** This function retrieves the string specified by StringId which is associated with the specified PackageList in the language Language and copies it into the buffer specified by String. @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. @param Language Points to the language for the retrieved string. @param PackageList The package list in the HII database to search for the specified string. @param StringId The string's id, which is unique within PackageList. @param String Points to the new null-terminated string. @param StringSize On entry, points to the size of the buffer pointed to by String, in bytes. On return, points to the length of the string, in bytes. @param StringFontInfo If not NULL, points to the string's font information. It's caller's responsibility to free this buffer. @retval EFI_SUCCESS The string was returned successfully. @retval EFI_NOT_FOUND The string specified by StringId is not available. The specified PackageList is not in the database. @retval EFI_INVALID_LANGUAGE The string specified by StringId is available but not in the specified language. @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to hold the string. @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL. @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL. @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the request. **/ typedef EFI_STATUS (EFIAPI *EFI_HII_GET_STRING)( IN CONST EFI_HII_STRING_PROTOCOL *This, IN CONST CHAR8 *Language, IN EFI_HII_HANDLE PackageList, IN EFI_STRING_ID StringId, OUT EFI_STRING String, IN OUT UINTN *StringSize, OUT EFI_FONT_INFO **StringFontInfo OPTIONAL );
該Protocol在《UEFI Spec》中也有定義。它的初始化位於HiiDatabaseDxe.inf模組中,具體的實現不在這裡深入了。
以上就是UNI檔案說明的全部內容,更多關於UEFI使用者互動介面UNI檔案的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45