45. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 문자열 목록 게시
파트 1: 패키지 목록 데이터 생성의 일반적인 측면
지난 수업에서는 내부적으로 HII 데이터베이스가 패키지 목록과 해당 패키지를 연속적인 데이터 배열이 아닌 많은 이중 연결 리스트로 구현된 복잡한 데이터 구조로 저장되어 있다는 것을 발견했다.
하지만 EFI_HII_DATABASE_PROTOCOL 에서 ExportPackageLists 를 사용했을 때 패키지 목록과 해당 패키지의 연속 데이터 배열을 받을 수 있었다. 이는 HII 데이터베이스의 내부를 추상화하고 사용자 입장에서 분석하기 쉬운 형식으로 데이터를 제공하는 편리한 인터페이스라고 볼 수 있다.
EFI_HII_DATABASE_PROTOCOL 에서 NewPackageList 를 통해 패키지 목록을 데이터베이스에 추가하는 경우도 마찬가지이다. 이 함수는 동일한 형식의 연속적 데이터 배열에서 오는 패키지 목록을 예상한다.
EFI_HII_DATABASE_PROTOCOL.NewPackageList()
Summary:
Adds the packages in the package list to the HII database.
Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_NEW_PACK) (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
IN CONST EFI_HANDLE DriverHandle, OPTIONAL
OUT EFI_HII_HANDLE *Handle
);
Parameters:
This A pointer to the EFI_HII_DATABASE_PROTOCOL instance
PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure
DriverHandle Associate the package list with this EFI handle
Handle A pointer to the EFI_HII_HANDLE instance
Description This function adds the packages in the package list to the database and returns a handle. If there is a
EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will create a
package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
EFI_HII_STRING_PROTOCOL *gHiiString // UEFI HII String Protocol
EFI_HII_DATABASE_PROTOCOL *gHiiDatabase // UEFI HII Database Protocol
EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting // UEFI HII Config Routing Protocol
EFI_HII_FONT_PROTOCOL *gHiiFont // UEFI HII Font Protocol
EFI_HII_IMAGE_PROTOCOL *gHiiImage // UEFI HII Image Protocol
따라서 마지막 애플리케이션에서 아래 코드를 사용하는 대신에
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL* HiiDbProtocol;
Status = gBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid,
NULL,
(VOID**)&HiiDbProtocol);
if (EFI_ERROR(Status)) {
Print(L"ERROR: Could not find HII Database protocol: %r\n", Status);
return Status;
}
application의 *.inf 파일에 UefiHiiServicesLib 을 포함하고 gHiiDatabase 를 EFI_HII_DATABASE_PROTOCOL* 로 사용할 수 있다.
따라서 현재 application의 *.inf 파일에 UefiHiiServicesLib 를 Library classes section에 추가한다.
[LibraryClasses]
...
UefiHiiServicesLib
또한 application의 *.inf 에 이 라이브러리 패키지 *.dec 파일을 포함해야 한다.
[Packages]
...
MdeModulePkg/MdeModulePkg.dec
최종적으로 소스 코드에서 해당 헤더를 선언하여 사용한다.
#include <Library/UefiHiiServicesLib.h>
Application 코드 설명
아래 코드에서 패키지 목록의 크기를 계산하지 않기 때문에 약간의 트릭을 사용한다. 그리고 예시에서는 실제로 필요한 것보다 더 큰 숫자를 사용하고 있다.
이 장은 여러 파트로 분할되어 있으며 충분히 어렵기 때문에 이 이상의 어려움을 만들지 않고자 함을 미리 설명한다.
#include <Library/MemoryAllocationLib.h>
...
CHAR8* Data = (CHAR8*) AllocateZeroPool(200); // CHEAT! NEEDS CORRECTION FOR YOUR OWN PACKAGES!
UINT32 offset = 0;
EFI_HII_PACKAGE_LIST_HEADER* PackageListHdr = (EFI_HII_PACKAGE_LIST_HEADER*)&Data[offset];
PackageListHdr->PackageListGuid = gHIIStringsCGuid;
offset += sizeof(EFI_HII_PACKAGE_LIST_HEADER);
<...> // Fill String Packages in the memory starting from &Data[offset]
offset += <...> // Add packages size to the 'offset' variable
EFI_HII_PACKAGE_HEADER* HIIEndPackageHdr = (EFI_HII_PACKAGE_HEADER*)&Data[offset];
HIIEndPackageHdr->Type = EFI_HII_PACKAGE_END;
HIIEndPackageHdr->Length = sizeof(EFI_HII_PACKAGE_HEADER);
offset += sizeof(EFI_HII_PACKAGE_HEADER);
PackageListHdr->PackageLength = offset;
<...> // Add new package to the HII Database
FreePool(Data);