天天看點

【UEFI實戰】UEFI使用者互動界面之C代碼實作前言一、C代碼的生成二、解讀定義AutogenPackageHeader三、總結

提示:HII使用者互動界面的c代碼實作過程

文章目錄

  • 前言
  • 一、C代碼的生成
  • 二、解讀
  • 定義AutogenPackageHeader
    • 定義PackageHeader
    • PACKAGE_LIST_HEADER
    • FORM_PACKAGE_HDR
    • STRING_PACKAGE_HDR
    • FONT_PACKAGE_HDR
    • IMAGE_PACKAGE_HDR
    • DEVICE_PATH_PACKAGE_HDR
    • GUID_PACKAGE_HDR
    • KEYBOARD_PACKAGE_HDR
    • ANIMATION_PACKAGE_HDR
  • 三、總結

前言

在檢視build目錄下的對應Pakage目錄下的DEBUG目錄下可以找到與VFR檔案相對應的.c代碼。

如下

unsigned char PciVfrBin[] = {
  // ARRAY LENGTH

  0x13,  0x01,  0x00,  0x00,  

  // PACKAGE HEADER

  0x0F,  0x01,  0x00,  0x02,  

  // PACKAGE DATA

  0x0E,  0xA7,  0xE8,  0x3E,  0x42,  0x21,  0xE1,  0x72,  0xCB,  0x49,  0xAD,  0xA0,  0xA4,  0xBC,  0xCD,  0xC8,  
  ……
  
};
           

那他是怎麼生成的,又該怎麼解析?

提示:隻是個人了解可能會有一些錯誤,如果有錯誤的地方希望能夠指出來共同進步

一、C代碼的生成

C代碼是根據VFR檔案使用Basetools中VfrCompile工具和StringGather.py來生成的。

二、解讀

定義AutogenPackageHeader

HiiLib.h檔案中定義

#pragma pack (push, 1)
  typedef struct {
    UINT32                  BinaryLength;
    EFI_HII_PACKAGE_HEADER  PackageHeader;
  } EDKII_AUTOGEN_PACKAGES_HEADER;
  #pragma pack (pop)
           

c檔案的代碼中

// ARRAY LENGTH

  0x13,  0x01,  0x00,  0x00,
           

資料0x00000113 即 BinaryLength = 275 Bytes

定義PackageHeader

typedef struct {
  UINT32  Length:24;
  UINT32  Type:8;
  // UINT8  Data[...];
} EFI_HII_PACKAGE_HEADER;
           

c檔案代碼中

// PACKAGE HEADER

  0x0F,  0x01,  0x00,  0x02, 
  
           

在檔案UefiInternalFormRepresentation.h定義Package Type。

#define EFI_HII_PACKAGE_TYPE_ALL             0x00
#define EFI_HII_PACKAGE_TYPE_GUID            0x01
#define EFI_HII_PACKAGE_FORMS                0x02
#define EFI_HII_PACKAGE_STRINGS              0x04
#define EFI_HII_PACKAGE_FONTS                0x05
#define EFI_HII_PACKAGE_IMAGES               0x06
#define EFI_HII_PACKAGE_SIMPLE_FONTS         0x07
#define EFI_HII_PACKAGE_DEVICE_PATH          0x08
#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT      0x09
#define EFI_HII_PACKAGE_ANIMATIONS           0x0A
#define EFI_HII_PACKAGE_END                  0xDF
#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN    0xE0
#define EFI_HII_PACKAGE_TYPE_SYSTEM_END      0xFF

           

資料PackageLength 0x00010F即長度為271Bytes ,PackageType 0x02 即本資料為Package Form資料。

它是一系列Package中最開始的資料,這些package中最重要的是二進制資料,這些二進制資料就是 String 、Fonts、Images和Forms等列出來的為顯示架構的基礎部分資料,生成的各類Package同時用HiiAddPackages()注冊到PackageList,PackageList以mEndOfPackageList結束。基本資料排布為:

EFI_HII_PACKAGE_LIST_HEADER ->Package1->……->PackageN->mEndOfPackageList。PackageList的GUID就是HiiAddPackages傳入的參數的GUID也用于辨別整個Package表。

PACKAGE_LIST_HEADER

typedef struct {
  EFI_GUID               PackageListGuid;
  UINT32                 PackageLength;
} EFI_HII_PACKAGE_LIST_HEADER;
           

FORM_PACKAGE_HDR

typedef struct _EFI_HII_FORM_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER       Header;
  // EFI_IFR_OP_HEADER         OpCodeHeader;
  // More op-codes follow
} EFI_HII_FORM_PACKAGE_HDR;
           

