【UEFI实战】HII之常用函数---HiiAddPackages
创始人
2024-06-02 14:36:57
0

资源安装
HiiAddPackages
函数原型:

/**
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,

)

简单来说就是将资源(代码中用Package标识,这里将其翻译为资源似乎更好理解,它表示的可能是uni文件对应的字符串、vfr文件对应的Setup骨架、字体等等)安装HII数据库中,并返回数据库的Handle,后续要使用资源就要用到这个Handle。

它的第一个参数是GUID,用来唯一地标识安装的资源,目前不确定其作用,似乎是为了防止重复安装的;DeviceHandle用来在其上安装DEVICE_PATH_PROTOCOL实例,通过这种方式就可以将资源与安装在DeviceHandle之上的其它内容(比如设备)等联系在一起;…表示的是需要安装的资源。

下面是一个简单的例子,为了使用字符串资源,这里首先通过HiiAddPackages()进行安装:

VOID
InitializeStringSupport (
VOID
)
{
gStringPackHandle = HiiAddPackages (
&mUiStringPackGuid,
gImageHandle,
UiAppStrings,
NULL
);
ASSERT (gStringPackHandle != NULL);
}

UiAppStrings对应uni文件得到的数据,它通过HiiAddPackages()安装,并返回全局的gStringPackHandle,这个后面会用到,而另外一个gImageHandle在本例中并不重要。使用字符串资源的代码示例:

String = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
1
STR_MISSING_STRING是uni文件中定义的宏,gStringPackHandle是前面调用HiiAddPackages时的返回值,第三个参数NULL表示跟随当前语言。另外需要注意的是这里的返回值String后面需要释放。

另一个比较复杂的示例,首先也是安装:

//
// Publish our HII data
//
gFrontPagePrivate.HiiHandle = HiiAddPackages (
&mFrontPageGuid,
gFrontPagePrivate.DriverHandle,
FrontPageVfrBin,
UiAppStrings,
NULL
);

这里的mFrontPageGuid跟vfr文件(MdeModulePkg\Application\UiApp\FrontPageVfr.Vfr)中的GUID一致,就是下面的FORMSET_GUID:

#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }

#define FRONT_PAGE_FORM_ID 0x1000

#define LABEL_FRANTPAGE_INFORMATION 0x1000
#define LABEL_END 0xffff

formset
guid = FORMSET_GUID,
title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),
help = STRING_TOKEN(STR_EMPTY_STRING ),
classguid = FORMSET_GUID,

返回的gFrontPagePrivate.HiiHandle会在EFI_FORM_BROWSER2_PROTOCOL中使用:

Status = gFormBrowser2->SendForm (
gFormBrowser2,
&gFrontPagePrivate.HiiHandle,
1,
&mFrontPageGuid,
0,
NULL,
&ActionRequest
);

这里也用到了mFrontPageGuid,且应该是必须的,跟classguid = FORMSET_GUID匹配。

目前可添加的Packages有如下的种类:

Font
Simplified Font
String
Image
Device Path
keyboard Layout
GUID
Forms
本例中就使用了Font和String这些Package。

创建操作码
操作码可以在vfr文件中指定,也可以通过代码创建,下面介绍一些简单的创建操作码的函数。

HiiAllocateOpCodeHandle/HiiFreeOpCodeHandle
HiiAllocateOpCodeHandle()创建HII_LIB_OPCODE_BUFFER结构体并返回:

VOID *
EFIAPI
HiiAllocateOpCodeHandle (
VOID
)

其结构如下:

typedef struct {
UINT8 *Buffer;
UINTN BufferSize;
UINTN Position;
} HII_LIB_OPCODE_BUFFER;

创建好之后的结构体中Buffer是一个大小为0x200字节的空间;BufferSize就是0x200;Position初始化为0。

HiiFreeOpCodeHandle()用来释放HiiAllocateOpCodeHandle()分配的数据,两者配合使用。

Buffer里面存放到就是各类操作码,如果操作码多,则Buffer还会根据实际的情况重新分配大小以存放所有的操作码。

HiiCreateActionOpCode
创建一个可以执行的操作码,其函数原型:

/**
Create EFI_IFR_ACTION_OP opcode.

If OpCodeHandle is NULL, then ASSERT().
If any reserved bits are set in QuestionFlags, then ASSERT().

@param[in] OpCodeHandle Handle to the buffer of opcodes.
@param[in] QuestionId Question ID
@param[in] Prompt String ID for Prompt
@param[in] Help String ID for Help
@param[in] QuestionFlags Flags in Question Header
@param[in] QuestionConfig String ID for configuration

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateActionOpCode (
IN VOID *OpCodeHandle,
IN EFI_QUESTION_ID QuestionId,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN EFI_STRING_ID QuestionConfig
)

操作码对应的结构体:

typedef struct _EFI_IFR_ACTION {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_STRING_ID QuestionConfig;
} EFI_IFR_ACTION;

HiiCreateGotoExOpCode
创建的操作码用于跳转,其函数原型:

/**
Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.

When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.

If OpCodeHandle is NULL, then ASSERT().
If any reserved bits are set in QuestionFlags, then ASSERT().

@param[in] OpCodeHandle The handle to the buffer of opcodes.
@param[in] RefFormId The Destination Form ID.
@param[in] Prompt The string ID for Prompt.
@param[in] Help The string ID for Help.
@param[in] QuestionFlags The flags in Question Header
@param[in] QuestionId Question ID.
@param[in] RefQuestionId The question on the form to which this link is referring.
If its value is zero, then the link refers to the top of the form.
@param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is
zero, then the link is to the current form set.
@param[in] RefDevicePath The string identifier that specifies the string containing the text representation of
the device path to which the form set containing the form specified by FormId.
If its value is zero, then the link refers to the current page.

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateGotoExOpCode (
IN VOID *OpCodeHandle,
IN EFI_FORM_ID RefFormId,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN EFI_QUESTION_ID QuestionId,
IN EFI_QUESTION_ID RefQuestionId,
IN EFI_GUID *RefFormSetId, OPTIONAL
IN EFI_STRING_ID RefDevicePath
)

创建的结构体根据参数的不同而存在差异:

typedef struct _EFI_IFR_REF {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_FORM_ID FormId;
} EFI_IFR_REF;

typedef struct _EFI_IFR_REF2 {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_FORM_ID FormId;
EFI_QUESTION_ID QuestionId;
} EFI_IFR_REF2;

typedef struct _EFI_IFR_REF3 {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_FORM_ID FormId;
EFI_QUESTION_ID QuestionId;
EFI_GUID FormSetId;
} EFI_IFR_REF3;

typedef struct _EFI_IFR_REF4 {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_FORM_ID FormId;
EFI_QUESTION_ID QuestionId;
EFI_GUID FormSetId;
EFI_STRING_ID DevicePath;
} EFI_IFR_REF4;

typedef struct _EFI_IFR_REF5 {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
} EFI_IFR_REF5;
其实现中有如下的代码:

//
// Cacluate OpCodeSize based on the input Ref value.
// Try to use the small OpCode to save size.
//
OpCodeSize = sizeof (EFI_IFR_REF);
if (RefDevicePath != 0) {
OpCodeSize = sizeof (EFI_IFR_REF4);
} else if (RefFormSetId != NULL) {
OpCodeSize = sizeof (EFI_IFR_REF3);
} else if (RefQuestionId != 0) {
OpCodeSize = sizeof (EFI_IFR_REF2);
}

从这里可以看到指定了不同的操作码。

HiiCreateGuidOpCode
函数原型:

/**
Create EFI_IFR_GUID opcode.

If OpCodeHandle is NULL, then ASSERT().
If Guid is NULL, then ASSERT().
If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().

@param[in] OpCodeHandle Handle to the buffer of opcodes.
@param[in] Guid Pointer to EFI_GUID of this guided opcode.
@param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an
optional parameter that may be NULL. If this
parameter is NULL, then the GUID extension
region of the created opcode is filled with zeros.
If this parameter is not NULL, then the GUID
extension region of GuidData will be copied to
the GUID extension region of the created opcode.
@param[in] OpCodeSize The size, in bytes, of created opcode. This value
must be >= sizeof(EFI_IFR_GUID).

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateGuidOpCode (
IN VOID *OpCodeHandle,
IN CONST EFI_GUID *Guid,
IN CONST VOID *GuidOpCode, OPTIONAL
IN UINTN OpCodeSize
)

创建EFI_IFR_GUID操作码,它是现有的GUID的扩展,本身包含不同的格式,通过一个GUID来标识,现有的有gEfiIfrTianoGuid,它包含的格式有:

///
/// EDKII implementation extension opcodes, new extension can be added here later.
///
#define EFI_IFR_EXTEND_OP_LABEL 0x0
#define EFI_IFR_EXTEND_OP_BANNER 0x1
#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2
#define EFI_IFR_EXTEND_OP_CLASS 0x3
#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4

下面是创建一个LABLE的示例:

//
// Create Hii Extend Label OpCode.
//
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
StartOpCodeHandle,
&gEfiIfrTianoGuid,
NULL,
sizeof (EFI_IFR_GUID_LABEL)
);

参数说明:

OpCodeHandle:对应容纳操作码的HII_LIB_OPCODE_BUFFER结构体;
HiiCreateOneOfOpCode
函数原型:

/**
Create EFI_IFR_ONE_OF_OP opcode.

If OpCodeHandle is NULL, then ASSERT().
If any reserved bits are set in QuestionFlags, then ASSERT().
If any reserved bits are set in OneOfFlags, then ASSERT().

@param[in] OpCodeHandle Handle to the buffer of opcodes.
@param[in] QuestionId Question ID
@param[in] VarStoreId Storage ID
@param[in] VarOffset Offset in Storage or String ID of the name (VarName)
for this name/value pair.
@param[in] Prompt String ID for Prompt
@param[in] Help String ID for Help
@param[in] QuestionFlags Flags in Question Header
@param[in] OneOfFlags Flags for oneof opcode
@param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.
@param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This
is an optional parameter that may be NULL.

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateOneOfOpCode (
IN VOID *OpCodeHandle,
IN EFI_QUESTION_ID QuestionId,
IN EFI_VARSTORE_ID VarStoreId,
IN UINT16 VarOffset,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 QuestionFlags,
IN UINT8 OneOfFlags,
IN VOID *OptionsOpCodeHandle,
IN VOID *DefaultsOpCodeHandle OPTIONAL
)

创建EFI_IFR_ONE_OF操作码,它表示的是select-one-of question,其实就是单选框,比如Front Page中的语言选择框:

其对应的结构体:

typedef struct _EFI_IFR_ONE_OF {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question; // 单选框结构体中的EFI_IFR_QUESTION_HEADER
UINT8 Flags;
MINMAXSTEP_DATA data;
} EFI_IFR_ONE_OF;

下面是一个示例:

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
);

参数说明:

OpCodeHandle:应该是上一层操作码对应的HII_LIB_OPCODE_BUFFER结构体;
QuestionId:其实是一个UINT16类型的数值,它是一个在当前驱动唯一的值,通过它回调函数(由EFI_HII_ACCESS_FORM_CALLBACK声明)就能够知道需要处理的数据具体是哪个;(UEFI规范中的说明:A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. The format of the data tends to vary based on the opcode that generated the callback. )
EFI_HII_ACCESS_FORM_CALLBACK回调函数的声明如下:

/**

This function is called to provide results data to the driver.
This data consists of a unique key that is used to identify
which data is either being passed back or being asked for.

@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param Action Specifies the type of action taken by the browser.
@param QuestionId A unique value which is sent to the original
exporting driver so that it can identify the type
of data to expect. The format of the data tends to
vary based on the opcode that generated the callback.
@param Type The type of value for the question.
@param Value A pointer to the data being sent to the original
exporting driver.
@param ActionRequest On return, points to the action requested by the
callback function.

@retval EFI_SUCCESS The callback successfully handled the action.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be saved.
@retval EFI_UNSUPPORTED The specified Action is not supported by the
callback.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_ACCESS_FORM_CALLBACK)(
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN EFI_BROWSER_ACTION Action,
IN EFI_QUESTION_ID QuestionId,
IN UINT8 Type,
IN OUT EFI_IFR_TYPE_VALUE *Value,
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
);

它是EFI_HII_CONFIG_ACCESS_PROTOCOL的接口。

VarStoreId/VarOffset:这里通过一个ID指定对应的变量,通过Offset指定对应的成员,对该操作码的修改就对应的变量;如果没有变量与之对应,就直接写0就可以了;
Prompt:对应显示;
Help:对应操作的帮助;
QuestionFlags:表示选项的属性,比如只读、回调,等等,对应的值如下所示:
//
// Flag values of EFI_IFR_QUESTION_HEADER
//
#define EFI_IFR_FLAG_READ_ONLY 0x01
#define EFI_IFR_FLAG_CALLBACK 0x04
#define EFI_IFR_FLAG_RESET_REQUIRED 0x10
#define EFI_IFR_FLAG_REST_STYLE 0x20
#define EFI_IFR_FLAG_RECONNECT_REQUIRED 0x40
#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80

EFI_IFR_QUESTION_HEADER在不少操作码都存在,比如这里创建的单选框(见结构体中的Question成员)就有,其结构体:

typedef struct _EFI_IFR_QUESTION_HEADER {
EFI_IFR_STATEMENT_HEADER Header;
EFI_QUESTION_ID QuestionId;
EFI_VARSTORE_ID VarStoreId;
union {
EFI_STRING_ID VarName;
UINT16 VarOffset;
} VarStoreInfo;
UINT8 Flags; // 对应QuestionFlags
} EFI_IFR_QUESTION_HEADER;

OneOfFlags:单选框的Flags,有如下的值:
//
// Flags related to the numeric question
//
#define EFI_IFR_NUMERIC_SIZE 0x03
#define EFI_IFR_NUMERIC_SIZE_1 0x00
#define EFI_IFR_NUMERIC_SIZE_2 0x01
#define EFI_IFR_NUMERIC_SIZE_4 0x02
#define EFI_IFR_NUMERIC_SIZE_8 0x03

#define EFI_IFR_DISPLAY 0x30
#define EFI_IFR_DISPLAY_INT_DEC 0x00
#define EFI_IFR_DISPLAY_UINT_DEC 0x10
#define EFI_IFR_DISPLAY_UINT_HEX 0x20

它表示的意义目前有两种,第一种表示值的类型,第二种表示显示的格式;

OptionsOpCodeHandle:表示单选框操作码本身,它里面通常还需要包含EFI_IFR_ONE_OF_OPTION_OP操作码,表示单选框中的子选项;
DefaultsOpCodeHandle:表示默认显示的单选框子选项;
关于子选项,见HiiCreateOneOfOptionOpCode。

HiiCreateOneOfOptionOpCode
函数原型:

/**
Create EFI_IFR_ONE_OF_OPTION_OP opcode.

If OpCodeHandle is NULL, then ASSERT().
If Type is invalid, then ASSERT().
If Flags is invalid, then ASSERT().

@param[in] OpCodeHandle Handle to the buffer of opcodes.
@param[in] StringId StringId for the option
@param[in] Flags Flags for the option
@param[in] Type Type for the option
@param[in] Value Value for the option

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateOneOfOptionOpCode (
IN VOID *OpCodeHandle,
IN UINT16 StringId,
IN UINT8 Flags,
IN UINT8 Type,
IN UINT64 Value
)

创建的操作码对应的结构体:

typedef struct _EFI_IFR_ONE_OF_OPTION {
EFI_IFR_OP_HEADER Header;
EFI_STRING_ID Option;
UINT8 Flags;
UINT8 Type;
EFI_IFR_TYPE_VALUE Value;
} EFI_IFR_ONE_OF_OPTION;

HiiCreateSubTitleOpCode
函数原型:

/**
Create EFI_IFR_SUBTITLE_OP opcode.

If OpCodeHandle is NULL, then ASSERT().
If any reserved bits are set in Flags, then ASSERT().
If Scope > 1, then ASSERT().

@param[in] OpCodeHandle Handle to the buffer of opcodes.
@param[in] Prompt String ID for Prompt
@param[in] Help String ID for Help
@param[in] Flags Subtitle opcode flags
@param[in] Scope 1 if this opcode is the beginning of a new scope.
0 if this opcode is within the current scope.

@retval NULL There is not enough space left in Buffer to add the opcode.
@retval Other A pointer to the created opcode.

**/
UINT8 *
EFIAPI
HiiCreateSubTitleOpCode (
IN VOID *OpCodeHandle,
IN EFI_STRING_ID Prompt,
IN EFI_STRING_ID Help,
IN UINT8 Flags,
IN UINT8 Scope
)

