您好,登錄后才能下訂單哦!
這篇“UEFI開發用戶交互界面實例分析”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“UEFI開發用戶交互界面實例分析”文章吧。
這里UEFI用戶交互界面的實現載體是OVMF(使用QEMU啟動),其形式如下:
它一般被叫做Front Page(后面將以該名稱來稱呼上述的界面),其下還包括Setup,Boot Manager,Device Manager等選項。
相比Legacy BIOS,UEFI的交互界面要豐富得多,比如支持多語言,支持圖片等,不過EDK默認帶的還是最原始的,跟Legacy BIOS類似的界面。
在EDK2017的OVMF代碼中,Front Page被做成一個獨立的APP(跟Shell一樣),然后注冊,可以通過在啟動過程中按F2來進入,具體的注冊代碼如下:
VOID PlatformRegisterOptionsAndKeys ( VOID ) { EFI_STATUS Status; EFI_INPUT_KEY Enter; EFI_INPUT_KEY F2; EFI_INPUT_KEY Esc; EFI_BOOT_MANAGER_LOAD_OPTION BootOption; // // Register ENTER as CONTINUE key // Enter.ScanCode = SCAN_NULL; Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); ASSERT_EFI_ERROR (Status); // // Map F2 to Boot Manager Menu // F2.ScanCode = SCAN_F2; F2.UnicodeChar = CHAR_NULL; Esc.ScanCode = SCAN_ESC; Esc.UnicodeChar = CHAR_NULL; Status = EfiBootManagerGetBootManagerMenu (&BootOption); ASSERT_EFI_ERROR (Status); Status = EfiBootManagerAddKeyOptionVariable ( NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL ); ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); Status = EfiBootManagerAddKeyOptionVariable ( NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL ); ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); }
而Front Page對應APP的驅動是UiApp.inf,它對應的GUID是:
# Point to the MdeModulePkg/Application/UiApp/UiApp.inf gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
在EfiBootManagerGetBootManagerMenu()函數中會根據上述的GUID尋找UiApp模塊,并生成對應的啟動項。
最終的結果就是啟動過程中按F2就可以進入UiApp模塊,其入口是InitializeUserInterface(),將在后續的內容中介紹。
InitializeUserInterface()模塊的大致流程如下:
其中綠色部分涉及到交互相關的操作,后續會重點說明。
字體使用一種稱為Glyph的元素表示,它其實就是一個二進制的文件,里面包含了描述字體的元素,但是具體是怎么樣表示的,目前還不是很清楚,這個也不是我們需要關注的重點。
這個二進制在代碼中有下述的數組表示:
typedef struct { /// /// This 4-bytes total array length is required by HiiAddPackages() /// UINT32 Length; // // This is the Font package definition // EFI_HII_PACKAGE_HEADER Header; UINT16 NumberOfNarrowGlyphs; UINT16 NumberOfWideGlyphs; EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; } FONT_PACK_BIN; FONT_PACK_BIN mFontBin = { sizeof (FONT_PACK_BIN), { sizeof (FONT_PACK_BIN) - sizeof (UINT32), EFI_HII_PACKAGE_SIMPLE_FONTS, }, NARROW_GLYPH_NUMBER, 0, { // Narrow Glyphs { 0x05d0, 0x00, { 0x00, // 后面的省略
這個數組通過一個通過HiiAddPackages()導入,如下所示:
/** Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. **/ EFI_HII_HANDLE ExportFonts ( VOID ) { return HiiAddPackages ( &mFontPackageGuid, gImageHandle, &mFontBin, NULL ); }
字符串通過UNI文件轉換成,編譯時在AutoGen.c中生成對應的數組,然后通過下面的函數來注冊到HII數據庫中:
/** Initialize HII global accessor for string support. **/ VOID InitializeStringSupport ( VOID ) { gStringPackHandle = HiiAddPackages ( &mUiStringPackGuid, gImageHandle, UiAppStrings, NULL ); ASSERT (gStringPackHandle != NULL); }
這里的UiAppStrings就是通過.uni文件生成的字符串表示。
可以看到,導入字體和字符串使用的是相同的函數。
進入UI界面是通過UiEntry()來實現的,其大致流程如下:
這里的重點也主要在綠色部分,它包含了Front Page的初始化和調用。
上述的綠色部分大致流程如下所示:
這里最重要的是兩個部分,一個是更新Front Page的部分,另一個是SendForm()的部分。
更新Front Page部分主要由UpdateFrontPageBannerStrings()、UpdateFrontPageForm()等函數組成,它們使用了各類HII操作來更新界面,比如說UiCustomizeFrontPageBanner()構成了Front Page界面中的一條條的字符串顯示(就是開頭圖片中的藍字部分),另外還有UiCustomizeFrontPage()、HiiUpdateForm()等函數,都更新了界面。
SendForm()部分,它其實是整個UEFI界面顯示的引擎,這部分實現在顯示界面(比如圖形輸出界面,或者串口)上顯示前面更新的內容,后續會詳細介紹。
以上就是關于“UEFI開發用戶交互界面實例分析”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。