72. label 키워드를 이용하여 HII 양식에 동적 요소 추가하기

이 장을 통해 아래 항목을 표시하는데 이용할 수 있다.

  • 현재 가능한 부팅 소스

  • 현재 존재하는 PCI 장치

  • 현재 메모리 정보

  • ...

이러한 것들은 UEFI 부트 프로세스에서 결정되고 하드웨어 장비 구성에 따른 부팅마다 다를 수 있다. 따라서 이러한 정보를 HII 양식에 추가하려면 동적으로 수행할 필요가 있다.

이 작업을 위해서 EDKII의 lable 메커니즘을 이용할 것이다.

그 전에 먼저 간단하게 빈 양식으로 저장소를 사용하지 않는 HIIFormLabel 애플리케이션을 생성해보자.

Initial code

아래는 빈 양식을 추가하는 드라이버 코드이다.

UefiLessonsPkg/HIIFormLabel/HIIFormLabel.inf:

[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = HIIFormLabel
  FILE_GUID                      = a869c42c-fd49-469d-b6ab-b37569c0e90d
  MODULE_TYPE                    = UEFI_DRIVER
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = HIIFormLabelEntryPoint
  UNLOAD_IMAGE                   = HIIFormLabelUnload

[Sources]
  HIIFormLabel.c
  Strings.uni
  Form.vfr

[Packages]
  MdePkg/MdePkg.dec
  MdeModulePkg/MdeModulePkg.dec

[LibraryClasses]
  UefiDriverEntryPoint
  UefiLib
  HiiLib

UefiLessonsPkg/HIIFormLabel/HIIFormLabel.c:

#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/HiiLib.h>
#include "Data.h"

#include <Guid/MdeModuleHii.h>

extern UINT8 FormBin[];

EFI_HII_HANDLE  mHiiHandle = NULL;


EFI_STATUS
EFIAPI
HIIFormLabelUnload (
  EFI_HANDLE ImageHandle
  )
{
  if (mHiiHandle != NULL)
    HiiRemovePackages(mHiiHandle);

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
HIIFormLabelEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  mHiiHandle = HiiAddPackages(
                 &gEfiCallerIdGuid,
                 NULL,
                 HIIFormLabelStrings,
                 FormBin,
                 NULL
                 );
  if (mHiiHandle == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  return EFI_SUCCESS;

UefiLessonsPkg/HIIFormLabel/Data.h:

#ifndef _DATA_H_
#define _DATA_H_

#define FORMSET_GUID  {0x29caf8e0, 0x2788, 0x4e1c, {0xb6, 0x15, 0x5b, 0xf8, 0x2f, 0x06, 0x7a, 0xa5}}

#endif

UefiLessonsPkg/HIIFormLabel/Form.vfr:

#include "Data.h"

formset
  guid     = FORMSET_GUID,
  title    = STRING_TOKEN(FORMSET_TITLE),
  help     = STRING_TOKEN(FORMSET_HELP),
  form
    formid = 1,
    title = STRING_TOKEN(FORMID1_TITLE);
  endform;
endformset;

UefiLessonsPkg/HIIFormLabel/Strings.uni:

#langdef en-US "English"

#string FORMSET_TITLE          #language en-US  "Simple Formset"
#string FORMSET_HELP           #language en-US  "This is a very simple formset"
#string FORMID1_TITLE          #language en-US  "Simple Form"

해당 코드를 빌드한 결과이다.

Add label

이제 위 양식에 동적인 콘텐츠를 추가해보자.

UefiLessonsPkg/HIIFormDataElements/Form.vfr 내부에 2개의 label 요소를 추가한다.

formset
  guid     = FORMSET_GUID,
  title    = STRING_TOKEN(FORMSET_TITLE),
  help     = STRING_TOKEN(FORMSET_HELP),
  form
    formid = 1,
    title = STRING_TOKEN(FORMID1_TITLE);

    label LABEL_START;
    label LABEL_END;
  endform;
endformset;

이 두 요소는 동적 콘텐츠를 위해 시작과 끝 영역을 정의한다.

LABEL_STARTLABEL_ENDUINT16의 숫자 값을 가진다. UefiLessonsPkg/HIIFormDataElements/Data.h 에 아래처 정의를 작성한다.

#define LABEL_START 0x1111
#define LABEL_END   0x2222

실제 label 번호는 중요하지 않지만 해당 label 번호는 반드시 대상 양식 범위 내에서 고유한 번호여야 한다.

IFR

모듈을 빌드하고 IFR 코드를 살펴보자. Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIFormDataElements/HIIFormDataElements/DEBUG/Form.lst:

   label 0x1111;
>00000117: 5F 15 35 17 0B 0F A0 87 93 41 B2 66 53 8C 38 AF 48 CE 00 11 11
    label 0x2222;
>0000012C: 5F 15 35 17 0B 0F A0 87 93 41 B2 66 53 8C 38 AF 48 CE 00 22 22

Label들은 EFI_IFR_GUID_OP opcode로 인코딩 되어졌다. 해당 opcode는 vendor가 UEFI 스펙에 정의되지 않은 새로운 IFR opcode를 추가할 수 있도록 돕는다. 이는 UEFI 스펙의 확장을 위한 수단이다.

EFI_IFR_GUID

Summary:
A GUIDed operation. This op-code serves as an extensible op-code which can be defined by the Guid value to have various functionality. It should be noted that IFR browsers or scripts which cannot interpret the meaning of this GUIDed op-code will skip it.

Prototype:

#define EFI_IFR_GUID_OP 0x5F

typedef struct _EFI_IFR_GUID {
 EFI_IFR_OP_HEADER Header;
 EFI_GUID Guid;
//Optional Data Follows
} EFI_IFR_GUID;

Parameters:
Header	The sequence that defines the type of opcode as well as the length of the opcode being defined.
	For this tag, Header.OpCode = EFI_IFR_GUID_OP
Guid 	The GUID value for this op-code. This field is intended to define a particular type of special-purpose function,
	and the format of the data which immediately follows the Guid field (if any) is defined by that particular GUID.

만약 binary의 데이터를 분석하면 이 경우 Guid가 다음과 같다는 것을 알 수 있다.

35 17 0B 0F A0 87 93 41 B2 66 53 8C 38 AF 48 CE

이 값은 opcode의 끝(Header.Length 에 의해 결정된다) 다음에 오는 나머지 모든 opcode 데이터의 모든 형식을 정의한다. 이 경우 00 11 11 또는 00 22 22 이다.\

IFR에 존재하는 GUID는 ./MdeModulePkg/MdeModulePkg.dec 에 정의되었다.

gEfiIfrTianoGuid      = { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce }}

./MdeModulePkg/Include/Guid/MdeModuleHii.h 내부에도 있다.

#define EFI_IFR_TIANO_GUID \
  { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }

EDKII에는 몇몇 특수한 IFR opcode가 있다. 이러한 것들은 모두 EFI_IFR_TIANO_GUID 아래에 정의되어 있다. GUID가 opcode를 정의하고 각 첫 번째 바이트를 서로 구분하기 위해 다음과 같이 정의한다.

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

우리의 경우는 다음 바이트는 EFI_IFR_EXTEND_OP_LABEL 에 해당하는 0x00 이다.

이렇게 전체 opcode는 다음 구조로 정의 된다.

///
/// Label opcode.
///
typedef struct _EFI_IFR_GUID_LABEL {
  EFI_IFR_OP_HEADER   Header;
  ///
  /// EFI_IFR_TIANO_GUID.
  ///
  EFI_GUID            Guid;			// EFI_IFR_TIANO_GUID
  ///
  /// EFI_IFR_EXTEND_OP_LABEL.
  ///
  UINT8               ExtendOpCode;		// EFI_IFR_EXTEND_OP_LABEL = 0x0
  ///
  /// Label Number.
  ///
  UINT16              Number;
} EFI_IFR_GUID_LABEL;

C code

C 코드의 콘텐츠를 label로 정의된 섹션에 추가하려면 HiiLib 에 존재하는 HiiUpdateForm 함수를 활용해야 한다. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Library/HiiLib.h

/**
  This function updates a form that has previously been registered with the HII
  Database.  This function will perform at most one update operation.
  The form to update is specified by Handle, FormSetGuid, and FormId.  Binary
  comparisons of IFR opcodes are performed from the beginning of the form being
  updated until an IFR opcode is found that exactly matches the first IFR opcode
  specified by StartOpCodeHandle.  The following rules are used to determine if
  an insert, replace, or delete operation is performed:
  1) If no matches are found, then NULL is returned.
  2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
     from StartOpCodeHandle except the first opcode are inserted immediately after
     the matching IFR opcode in the form to be updated.
  3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
     from the matching IFR opcode until an IFR opcode exactly matches the first
     IFR opcode specified by EndOpCodeHandle.  If no match is found for the first
     IFR opcode specified by EndOpCodeHandle, then NULL is returned.  If a match
     is found, then all of the IFR opcodes between the start match and the end
     match are deleted from the form being updated and all of the IFR opcodes
     from StartOpCodeHandle except the first opcode are inserted immediately after
     the matching start IFR opcode.  If StartOpCcodeHandle only contains one
     IFR instruction, then the result of this operation will delete all of the IFR
     opcodes between the start end matches.
  If HiiHandle is NULL, then ASSERT().
  If StartOpCodeHandle is NULL, then ASSERT().
  @param[in]  HiiHandle          The HII Handle of the form to update.
  @param[in]  FormSetGuid        The Formset GUID of the form to update.  This
                                 is an optional parameter that may be NULL.
                                 If it is NULL, all FormSet will be updated.
  @param[in]  FormId             The ID of the form to update.
  @param[in]  StartOpCodeHandle  An OpCode Handle that contains the set of IFR
                                 opcodes to be inserted or replaced in the form.
                                 The first IFR instruction in StartOpCodeHandle
                                 is used to find matching IFR opcode in the
                                 form.
  @param[in]  EndOpCodeHandle    An OpCcode Handle that contains the IFR opcode
                                 that marks the end of a replace operation in
                                 the form.  This is an optional parameter that
                                 may be NULL.  If it is NULL, then the IFR
                                 opcodes specified by StartOpCodeHandle are
                                 inserted into the form.
  @retval EFI_OUT_OF_RESOURCES   Not enough memory resources are allocated.
  @retval EFI_NOT_FOUND          The following cases will return EFI_NOT_FOUND:
                                 1) The form specified by HiiHandle, FormSetGuid,
                                 and FormId could not be found in the HII Database.
                                 2) No IFR opcodes in the target form match the first
                                 IFR opcode in StartOpCodeHandle.
                                 3) EndOpCOde is not NULL, and no IFR opcodes in the
                                 target form following a matching start opcode match
                                 the first IFR opcode in EndOpCodeHandle.
  @retval EFI_SUCCESS            The matched form is updated by StartOpcode.
**/
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
  );

보다시피 이 함수에는 두 개의 opcode 핸들이 필요하다.

  • StartOpCodeHandle - 대체 section의 시작을 표시하는 IFR과 넣으려고 하는 모든 opcode를 포함하는 opcode 버퍼에 대한 핸들,

  • EndOpCodeHandle - 대체 section의 끝을 표시하는 IFR을 포함하는 opcode 버퍼에 대한 핸들

이러한 OpCode 핸들을 생성하기 위해 HiiLib 의 특별한 함수를 살펴보자.

/**
  Allocates and returns a new OpCode Handle.  OpCode Handles must be freed with
  HiiFreeOpCodeHandle().
  @retval NULL   There are not enough resources to allocate a new OpCode Handle.
  @retval Other  A new OpCode handle.
**/
VOID *
EFIAPI
HiiAllocateOpCodeHandle (
  VOID
  );

여기서 중요한 점은 이 함수는 어떠한 크기도 허용하지 않는다는 점이다. 왜냐하면 이 작업에서 해당 buffer는 항상 고정이기 때문이다. HiiAllocateOpCodeHandle 은 다음과 같이 정의된 새로 할당되는 구조인 HII_LIB_OPCODE_BUFFER 에 대한 포인터를 반환한다.

#define HII_LIB_OPCODE_ALLOCATION_SIZE  0x200	// (=512)

typedef struct {
  UINT8    *Buffer;		// Pointer to newly allocated buffer of HII_LIB_OPCODE_ALLOCATION_SIZE bytes
  UINTN    BufferSize;
  UINTN    Position;
} HII_LIB_OPCODE_BUFFER;

모든 동적 할당되어진 opcode들은 사전에 할당된 버퍼 크기에 맞아야 한다.

물론 HiiAllocateOpCodeHandle 로 할당된 모든 버퍼를 해제해야 한다.

/**
  Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
  When an OpCode Handle is freed, all of the opcodes associated with the OpCode
  Handle are also freed.
  If OpCodeHandle is NULL, then ASSERT().
  @param[in]  OpCodeHandle   The handle to the buffer of opcodes.
**/
VOID
EFIAPI
HiiFreeOpCodeHandle (
  VOID  *OpCodeHandle
  );

따라서 만들 드라이버 내부에 다음과 같은 코드를 포함해야 한다.

VOID* StartOpCodeHandle = HiiAllocateOpCodeHandle();
VOID* EndOpCodeHandle = HiiAllocateOpCodeHandle();

<...>  // fill OpCode Handles


EFI_GUID formsetGuid = FORMSET_GUID;
EFI_STATUS Status = HiiUpdateForm(
                      mHiiHandle,
                      &formsetGuid,
                      0x1,
                      StartOpCodeHandle,
                      EndOpCodeHandle
                    );
if (EFI_ERROR(Status)) {
  Print(L"Error! HiiUpdateForm returned = %r\n", Status);
}

HiiFreeOpCodeHandle(StartOpCodeHandle);
HiiFreeOpCodeHandle(EndOpCodeHandle);
return Status;

이제 StartOpCodeHandleEndOpCodeHandle 에 올바른 데이터를 만들어야 한다. 첫번째로 우리는 lable IFR을 추가해야 한다. 이 작업은 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
  )

