44. HII 데이터베이스 내부
먼저 HII 데이터베이스의 기본 구조를 살펴보자. https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
typedef struct _HII_DATABASE_PRIVATE_DATA {
UINTN Signature;
LIST_ENTRY DatabaseList;
LIST_ENTRY DatabaseNotifyList;
EFI_HII_FONT_PROTOCOL HiiFont;
EFI_HII_IMAGE_PROTOCOL HiiImage;
EFI_HII_IMAGE_EX_PROTOCOL HiiImageEx;
EFI_HII_STRING_PROTOCOL HiiString;
EFI_HII_DATABASE_PROTOCOL HiiDatabase;
EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRouting;
EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL ConfigKeywordHandler;
LIST_ENTRY HiiHandleList;
INTN HiiHandleCount;
LIST_ENTRY FontInfoList;
UINTN Attribute;
EFI_GUID CurrentLayoutGuid;
EFI_HII_KEYBOARD_LAYOUT *CurrentLayout;
} HII_DATABASE_PRIVATE_DATA;해당 구조에는 기본 HII 프로토콜에 대한 포인터가 포함되어 있다. 이러한 각 프로토콜은 HII의 다른 부분과의 상호작용을 담당한다. 예를 들어 하나는 HII 데이터베이스(EFI_HII_FONT_PROTOCOL)의 글꼴과의 상호 작용을 담당하고, 다른 하나는 이미지와의 상호 작용(EFI_HII_IMAGE_PROTOCOL/EFI_HII_IMAGE_EX_PROTOCOL)과 문자열(EFI_HII_STRING_PROTOCOL)과의 상호작용을 담당한다.
앞서 데이터베이스에서 HII 패키지를 추가/제거하는 EFI_HII_DATABASE_PROTOCOL 를 살펴보았기 때문에 다른 HII 요소들을 통해 이 프로토콜의 가능성을 더 살펴보자.
프로토콜 외에도 이 구조는 다른 요소에 대한 이중 연결 리스트를 유지한다. https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h
이러한 목록 중에는 데이터 베이스 레코드 LIST_ENTRY DatabaseList 에 대한 이중 연결 리스트가 있다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
LIST_ENTRY DatabaseList 는 첫번째 HII_DATABASE_RECORD 의 DatabaseEntry 필드를 가르킨다. 이 구조에서 DatabaseEntry 는 차례로 다음 HII_DATABASE_RECORD 의 DatabaseEntry 필드를 가르킨다.
각 데이터베이스 레코드에는 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList 가 존재한다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
각 이중 연결 리스트에는 이 패키지 목록에 있는 해당 유형의 패키지에 대한 포인터가 포함되어 있다. 이전 학습에서는 모든 패키지 목록과 해당 패키지를 연속 데이터 배열로 받았지만 이는 EFI_HII_DATABASE_PROTOCOL 의 ExportPackageLists 함수 기능일 뿐, HII 데이터는 플랫폼 메모리 전체에 분산 될 수 있는 이중 연결 리스트로 표현되어 있다.
HII_DATABASE_RECORD에 있는 또 다른 중요한 필드는 EFI_HII_HANDLE 핸들이다. 각 HII_DATABASE_RECORD 는 패키지 목록을 정의하고 EFI_HII_HANDLE 로 식별된다.
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h
하지만 GenerateHiiDatabaseRecord 함수 구현을 살펴보면 HII 핸들의 실제 구현을 볼 수 있다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
HII_HANDLE 타입의 정의는 다음과 같다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
Key 필드는 HII_DATABASE_PRIVATE_DATA 에 있는 HiiHandleCount 의 현재 값에 해당한다.
그리고 LIST_ENTRY Handle 은 시스템의 모든 HII_HANDLE 을 함께 연결하는데 도움이 된다. 중요한 점은 HII_DATABASE_PRIVATE_DATA 에 있는 LIST_ENTRY HiiHandleList 필드와 동일한 핸들 목록이다.
다음은 방금 다룬 HII 데이터 베이스 구조의 그림이다.

HII 데이터베이스 초기화
이 HII 데이터베이스 구조는 HiiDatabaseDxe 에서 정적 초기화 되었다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
HiiDatabaseDxe driver의 진입점은 linked lists(LIST_ENTRY)를 초기화하고 HII 데이버베이스의 모든 프로토콜을 시트템에 설치한다.
Linked lists 포인터
여기에 해당 필드에 대한 포인터로부터 구조체 포인터를 가져오는 전처리기 방법이 있다.
바로CR 매크로의 도움으로 DatabaseEntry 필드에 대한 포인터로 HII_DATABASE_RECORD 에 대한 포인터를 쉽게 얻는 것이다.
아래는CR 매크로에 대한 정의이다.
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h
그리고 BASE_CR 에 대한 정의는 다음과 같다.
https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Base.h
마지막으로로OFFSET_OF 에 대한 정의이다.
Last updated