59. 간단한 폼 애플리케이션을 UEFI 드라이버 Form으로 변환하기

지금까지는 폼을 HII 데이터베이스에 입력한 것과 동일한 애플리케이션에 표시했다. 그러나 지금까지 한 방식은 표준 방법이 아니다. 일반적으로 UEFI 드라이버는 HII 폼을 작성하고 다른 애플리케이션은 이를 로드한다. 실제 비휘발성 설정을 가진 더 복잡한 form을 생성해야 하기 때문에 이 두 가지 기능을 분리해야 한다.

따라서 아래의 2가지를 진행한다.

  • HII Form UEFI 애플리케이션을 UEFI 드라이버 폼으로 변환

  • HII 데이터베이스에서 작성된 HII 폼을 로드할 수 있는 애플리케이션 생성

DisplayHIIByGuid

두 번째 작업부터 진행하기 위해 DisplayHIIByGuid 애플리케이션을 생성한다. UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.inf

[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = DisplayHIIByGuid
  FILE_GUID                      = 1597e1d0-7f62-4631-a166-703f03bd7223
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = ShellCEntryLib

[Sources]
  DisplayHIIByGuid.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiLib
  ShellCEntryLib

UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.c

UefiLessonsPkg/UefiLessonsPkg.dsc

애플리케이션은 명령 인자에서 HII 패키지 목록 GUID를 받아 그 패키지에서 HII 폼을 표시할 것이다.

먼저 인자로 들어오는 문자열을 GUID 값으로 변경해야 한다. 이를 위해StrToGuid 함수를 사용할 수 있다. https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/BaseLib.h

아래와 같이 사용하며 DisplayHIIByGuid.c에 작성한다.

이제 패키지 목록 GUID가 있으면 HiiGetHiiHandles 함수를 사용해 GUID에 대한 HII 핸들을 가져올 수 있다. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Library/HiiLib.h https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/UefiHiiLib/HiiLib.c

HiiGetHiiHandles를 아래와 같이 간단하게 사용할 수 있으며 DisplayHIIByGuid.c에 작성한다.

HiiLib 헤더 파일을 사용하기 때문에 INF 파일에 필요한 패키지와 라이브러리 클래스를 추가한다.

이제 GUID와 연결된 HII 핸들 배열에 대한 포인터가 있다. SendForm을 호출하기 전에 이 배열의 길이를 알아야 한다. 아래 코드와 같이 HiiHandles 포인터를 복사해 NULL을 만날 때까지 반복문을 돌려 배열의 길이를 알아낸다. 아래 코드를 <...>에 작성한다.

SendForm 함수를 사용하기 위해 EFI_FORM_BROWSER2_PROTOCOL에서 SendForm 함수를 호출해야 한다. 따라서 필요한 프로토콜과 헤더 파일을 추가한다.

UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.inf

UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.c

추가로 프로토콜을 호출하기 위해 아래 코드를 작성한다.

빌드 후 QEMU를 실행하여 DispalyHIIByGuid 애플리케이션을 실행하기 전에 기존에 만들었던 ShowHII 애플리케이션을 통해 HII 데이터베이스의 모든 패키지 목록 확인한다.

ShowHII 애플리케이션을 통해 GUID도 확인할 수 있으므로 이제 DisplayHIIByGuid를 실행할 수 있다.

여기서 확인한 GUID은 아래와 같다.

DisplayHIIByGuid.efi D9DCC5DF-4007-435E-9098-8970935504B2 명령어를 통해서는 아래와 같은 화면을 확인할 수 있다.

Formset: classguid

DisplayHIIByGuid.efi를 사용해 보았을 때 하나의 GUID가 작동하지 않는 다는 것을 알 수 있었다.

해당 GUID에 대한 내용은 아래 링크에서 확인할 수 있다.

EFI_FORM_BROWSER2_PROTOCOL.SendForm()을 다시 살펴본다.

지금까지 함수를 호출할 때 FormsetGuid = NULL을 사용했다. 설명에서는 EFI_HII_PLATFORM_SETUP_FORMSET_GUID가 사용되었음을 의미한다.

또한 이전에 FormSet에 대해 classguid를 명시적으로 선언하지 않았을 때, IFR은 기본값으로 EFI_HII_PLATFORM_SETUP_FORMSET_GUID를 가진다는 것을 알아봤었다. 그래서 SendForm도 정상적으로 호출됐었던 것이다.

그러나 문제가 있는 패키지 목록에서 폼의 VFR 코드를 보면 다른 classguid를 사용한다는 것을 알 수 있다. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/FileExplorerLib/FileExplorerVfr.vfr

패키지 목록에서 확인한 GUID와 EFI_FILE_EXPLORE_FORMSET_GUID는 같다.

문제를 해결하기 위해 *.c 코드를 수정해야 한다.

새로운 인자를 처리할 수 있는 코드를 추가한다.

SendForm을 호출하는 부분에서 FormsetClassGuid를 추가한다.

이제 아래 명령을 통해 정상 동작하는 것을 확인할 수 있다.

DisplayHIIByGuid.efi : File Explorer

HIIStaticFormDriver

이전에 생성한 HIIStaticForm UEFI 애플리케이션의 복사본이 될 HIIStaticFormDriver Uefi 드라이버를 생성한다.

아래 스크립트를 코드를 이용해 생성한다.

아래는 HIIStaticFormDriver*.c*.inf 파일이다.

UefiLessonsPkg/HIIStaticFormDriver/HIIStaticFormDriver.inf

UefiLessonsPkg/HIIStaticFormDriver/HIIStaticFormDriver.c

UefiLessonsPkg/UefiLessonsPkg.dsc에 INF 파일을 추가한다.

HIIStaticFormDriver를 빌드하고 로드한다.

드라이버를 로드하면 드라이버가 HII 데이터베이스에 데이터를 저장한 것을 볼 수 있다.

DisplayHIIByGuid.efi를 사용해 HII 데이터를 확인할 수 있다.

기본 UEFI 메뉴에서 애플리케이션 확인하기

exit 명령을 통해 UEFI 메뉴로 나간다.

Device Manager로 이동하면 Device ListStatic Formset이 있는 것을 확인할 수 있다.

해당 메뉴를 선택하면 만들었던 드라이버 폼인 것을 볼 수 있다.

classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID가 있는 모든 폼이 Device Manager에 추가된다.

따라서 폼에 다른 classguid를 사용하지 않으면 DisplayHIIByGuid.efi 애플리케이션을 사용하는 것보다 메뉴에서 폼을 확인하는 방법이 더 쉽다.

새 폼이 Device Manager에 동적으로 추가되는 방법이 궁금한 경우 아래 링크를 통해 확인한다. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c

아래 코드는 CompareGuid를 사용하여 모든 formset classguidEFI_HII_PLATFORM_SETUP_FORMSET_GUID와 비교하고 CompareGuidTrue를 반환하는 경우에만 진행되는 snippet 폼이다.

Last updated