이 함수는 opcode 버퍼에 대한 포인터를 반환하는데 우리의 경우에는 EFI_IFR_GUID_LABEL opcode로 시작하는 버퍼가 된다. 따라서 버퍼를 EFI_IFR_GUID_LABEL 구조로 캐스팅하고 올바른 데이터로 채워야 한다. 만약 HiiCreateGuidOpCodeNULL 을 반환한다면 오류가 발생한 것이다.

EFI_IFR_GUID_LABEL* StartLabel = (EFI_IFR_GUID_LABEL*) HiiCreateGuidOpCode(StartOpCodeHandle,
                                                                           &gEfiIfrTianoGuid,
                                                                           NULL,
                                                                           sizeof(EFI_IFR_GUID_LABEL)
                                                                           );
if (StartLabel == NULL) {
  Print(L"Error! Can't create StartLabel opcode, not enough space\n");
  HiiRemovePackages(mHiiHandle);
  return EFI_BUFFER_TOO_SMALL;
}
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartLabel->Number = LABEL_START;


EFI_IFR_GUID_LABEL* EndLabel = (EFI_IFR_GUID_LABEL*) HiiCreateGuidOpCode(EndOpCodeHandle,
                                                                         &gEfiIfrTianoGuid,
                                                                         NULL,
                                                                         sizeof(EFI_IFR_GUID_LABEL)
                                                                         );