创建的操作码对应的结构体:

typedef struct _EFI_IFR_SUBTITLE {
EFI_IFR_OP_HEADER Header;
EFI_IFR_STATEMENT_HEADER Statement;
UINT8 Flags;
} EFI_IFR_SUBTITLE;

字符串操作
HiiGetString
函数原型:

/**
Retrieves a string from a string package in a specific language specified in Language
or in the best lanaguage. See HiiGetStringEx () for the details.

@param[in] HiiHandle A handle that was previously registered in the HII Database.
@param[in] StringId The identifier of the string to retrieved from the string
package associated with HiiHandle.
@param[in] Language The language of the string to retrieve. If this parameter
is NULL, then the current platform language is used. The
format of Language must follow the language format assumed
the HII Database.

@retval NULL The string specified by StringId is not present in the string package.
@retval Other The string was returned.

**/
EFI_STRING
EFIAPI
HiiGetString (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_STRING_ID StringId,
IN CONST CHAR8 *Language OPTIONAL
);

这个函数用来获取字符串,字符串通过Language来确定语种,StringId确定使用哪个字段,这个字段定义在uni文件中,而uni文件通过函数HiiAddPackages()安装,下面是一个例子(来自MdeModulePkg\Application\UiApp\UiApp.inf):

//
// Publish our HII data
//
gFrontPagePrivate.HiiHandle = HiiAddPackages (
&mFrontPageGuid,
gFrontPagePrivate.DriverHandle,
FrontPageVfrBin,
UiAppStrings,
NULL
);

