모든 작업을 완료하면 HIIStringsUNI 애플리케이션과 동일한 결과를 얻을 수 있다.
FS0:\> HIIStringsUNIRC.efi
en-US ID=1: English
en-US ID=2: Hello!
en-US ID=3: Bye!
fr-FR ID=1: Francais
fr-FR ID=2: Bonjour!
fr-FR ID=3: Au revoir!
Best language ID=1: English
Best language ID=2: Hello!
Best language ID=3: Bye!
fr ID=3: Au revoir!
이제 애플리케이션을 수정할 준비가 다 되었다.
UEFI_HII_RESOURCE_SECTION
UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.inf에 다음을 추가한다.
[Defines]
...
UEFI_HII_RESOURCE_SECTION = TRUE
UEFI_HII_RESOURCE_SECTION 플래그는 HII 리소스 섹션이 PE 이미지로 생성되는지 여부를 지정한다. 애플리케이션을 빌드하면 다음 오류로 인해 애플리케이션을 빌드할 수 없다.
UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.c:15:42: error: ‘HIIStringsUNIRCStrings’ undeclared (first use in this function);
Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC/DEBUG/HIIStringsUNIRCStrDefs.h를 보면 이 파일에 여전히 문자열 토큰이 포함되어 있지만 HIIStringsUNIRCStrings는 더 이상 여기에 존재하지 않는 것을 알 수 있다.
그리고 AutoGen.c 파일에는 더 이상 HIIStringsUNIRCStrings 배열 초기화 코드가 포함되어 있지 않다(Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC/DEBUG/AutoGen.c).
이제 우리의 문자열이 결과로 나오는 *.efi 이미지의 특수 섹션으로 인코딩되어 들어가는 것이다.
이를 우리가 얻으려면 애플리케이션 EFI_HANDLE ImageHandle에서 프로토콜 EFI_HII_PACKAGE_LIST_PROTOCOL을 검색해야 한다.
다음은 Shell이 모든 프로그램을 로드하는 데 사용하는 EFI_BOOT_SERVICES.LoadImage() 함수에 대한 UEFI 스펙의 관련 내용이다.
Once the image is loaded, LoadImage() installs EFI_HII_PACKAGE_LIST_PROTOCOL on the handle if
the image contains a custom PE/COFF resource with the type 'HII'. The protocol's interface pointer points
to the HII package list which is contained in the resource's data
우리의 INF 파일의 [Packages] 섹션에 MdeModulePkg/MdeModulePkg.dec가 이미 있으므로 이 GUID를 [Protocols] 섹션에 추가하기만 하면 된다.
[Protocols]
gEfiHiiPackageListProtocolGuid
코드에서는 OpenProtocol UEFI 부트 서비스의 도움으로 애플리케이션의 ImageHandle 에서 PackageList 프로토콜을 얻을 수 있다.
...EFI_STATUSEFIAPIUefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ){ EFI_STATUS Status; EFI_HII_PACKAGE_LIST_HEADER *PackageList;//// Retrieve HII package list from ImageHandle.// Status =gBS->OpenProtocol ( ImageHandle,&gEfiHiiPackageListProtocolGuid, (VOID **)&PackageList, ImageHandle,NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL );if (EFI_ERROR (Status)) {Print(L"Error! Can't open EFI_HII_PACKAGE_LIST_PROTOCOL\n");return Status; } ...
결과의 PackageList는 HIIStringsUNI 애플리케이션의 경우와 같이 StrGather 스크립트의 결과인 일부 size 헤더가 있는 문자열 패키지가 아니다. HIIStringsC 애플리케이션에서 수동으로 구성한 것과 같은 일반 PackageList이다. 따라서 HiiAddPackages 라이브러리 함수를 사용하는 대신 EFI_HII_DATABASE_PROTOCOL.NewPackageList()를 직접 사용해야 한다.
EFI_HII_HANDLE Handle;Status = gHiiDatabase->NewPackageList(gHiiDatabase, PackageList,NULL,&Handle);if (EFI_ERROR(Status)){Print(L"Can't register HII Package list %g, status = %r\n", gHIIStringsUNIRCGuid, Status);return Status;}
여기서는 gHiiDatabase를 사용했으므로 필요한 헤더인 #include <Library/UefiHiiServicesLib.h>를 추가하고 애플리케이션 INF 파일의 [LibraryClasses]에 UefiHiiServicesLib를 추가하는 것을 잊지 말자.
이제 애플리케이션을 빌드하고 실행해보면 모든 것이 정상인것을 확인할 수 있다.
FS0:\> HIIStringsUNIRC.efi
Status = Success
en-US ID=1: English
en-US ID=2: Hello!
en-US ID=3: Bye!
fr-FR ID=1: Francais
fr-FR ID=2: Bonjour!
fr-FR ID=3: Au revoir!
Best language ID=1: English
Best language ID=2: Hello!
Best language ID=3: Bye!
fr ID=3: Au revoir!
유형이 'HII'인 PE/COFF 리소스
objdump를 사용하여 애플리케이션 헤더를 살펴보자. -x 옵션을 사용하여 모든 헤더의 내용을 출력할 수 있다.