46. EFI_HII_DATABASE_PROTOCOL의 NewPackageList를 사용하여 문자열 패키지가 포함된 HII 패키지 목록 게시
파트 2: 문자열 패키지 데이터 생성
문자열 패키지
문자열 패키지는 한 가지 언어로 된 문자열들의 집합이다. 패키지의 각 문자열은 ID를 통해 참조할 수 있다. 이러한 문자열에 대한 ID는 어디에도 기록되지 않지만 ID에 번호를 매길 때 모든 문자열 패키지에서 ID는 1부터 시작해서 모든 문자열에서 1씩 증가한다고 가정한다.(몇 가지 예외가 존재하지만 지금은 중요하지 않다.)
일반적으로 인터페이스에 대한 번역을 지원하고 싶을 때 지원하려는 각 언어에 대해 문자열 패키지를 만든다. 이러한 모든 언어 문자열 패키지에서 동일한 단어는 동일한 ID를 가져야 한다.
패키지 목록에서 코드 문자열은 (ID, language)조합으로 수신 된다. 이는 번역을 쉽게 전환할 수 있는 UI를 만드는 데 도움이 된다.
문자열 패키지 내용
문자열 패키지는 EFI_HII_STRING_PACKAGE_HDR라는 헤더로 시작되고 type이 여러개인 String blocks를 포함하고 있다. 그리고 패키지 목록과 마찬가지로 마지막 요소(=String block)에는 특별한 END type이 있다.
가장 중요하고 가장 일반적인 String 블록 type은 UCS2 String 블록이다. 블록 데이터로 문자열 블록 type을 가리키고 있는 헤더와 CHAR16 문자열을 가지고 있다. 기본적으로 문자열 패키지는 각각 하나의 문자열을 포함하는 UCS2 String 블록의 집합이다.
문자열 패키지 만들기
문자열 패키지의 헤더를 살펴보자.
Prototype:typedefstruct _EFI_HII_STRING_PACKAGE_HDR { EFI_HII_PACKAGE_HEADER Header; UINT32 HdrSize; UINT32 StringInfoOffset; CHAR16 LanguageWindow[16]; EFI_STRING_ID LanguageName; CHAR8 Language[ … ];} EFI_HII_STRING_PACKAGE_HDR;Members:Header The standard package header, where Header.Type = EFI_HII_PACKAGE_STRINGS.HdrSize Size of this header.StringInfoOffset Offset, relative to the start of this header, of the string information.LanguageWindow Specifies the default values placed in the static and dynamic windows before processing each SCSU-encoded string.LanguageName String identifier within the current string package of the full name of the language specified by Language.Language The null-terminated ASCII string that specifies the language of the strings in the package.
CHAR8 Language는 en-EN, en-US, en, ru-RU, ...와 같은 문자열이다. Language필드의 크기가 고정되어 있지 않기 때문에 EFI_HII_STRING_PACKAGE_HDR에는 전체 패키지 헤더 크기를 나타내는 HdrSize 필드가 있다.
이 짧은 형식 외에도 모든 문자열 패키지에는 전체 언어 이름(예: English) 문자열이 포함되며 LanguageName 필드가 이 문자열의 ID이다. 일반적으로 ID=1인 첫 번째 문자열이다.
이미 알고 있지만 문자열 패키지는 String Block으로 채워진다. 다양한 type이 있을 수 있지만 지금은 가장 중요한 type인 UCS2 String 블록과 End 블록을 조사해보려고 한다.
typedefstruct { UINT8 BlockType;} EFI_HII_STRING_BLOCK;//// Value of different string information block types//#defineEFI_HII_SIBT_END0x00...#defineEFI_HII_SIBT_STRING_UCS20x14...typedefstruct _EFI_HII_SIBT_STRING_UCS2_BLOCK { EFI_HII_STRING_BLOCK Header; CHAR16 StringText[1]; // <--- String size is not fixed, but to point a fact that this type of block has
} EFI_HII_SIBT_STRING_UCS2_BLOCK; // a string in itself, the header contains one element array
...typedefstruct _EFI_HII_SIBT_END_BLOCK { EFI_HII_STRING_BLOCK Header;} EFI_HII_SIBT_END_BLOCK;
이제 문자열에서 패키지 데이터 배열을 채울 수 있는 함수를 작성해보자.
UINT32 InitStringPackage(CHAR8* Ptr, CHAR8* Language, CHAR16** Strings, UINTN StringsLen):// CHAR8* Ptr - start of the array where we want our package data// CHAR8* Language - short language form for the `EFI_HII_STRING_PACKAGE_HDR.Language` field// CHAR16** Strings - array of CHAR16* Strings that would be written to the package// UINTN StringsLen - how many string there are in the Strings array//// Return UINT32 - function return the result package size
다음은 함수 구현이다.
UINT32 InitStringPackage(CHAR8* Ptr, CHAR8* Language, CHAR16** Strings, UINTN StringsLen){ UINT32 Size=0; EFI_HII_STRING_PACKAGE_HDR* HIIStringPackageHdr = (EFI_HII_STRING_PACKAGE_HDR*)&Ptr[0];HIIStringPackageHdr->Header.Type = EFI_HII_PACKAGE_STRINGS; UINT32 HeaderSize = (UINT32) (AsciiStrSize(Language)-1+sizeof (EFI_HII_STRING_PACKAGE_HDR));HIIStringPackageHdr->HdrSize = HeaderSize;HIIStringPackageHdr->StringInfoOffset = HeaderSize;HIIStringPackageHdr->LanguageName =1; // <--- the String[0] should be a full language name string!AsciiStrCpyS (HIIStringPackageHdr->Language, (HeaderSize - OFFSET_OF(EFI_HII_STRING_PACKAGE_HDR,Language)) /sizeof (CHAR8), Language);Size+= HeaderSize;for (UINTN i=0; i<StringsLen; i++) { EFI_HII_SIBT_STRING_UCS2_BLOCK* StrBlock = (EFI_HII_SIBT_STRING_UCS2_BLOCK*)&Ptr[Size];StrBlock->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;StrCpyS(StrBlock->StringText, StrLen(Strings[i])+1, Strings[i]);Size+=sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK) +StrLen(Strings[i])*2; } EFI_HII_SIBT_END_BLOCK* EndBlock = (EFI_HII_SIBT_END_BLOCK*)&Ptr[Size];EndBlock->Header.BlockType = EFI_HII_SIBT_END;Size+=sizeof(EFI_HII_SIBT_END_BLOCK);HIIStringPackageHdr->Header.Length =Size;returnSize;}