57. VFR을 사용해 간단한 폼 생성 및 EFI_FORM_BROWSER2_PROTOCOL.SendForm()를 통해 화면에 폼 표시하기

HII의 주요 목적은 UEFI 설정을 제어하기 위해 사용자 구성 메뉴에 표시하는 것이다.

지금까지 HII 문자열과 HII 폰트에 대해서 알아보았다. 이제 모든 것을 하나로 묶는 HII 폼에 대해 알아본다.

HII 폼 패키지의 데이터는 IFR이 내부 폼 표현을 나타내는 특수 IFR 형식으로 인코딩된다. IFR은 사람이 읽을 수 있는 것이 아니기 때문에 직접 폼 패키지를 구성하는 것은 쉽지 않다. 일련의 작동 코드(opcode)로 파싱 프로세스가 매우 지루할 수 있다.

EDK2는 VFR이라는 특별한 사람이 사람 친화적인 언어로 HII 폼을 작성하는 방법을 제공한다. 여기서 VFR은 시각적 폼 표현 (내부 폼 표현의 반대)을 나타낸다. https://edk2-docs.gitbook.io/edk-ii-vfr-specification/ EDK2에는 IFR opcode로 VFR 코드를 C 배열로 변환하는 VfrCompile이라는 특수 유틸리티가 있다. https://github.com/tianocore/edk2/tree/master/BaseTools/Source/C/VfrCompile

HiiLib을 사용해 폼을 볼 수 있는 간단한 HIISimpleForm 애플리케이션을 생성한다.

UefiLessonsPkg/HIISimpleForm/HIISimpleForm.inf