UiAppStrings是一个中间文件(AutoGen.c)中定义的变量,在Build目录中生成,它的名字来自inf中设置的MODULE_UNI_FILE:

MODULE_UNI_FILE = UiApp.uni
1
两者的关系是uni文件去掉后缀并加上Strings就得到的用在HiiAddPackages()中的变量。不过模块中的uni文件并不需要都是这个名字,可以有多个不同名的uni文件。

下面是使用HiiGetString()的一个例子:

//
// Update default banner string.
//
NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_LEFT), NULL);

STR_CUSTOMIZE_BANNER_LINE4_LEFT就是在某个uni文件(FrontPageStrings.uni)中定义的(目前是空的):

#string STR_CUSTOMIZE_BANNER_LINE4_LEFT #language en-US “”
#language fr-FR “”

而gFrontPagePrivate.HiiHandle是使用HiiAddPackages()安装时的返回值。

HiiSetString
函数原型:

/**
This function creates a new string in String Package or updates an existing
string in a String Package. If StringId is 0, then a new string is added to
a String Package. If StringId is not zero, then a string in String Package is
updated. If SupportedLanguages is NULL, then the string is added or updated
for all the languages that the String Package supports. If SupportedLanguages
is not NULL, then the string is added or updated for the set of languages
specified by SupportedLanguages.

If HiiHandle is NULL, then ASSERT().
If String is NULL, then ASSERT().

@param[in] HiiHandle A handle that was previously registered in the
HII Database.
@param[in] StringId If zero, then a new string is created in the
String Package associated with HiiHandle. If
non-zero, then the string specified by StringId
is updated in the String Package associated
with HiiHandle.
@param[in] String A pointer to the Null-terminated Unicode string
to add or update in the String Package associated
with HiiHandle.
@param[in] SupportedLanguages A pointer to a Null-terminated ASCII string of
language codes. If this parameter is NULL, then
String is added or updated in the String Package
associated with HiiHandle for all the languages
that the String Package supports. If this
parameter is not NULL, then String is added
or updated in the String Package associated with
HiiHandle for the set of languages specified by
SupportedLanguages. The format of
SupportedLanguages must follow the language
format assumed in the HII Database.

@retval 0 The string could not be added or updated in the String Package.
@retval Other The EFI_STRING_ID of the newly added or updated string.

**/
EFI_STRING_ID
EFIAPI
HiiSetString (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_STRING_ID StringId, OPTIONAL
IN CONST EFI_STRING String,
IN CONST CHAR8 *SupportedLanguages OPTIONAL
);

