지금까지는 폼을 HII 데이터베이스에 입력한 것과 동일한 애플리케이션에 표시했다. 그러나 지금까지 한 방식은 표준 방법이 아니다. 일반적으로 UEFI 드라이버는 HII 폼을 작성하고 다른 애플리케이션은 이를 로드한다. 실제 비휘발성 설정을 가진 더 복잡한 form을 생성해야 하기 때문에 이 두 가지 기능을 분리해야 한다.
따라서 아래의 2가지를 진행한다.
HII Form UEFI 애플리케이션을 UEFI 드라이버 폼으로 변환
HII 데이터베이스에서 작성된 HII 폼을 로드할 수 있는 애플리케이션 생성
DisplayHIIByGuid
두 번째 작업부터 진행하기 위해 DisplayHIIByGuid 애플리케이션을 생성한다.
UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.inf
/**
Convert a Null-terminated Unicode GUID string to a value of type
EFI_GUID.
...
If String is not aligned in a 16-bit boundary, then ASSERT().
@param String Pointer to a Null-terminated Unicode string.
@param Guid Pointer to the converted GUID.
@retval RETURN_SUCCESS Guid is translated from String.
@retval RETURN_INVALID_PARAMETER If String is NULL.
If Data is NULL.
@retval RETURN_UNSUPPORTED If String is not as the above format.
**/
RETURN_STATUS
EFIAPI
StrToGuid (
IN CONST CHAR16 *String,
OUT GUID *Guid
);
아래와 같이 사용하며 DisplayHIIByGuid.c에 작성한다.
if (Argc != 2) {
Print(L"Usage:\n");
Print(L" DisplayHIIByGuid <Package list GUID>\n");
return EFI_INVALID_PARAMETER;
}
EFI_GUID PackageListGuid;
EFI_STATUS Status = StrToGuid(Argv[1], &PackageListGuid);
if (Status != RETURN_SUCCESS) {
Print(L"Error! Can't convert <Package list GUID> argument to GUID\n");
return EFI_INVALID_PARAMETER;
}
/**
Retrieves the array of all the HII Handles or the HII handles of a specific
package list GUID in the HII Database.
This array is terminated with a NULL HII Handle.
This function allocates the returned array using AllocatePool().
The caller is responsible for freeing the array with FreePool().
@param[in] PackageListGuid An optional parameter that is used to request
HII Handles associated with a specific
Package List GUID. If this parameter is NULL,
then all the HII Handles in the HII Database
are returned. If this parameter is not NULL,
then zero or more HII Handles associated with
PackageListGuid are returned.
@retval NULL No HII handles were found in the HII database
@retval NULL The array of HII Handles could not be retrieved
@retval Other A pointer to the NULL terminated array of HII Handles
**/
EFI_HII_HANDLE *
EFIAPI
HiiGetHiiHandles (
IN CONST EFI_GUID *PackageListGuid OPTIONAL
)
;
HiiGetHiiHandles를 아래와 같이 간단하게 사용할 수 있으며 DisplayHIIByGuid.c에 작성한다.
이제 GUID와 연결된 HII 핸들 배열에 대한 포인터가 있다. SendForm을 호출하기 전에 이 배열의 길이를 알아야 한다. 아래 코드와 같이 HiiHandles 포인터를 복사해 NULL을 만날 때까지 반복문을 돌려 배열의 길이를 알아낸다.
아래 코드를 <...>에 작성한다.
EFI_FORM_BROWSER2_PROTOCOL.SendForm()
Summary:
Initialize the browser to display the specified configuration forms.
Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_SEND_FORM2) (
IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
IN EFI_HII_HANDLE *Handles,
IN UINTN HandleCount,
IN CONST EFI_GUID *FormsetGuid, OPTIONAL
IN EFI_FORM_ID FormId, OPTIONAL
IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
);
Parameters:
This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance.
Handles A pointer to an array of HII handles to display.
HandleCount The number of handles in the array specified by Handle.
FormsetGuid This field points to the EFI_GUID which must match the Guid field or one of the
elements of the ClassId field in the EFI_IFR_FORM_SET op-code. If FormsetGuid
is NULL, then this function will display the form set class
EFI_HII_PLATFORM_SETUP_FORMSET_GUID.
FormId This field specifies the identifier of the form within the form set to render as the first
displayable page. If this field has a value of 0x0000, then the Forms Browser will
render the first enabled form in the form set.
ScreenDimensions Points to recommended form dimensions, including any non-content area, in characters.
ActionRequested Points to the action recommended by the form.
Description:
This function is the primary interface to the Forms Browser. The Forms Browser displays the forms specified by FormsetGuid and FormId from all of HII handles specified by Handles. If more than one form can be displayed, the Forms Browser will provide some means for the user to navigate between the
forms in addition to that provided by cross-references in the forms themselves.
지금까지 함수를 호출할 때 FormsetGuid = NULL을 사용했다. 설명에서는 EFI_HII_PLATFORM_SETUP_FORMSET_GUID가 사용되었음을 의미한다.
또한 이전에 FormSet에 대해 classguid를 명시적으로 선언하지 않았을 때, IFR은 기본값으로 EFI_HII_PLATFORM_SETUP_FORMSET_GUID를 가진다는 것을 알아봤었다. 그래서 SendForm도 정상적으로 호출됐었던 것이다.
이전에 생성한 HIIStaticForm UEFI 애플리케이션의 복사본이 될 HIIStaticFormDriver Uefi 드라이버를 생성한다.
아래 스크립트를 코드를 이용해 생성한다.
#!/bin/bash### Copyright (c) 2021, Konstantin Aladyshev <aladyshev22@gmail.com>## SPDX-License-Identifier: MIT### This is a simple script that creates a basic structure for your new UEFI driver# Put this script in your edk2 folder and run it with 1 argument - your new driver nameDRIVER_NAME=${1}UUID=$(uuidgen)mkdir-pUefiLessonsPkg/${DRIVER_NAME}cat<<EOF>UefiLessonsPkg/${DRIVER_NAME}/${DRIVER_NAME}.inf[Defines] INF_VERSION = 1.25 BASE_NAME = ${DRIVER_NAME} FILE_GUID = ${UUID} MODULE_TYPE = UEFI_DRIVER VERSION_STRING = 1.0 ENTRY_POINT = ${DRIVER_NAME}EntryPoint UNLOAD_IMAGE = ${DRIVER_NAME}Unload[Sources] ${DRIVER_NAME}.c[Packages] MdePkg/MdePkg.dec[LibraryClasses] UefiDriverEntryPoint UefiLibEOFcat<<EOF>UefiLessonsPkg/${DRIVER_NAME}/${DRIVER_NAME}.c#include <Library/UefiBootServicesTableLib.h>#include <Library/UefiLib.h>EFI_STATUSEFIAPI${DRIVER_NAME}Unload ( EFI_HANDLE ImageHandle ){ return EFI_SUCCESS;}EFI_STATUSEFIAPI${DRIVER_NAME}EntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ){ return EFI_SUCCESS;}EOF