自動生成的檔案在edkii\Build\EmulatorIA32\DEBUG_VS2015x86\IA32\MdeModulePkg\Library\BootManagerUiLib\BootManagerUiLib\DEBUG目錄下的xxxVfr.c檔案。

STRING_PACKAGE_HDR

typedef struct _EFI_HII_STRING_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER  Header;
  UINT32                  HdrSize;
  UINT32                  StringInfoOffset;
  CHAR16                  LanguageWindow[16];
  EFI_STRING_ID           LanguageName;
  CHAR8                   Language[1];
} EFI_HII_STRING_PACKAGE_HDR;
           

String編譯的二進制資料在編譯後生成的AutoGen.c檔案内。

如:

//
//Unicode String Pack Definition
//
unsigned char BootManagerUiLibStrings[] = {

// STRGATHER_OUTPUT_HEADER
  0x34,  0x04,  0x00,  0x00,

// PACKAGE HEADER

  0x40,  0x02,  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, 
  ……
           

FONT_PACKAGE_HDR

typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER Header;
  UINT16                 NumberOfNarrowGlyphs;
  UINT16                 NumberOfWideGlyphs;
  // EFI_NARROW_GLYPH       NarrowGlyphs[];
  // EFI_WIDE_GLYPH         WideGlyphs[];
} EFI_HII_SIMPLE_FONT_PACKAGE_HDR;
           

它在UiApp.inf中有使用到。

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,
        0x00,
        0x00,
        ……
           

注冊HII資料庫。

EFI_HII_HANDLE
ExportFonts (
  VOID
  )
{
  return HiiAddPackages (
           &mFontPackageGuid,
           gImageHandle,
           &mFontBin,
           NULL
           );
}
           
///
/// The fixed header consists of a standard record header,
/// then the character values in this section, the flags
/// (including the encoding method) and the offsets of the glyph
/// information, the glyph bitmaps and the character map.
///
typedef struct _EFI_HII_FONT_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER Header;
  UINT32                 HdrSize;
  UINT32                 GlyphBlockOffset;
  EFI_HII_GLYPH_INFO     Cell;
  EFI_HII_FONT_STYLE     FontStyle;
  CHAR16                 FontFamily[1];
} EFI_HII_FONT_PACKAGE_HDR;
           

IMAGE_PACKAGE_HDR

//
// Definitions for Image Package
// Section 27.3.7
//

typedef struct _EFI_HII_IMAGE_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER  Header;
  UINT32                  ImageInfoOffset;
  UINT32                  PaletteInfoOffset;
} EFI_HII_IMAGE_PACKAGE_HDR;
           

DEVICE_PATH_PACKAGE_HDR

///
/// The device path package is used to carry a device path
/// associated with the package list.
///
typedef struct _EFI_HII_DEVICE_PATH_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER   Header;
  // EFI_DEVICE_PATH_PROTOCOL DevicePath[];
} EFI_HII_DEVICE_PATH_PACKAGE_HDR;
           

GUID_PACKAGE_HDR

//
// Definitions for GUID Package
// Section 27.3.5
//

///
/// The GUID package is used to carry data where the format is defined by a GUID.
///
typedef struct _EFI_HII_GUID_PACKAGE_HDR {
  EFI_HII_PACKAGE_HEADER  Header;
  EFI_GUID                Guid;
  // Data per GUID definition may follow
} EFI_HII_GUID_PACKAGE_HDR;
           

KEYBOARD_PACKAGE_HDR

typedef struct {
  EFI_HII_PACKAGE_HEADER  Header;
  UINT16                  LayoutCount;
  // EFI_HII_KEYBOARD_LAYOUT Layout[];
} EFI_HII_KEYBOARD_PACKAGE_HDR;
           

ANIMATION_PACKAGE_HDR

///
/// HII animation package header.
///
typedef struct _EFI_HII_ANIMATION_PACKAGE_HDR {
  ///
  /// Standard package header, where Header.Type = EFI_HII_PACKAGE_ANIMATIONS.
  ///
  EFI_HII_PACKAGE_HEADER  Header;
  ///
  /// Offset, relative to this header, of the animation information. If
  /// this is zero, then there are no animation sequences in the package.
  ///
  UINT32                  AnimationInfoOffset;
} EFI_HII_ANIMATION_PACKAGE_HDR;
           

三、總結

根據對PackageHeader的觀察,header中注釋掉的并不是不用而是為了提示後面的資料解析提供一個線索。
           

繼續閱讀