这个函数在字符串资源中新增或者字符串。StringId如果是0表示新增,否则就表示修改原有的字符串。

Form操作
HiiUpdateForm
用于更新界面结构,函数原型:

EFI_STATUS
EFIAPI
HiiUpdateForm (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_GUID *FormSetGuid, OPTIONAL
IN EFI_FORM_ID FormId,
IN VOID *StartOpCodeHandle,
IN VOID *EndOpCodeHandle OPTIONAL
)

这里的HiiHandle就是HiiAddPackages()添加元素数据之后的返回值:

gFrontPagePrivate.HiiHandle = HiiAddPackages (
&mFrontPageGuid,
gFrontPagePrivate.DriverHandle,
FrontPageVfrBin,
UiAppStrings,
NULL
);

FormSetGuid是HiiAddPackages()中的第一个参数,即mFrontPageGuid。

FormId是定义在vfr文件中:

form formid = FRONT_PAGE_FORM_ID,
1
StartOpCodeHandle和EndOpCodeHandle由HiiAllocateOpCodeHandle()创建。

相关内容

热门资讯

安卓13系统更新蓝牙,蓝牙功能... 你有没有发现,最近你的安卓手机好像变得不一样了?没错,就是那个神秘的安卓13系统更新,它悄悄地来到了...
安卓系统钉钉打开声音,安卓系统... 你有没有遇到过这种情况?手机里装了钉钉,可每次打开它,那声音就“嗖”地一下跳出来,吓你一跳。别急,今...
理想汽车操作系统安卓,基于安卓... 你有没有想过,一辆汽车,除了能带你去你想去的地方,还能像智能手机一样,给你带来智能化的体验呢?没错,...
安卓系统越狱还能升级吗,升级之... 你有没有想过,你的安卓手机越狱后,还能不能愉快地升级系统呢?这可是不少手机爱好者关心的大问题。今天,...
安卓系统蓝牙耳机拼多多,畅享无... 你有没有发现,最近蓝牙耳机在市场上可是火得一塌糊涂呢!尤其是安卓系统的用户,对于蓝牙耳机的要求那可是...
安卓变苹果系统桌面,桌面系统变... 你知道吗?最近有个大新闻在科技圈里炸开了锅,那就是安卓用户纷纷转向苹果系统桌面。这可不是闹着玩的,这...
鸿蒙系统怎么下安卓,鸿蒙系统下... 你有没有想过,你的手机里那个神秘的鸿蒙系统,竟然也能和安卓世界来一场亲密接触呢?没错,今天就要来揭秘...
手机安卓系统流程排行,便捷操作... 你有没有发现,现在手机的世界里,安卓系统就像是个大舞台,各种版本层出不穷,让人眼花缭乱。今天,就让我...
安卓系统左上角hd,左上角HD... 你有没有发现,每次打开安卓手机,左上角那个小小的HD标识总是默默地在那里,仿佛在诉说着什么?今天,就...
安卓系统软件文件,架构解析与功... 你有没有发现,手机里的安卓系统软件文件就像是一个神秘的宝库,里面藏着无数的宝藏?今天,就让我带你一起...
安卓系统输入法回车,探索安卓输... 你有没有发现,在使用安卓手机的时候,输入法回车键的奇妙之处?它就像是我们指尖的魔法师,轻轻一点,文字...
安卓修改系统时间的软件,轻松掌... 你有没有想过,有时候手机上的时间不对劲,是不是觉得生活节奏都被打乱了?别急,今天就来给你揭秘那些神奇...
安卓系统能改成鸿蒙吗,系统迁移... 你有没有想过,你的安卓手机能不能变成一个鸿蒙系统的“小清新”呢?这可不是天方夜谭哦,今天就来聊聊这个...
安卓机怎么从新装系统,从零开始... 亲爱的安卓手机用户们,你是否在某个瞬间突然觉得手机卡顿得像个老古董,急需给它来个“大变身”?别急,今...
安卓手机安装Linux双系统,... 你有没有想过给你的安卓手机来个变身大法?没错,就是安装Linux双系统!想象一边是流畅的安卓,一边是...
安卓系统关闭更新补丁,轻松提升... 亲爱的手机用户们,你们有没有发现,最近你的安卓手机好像有点儿“懒”了呢?更新补丁的速度明显慢了下来,...
麒麟os是不是安卓系统,揭秘与... 最近手机圈里可是热闹非凡呢!不少朋友都在问我:“麒麟OS是不是安卓系统?”这个问题可真是让人好奇,咱...
安卓系统卸载快应用,安卓系统轻... 你有没有发现,手机里的应用越来越多,有时候真的让人眼花缭乱呢?尤其是安卓系统里的那些“快应用”,虽然...
安卓14系统更新包,全新功能与... 你知道吗?最近安卓系统又来了一次大变身,那就是安卓14系统更新包!这可不是一个小打小闹的更新,而是满...
oppo安卓11.1系统新功能... 你知道吗?最近OPPO手机又来了一次大升级,安卓11.1系统的新功能简直让人眼前一亮!今天,就让我带...