if (EndLabel == NULL) {
  Print(L"Error! Can't create Text opcode, not enough space\n");
  HiiFreeOpCodeHandle(StartOpCodeHandle);
  HiiRemovePackages(mHiiHandle);
  return EFI_BUFFER_TOO_SMALL;
}
EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
EndLabel->Number = LABEL_END;

이 코드에서 gEfiIfrTianoGuid 를 사용하므로 코드에 적절한 헤더 파일 정보(#include <Guid/MdeModuleHii.h>)와 *.inf 파일의 Guid 섹션에 정보를 추가해야 한다.

[Guids]
  gEfiIfrTianoGuid

마지막 작업은 IFR 코드에 새 코드를 포함하는 것이다. 따라서 우리는 Label 외에도 StartOpCodeHandle 이 참조하는 버퍼에 실제 새로운 IFR 코드를 추가해야 한다. HiiCreateTextOpcode 함수를 사용해 VFR text 요소를 추가해보자.

/**
  Create EFI_IFR_TEXT_OP opcode.
  If OpCodeHandle is NULL, 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]  TextTwo       String ID for TextTwo.
  @retval NULL   There is not enough space left in Buffer to add the opcode.
  @retval Other  A pointer to the created opcode.
**/
UINT8 *
EFIAPI
HiiCreateTextOpCode (
  IN VOID           *OpCodeHandle,
  IN EFI_STRING_ID  Prompt,
  IN EFI_STRING_ID  Help,
  IN EFI_STRING_ID  TextTwo
  );

보다시피 이 함수는 새 text 요소에 대해 EFI_STRING_ID 가 필요하다. 우리는 이 요소를 동적으로 생성하므로 HII 데이터베이스에 새 문자열도 동적으로 추가해보자.

/**
  This function create 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 then String is added
                                  or updated in the String Package associated with
                                  HiiHandle for the set oflanguages specified by
                                  SupportedLanguages.  The format of
                                  SupportedLanguages must follow the language
                                  format assumed 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
  )

이 함수를 이용하여 새로운 문자열을 다음과 같이 간단하게 만들 수 있다.

EFI_STRING_ID text_prompt = HiiSetString(mHiiHandle,
                                         0,
                                         L"Text prompt",
                                         NULL);
EFI_STRING_ID text_help = HiiSetString(mHiiHandle,
                                       0,
                                       L"Text help",
                                       NULL);

이제 HiiCreateTextOpCode 함수를 이용해 StartOpCodeHandle 이 참조하는 opcode 버퍼에 더 많은 opcode를 추가할 수 있다.

UINT8* Result = HiiCreateTextOpCode(StartOpCodeHandle,
                                    text_prompt,
                                    text_help,
                                    0);
if (Result == NULL) {
  Print(L"Error! Can't create Text opcode, not enough space\n");
  HiiFreeOpCodeHandle(StartOpCodeHandle);
  HiiFreeOpCodeHandle(EndOpCodeHandle);
  HiiRemovePackages(mHiiHandle);
  return EFI_BUFFER_TOO_SMALL;
}

예제에 또 다른 text 요소를 추가하기 위해 앞선 과정을 한번 더 반복한다.

text_prompt = HiiSetString(mHiiHandle,
                           0,
                           L"Another text prompt",
                           NULL);
text_help = HiiSetString(mHiiHandle,
                         0,
                         L"Another text help",
                         NULL);

Result = HiiCreateTextOpCode(StartOpCodeHandle,
                             text_prompt,
                             text_help,
                             0);
if (Result == NULL) {
  Print(L"Error! Can't create Text opcode, not enough space\n");
  HiiFreeOpCodeHandle(StartOpCodeHandle);
  HiiFreeOpCodeHandle(EndOpCodeHandle);
  HiiRemovePackages(mHiiHandle);
  return EFI_BUFFER_TOO_SMALL;
}

StartOpCodeHandleEndOpCodeHandle 이 채워졌기 때문에HiiUpdateForm 호출에 성공해야 한다. 드라이버를 빌드하고 로드해보자.

양식을 보면 의도한 대로 2개의 text 요소가 존재하는 것을 볼 수 있다.

HIICreate*

예제에서는 HiiCreateTextOpCode 함수만을 사용하여 text 요소(EFI_IFR_TEXT_OP)를 생성했었다. 하지만 HiiLib 에는 여러 종류의 요소를 생성하는 많은 함수가 존재한다. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Library/HiiLib.h https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/UefiHiiLib/HiiLib.c

HiiCreateSubTitleOpCode		EFI_IFR_SUBTITLE_OP
HiiCreateCheckBoxOpCode		EFI_IFR_CHECKBOX_OP
HiiCreateTextOpCode		EFI_IFR_TEXT_OP
HiiCreateNumericOpCode		EFI_IFR_NUMERIC_OP
HiiCreateStringOpCode		EFI_IFR_STRING_OP
HiiCreateDateOpCode		EFI_IFR_DATE_OP
HiiCreateTimeOpCode		EFI_IFR_TIME_OP
HiiCreateOneOfOpCode		EFI_IFR_ONE_OF_OP
HiiCreateOneOfOptionOpCode	EFI_IFR_ONE_OF_OPTION_OP
HiiCreateOrderedListOpCode	EFI_IFR_ORDERED_LIST_OP

HiiCreateDefaultOpCode		EFI_IFR_DEFAULT_OP
HiiCreateGuidOpCode		EFI_IFR_GUID
HiiCreateActionOpCode		EFI_IFR_ACTION_OP
HiiCreateGotoOpCode		EFI_IFR_REF_OP
HiiCreateGotoExOpCode		EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP
HiiCreateEndOpCode		EFI_IFR_END_OP

이 외에도 HiiLib 라이브러리에는 raw opcode 버퍼를 추가하는 함수도 있다.

/**
  Append raw opcodes to an OpCodeHandle.
  If OpCodeHandle is NULL, then ASSERT().
  If RawBuffer is NULL, then ASSERT();
  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
  @param[in]  RawBuffer      Buffer of opcodes to append.
  @param[in]  RawBufferSize  The size, in bytes, of Buffer.
  @retval NULL   There is not enough space left in Buffer to add the opcode.
  @retval Other  A pointer to the appended opcodes.
**/
UINT8 *
EFIAPI
HiiCreateRawOpCodes (
  IN VOID   *OpCodeHandle,
  IN UINT8  *RawBuffer,
  IN UINTN  RawBufferSize
  )

Last updated