中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

UEFI開發中用戶交互界面如何使用

發布時間:2022-06-06 15:02:29 來源:億速云 閱讀:174 作者:iii 欄目:開發技術

這篇文章主要介紹“UEFI開發中用戶交互界面如何使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“UEFI開發中用戶交互界面如何使用”文章能幫助大家解決問題。

作用

關于UNI文件的作用,在參考文檔中做了如下的說明:

UEFI開發中用戶交互界面如何使用

就是說,UNI提供了一系列的標記(Token)用來表示文本,這些文本可以有不同的實現(比如可以使用不同的語言,不同的編碼格式),但是在代碼調用中都可以使用統一的標記來表示。以之前在【UEFI實戰】UEFI用戶交互界面使用說明中的圖示為例:

UEFI開發中用戶交互界面如何使用

這里的Select Language就是一個在UNI文件中定義的標記(具體在FrontPageStrings.uni文件中):

UEFI開發中用戶交互界面如何使用

可以看到,這里實際上支持兩種語言,一種是英語一種是法語,所以我們的Front Page中可以進行切換:

UEFI開發中用戶交互界面如何使用

而在我們的代碼中,實際上使用的是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表示:

UEFI開發中用戶交互界面如何使用

簡單來說,::=左側的是表達式,右側是字符串定義。比如<US>這個表達式是最基本的,它就表示一個空格,它也會在::=的右側用到,來組成更復雜的標記;比如<MS>,它的定義是<US>+,就表示多個空格;再比如<ME>,它的定義是<MS>{<EOL>},<EOL>表示的是End Of Line,所以<ME>表達式實際上就是多個空格組成的一行。

以此類推,構成了UNI(其實也是其它一切用BNF或者它的擴展版本表示的)文件的語法基礎,正是上述的基本語法闡述了一個UNI文件應該如何實現。

語法說明

UNI文件的基本語法如下:

UEFI開發中用戶交互界面如何使用

以一個實際的例子做對比:

UEFI開發中用戶交互界面如何使用

這里就可以很明確的看到各個部分。不過上述例子中還有一部分沒有包含進去,就是

/=#

它應該屬于<Content>的一部分,稱為ControlRefactor,不過目前不清楚它的作用,并且不是所有的UNI文件中都包含它,另外<LanguageDefs>也不是所有的UNI文件都包含,關于這些,在參考文檔中并沒有特別說明原因。

<CommentLine>和<LanguageDefs>兩部分都比較簡單,這里主要說明下<Content>,它的定義如下:

UEFI開發中用戶交互界面如何使用

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>了,它的定義如下:

UEFI開發中用戶交互界面如何使用

下面是一個具體的例子:

UEFI開發中用戶交互界面如何使用

對于<FontId>沒有找到具體的例子。這里說明下它的定義:

UEFI開發中用戶交互界面如何使用

然后定義的Identifier就會被用在<UnicodeLines>中。

UNI文件的使用

本文的最后介紹下UNI文件的使用。

首先在C代碼中要使用UNI文件,對應模塊的INF文件中需要包含該文件,以Front Page對應的UiApp.inf為例:

UEFI開發中用戶交互界面如何使用

在模塊編譯的過程中,編譯工具(其實是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中定義的第一個標記是:

UEFI開發中用戶交互界面如何使用

在上述的字節中(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
);

關于“UEFI開發中用戶交互界面如何使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

晋州市| 紫金县| 大宁县| 乐清市| 东山县| 余姚市| 青龙| 紫金县| 沽源县| 恭城| 璧山县| 尚志市| 黄平县| 铜陵市| 万宁市| 娱乐| 洮南市| 大同县| 汶上县| 五指山市| 邢台市| 文成县| 淄博市| 清新县| 大冶市| 安化县| 兰西县| 津南区| 武山县| 马关县| 鄢陵县| 嵊泗县| 黎城县| 延川县| 贵溪市| 惠安县| 都匀市| 侯马市| 田林县| 台北市| 江阴市|