[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = HIISimpleForm
  FILE_GUID                      = df2f1465-2bf1-492c-af6c-232ac40bdf82
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

[Sources]
  HIISimpleForm.c

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

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib
  HiiLib

UefiLessonsPkg/HIISimpleForm/HIISimpleForm.c

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

이제 vfr 파일을 생성한다.

VFR의 모든 항목은 formset 내에서 인코딩되어야 한다. 이 요소는 formset 키워드로 시작해서 endformset으로 끝나야 한다. formset을 구성할 때는 필수로 guid, title, help 총 3개의 필드가 있어야 한다.

이제 guid를 인코딩 할 수 있다.

또는 이전에 했던 것처럼 C 구문과 유사한 정의문으로 작성할 수 있다.

titlehelp 필드에는 문자열의 문자열 ID가 포함되어야 한다. 따라서 필요한 ID를 얻기 위해 STRING_TOKEN(...)를 사용하고 문자열 자체는 UNI 파일(UefiLessonsPkg/HIISimpleForm/Strings.uni)로 인코딩되어야 한다.

formset이 다른 formset에 포함되면 titlehelp 필드가 표시된다. 예를 들면 아래와 같다. https://github.com/tianocore/edk2/blob/master/OvmfPkg/PlatformDxe/PlatformForms.vfr

https://github.com/tianocore/edk2/blob/master/OvmfPkg/PlatformDxe/Platform.uni

vfr 파일과 uni 파일을 위와 같이 하면 아래와 같이 BIOS에서 내용을 확인할 수 있다.

VFR과 UNI 파일이 생겼으니 HII에 폼을 게시한다. UefiLessonsPkg/HIISimpleForm/HIISimpleForm.inf에 VFR과 UNI 파일을 추가한다.

HIISimpleForm.c 파일에도 HII 데이터베이스에 폼과 문자열을 채우는 코드를 작성한다.

코드에서 볼 수 있듯이 FormBin 배열을 사용하여 폼 데이터를 저장한다. EDKII 빌드 시스템은 모든 VFR 파일에서 HII 폼 패키지를 생성하고 데이터를 <VFR name>Bin 배열에 넣는다. UNI 파일과 마찬가지로 이 배열에는 4바이트 패키지 크기 헤더가 추가된다. 따라서 HiiAddPackages 라이브러리 함수를 그대 사용할 수 있다. 또한 이 배열은 *.h 파일이 아닌 자동 생성된 *.c 파일에 선언되므로 파일에 extern으로 선언해야 한다.

모듈을 빌드하고 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIISimpleForm/HIISimpleForm/DEBUG/Form.c를 확인하면 아래와 같이 생성된 배열을 볼 수 있다.

EDKII의 빌드 시스템은 *.c 파일 말고 다른 파일을 추가로 생성한다. Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIISimpleForm/HIISimpleForm/DEBUG/Form.lst

여기서 FormBin 배열의 PACKAGE DATA 부분이 IFR opcode에서 어떻게 구성되는지 확인할 수 있으며, 담당 VFR 코드와의 관계에 대한 몇 가지 설명을 확인할 수 있다.

IFR 데이터 파싱

데이터는 4개의 요소 EFI_IFR_FORM_SET, 2개의 EFI_IFR_DEFAULTSTORE과 EFI_IFR_END로 구성되어 있다. 이 요소들은 Form.lst에서 하나의 데이터 문자열을 가진다.

문자열 패키지와 마찬가지로 가능한 모든 구성 요소에는 공통 헤더가 있다.

아래는 EFI_IFR_FORM_SET의 정의다.

위에서 VFR에 클래스 guid를 선언하지 않았었다. 그러나 opcode 출력에서 IFR에 93039971-8545-4b04-b45e-32eb8326040e과 동일한 ClassGuid가 있는 것을 확인할 수 있었다. 기본적으로 클래스에 다른 GUID를 선언하지 않은 경우 기본적으로 빌드 시스템에 의해 할당된다. https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Guid/HiiPlatformSetupFormset.h

클래스에 대한 다른 GUID를 선언하려면 아래와 같은 VFR 구문을 사용한다.

다음으로 EFI_IFR_DEFAULTSTORE 요소를 살펴본다.

EFI_IFR_FORM_SET으로 시작했으므로 EFI_IFR_END로 끝내야 한다.

폼 보기

실제로 폼을 보이게 하려면 EFI_FORM_BROWSER2_PROTOCOLSendForm 함수를 사용해야 한다.

보다시피 대부분의 매개 변수는 선택 사항이다. 그래서 이 함수를 아래와 같이 단순하게 사용할 수 있다. HIISimpleFomr.c에 추가한다.

HIISimpleForm.inf 파일에 gEfiFormBrowser2ProtocolGuid를 추가한다.

FormBrowser2를 사용하기 위해 헤더 파일도 추가한다.

애플리케이션이 끝나면 HII 패키지가 더이상 필요하지 않으므로 제거해야 한다.

애플리케이션을 빌드하고 실행하면 Form Browser에 아무것도 표시되지 않고 즉시 Shell로 제어 권한을 반환한다. formset에 표시할 항목이 없기 때문이다. formset의 핵심 요소는 폼이므로 UefiLessonsPkg/HIISimpleForm/Form.vfr에 간단한 폼을 formset에 추가한다.

각 폼에는 최소 formidtitle이 있어야 한다. 이것들은 필수 필드라고 할 수 있고 title은 폼이 표시될 때 페이지 제목에 사용되며, formid는 다른 코드에서 폼을 참조하는데 사용된다.

또한 다른 모든 form 속성과 마찬가지로 별도의 문자열에 formid 속성을 작성할 수 있다.

그러나 일반적으로 formid는 폼 키워드와 동일한 문자열에 작성된다. 두 구문 모두 VFR에서 동일하다.

UefiLessonsPkg/HIISimpleForm/Strings.uni에 새 문자열을 작성한다.

다시 빌드 후 HIISimpleForm.efi를 실행하면 아래와 같은 결과를 확인할 수 있다.

HIISimpleForm.efi

IFR data parsing

Form.lst를 다시 확인하면 아래와 같다.

두 개의 IFR이 추가되었다. 먼저 EFI_IFR_FORM이다.

그러나 이 opcode가 다른 범위를 열면 EFI_IFR_END opcode가 더 있다.

Last updated