#langdef en-US "English"
#string STR_FORMSET_TITLE #language en-US "OVMF Platform Configuration"
#string STR_FORMSET_HELP #language en-US "Change various OVMF platform settings."
#string STR_MAIN_FORM_TITLE #language en-US "OVMF Settings"
#string STR_RES_CUR #language en-US "Preferred Resolution at Next Boot"
#string STR_RES_CUR_HELP #language en-US "The preferred resolution of the Graphics Console at next boot. It might be unset, or even invalid (hence ignored) wrt. the video RAM size."
#string STR_RES_NEXT #language en-US "Change Preferred Resolution for Next Boot"
#string STR_RES_NEXT_HELP #language en-US "You can specify a new preference for the Graphics Console here. The list is filtered against the video RAM size."
#string STR_SAVE_EXIT #language en-US "Commit Changes and Exit"
#string STR_DISCARD_EXIT #language en-US "Discard Changes and Exit"
BIOS 메뉴에서 언어 기본 설정을 프랑스어로 변경하더라도 이러한 문자열은 여전히 영어로 출력된다. 확인해볼 수 있다.
Select Language 옵션을 사용하여 언어를 Francais로 변경한다.
그런 다음 Device Manager -> OVMF Platform Configuration을 살펴보도록 한다.
먼저 패키지 목록에서 가능한 모든 문자열을 출력해보겠다. 우리는 UNI 소스 코드를 보았지만, 일부 문자열은 시스템에서 동적으로 추가될 수 있으므로 이를 확인하는 것이 좋다.
패키지 목록에서 문자열을 출력하려면, 패키지 목록의 EFI_HII_HANDLE이 필요하다. 이를 위해 EFI_HII_DATABASE_PROTOCOL에서 ListPackageLists 함수를 활용할 수 있다.
EFI_HII_DATABASE_PROTOCOL.ListPackageLists()
Summary:
Determines the handles that are currently active in the database.
Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_LIST_PACKS) (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN OUT UINTN *HandleBufferLength,
OUT EFI_HII_HANDLE *Handle
);
Parameters:
This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
PackageType Specifies the package type of the packages to list or EFI_HII_PACKAGE_TYPE_ALL
for all packages to be listed.
PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then this is the pointer to the
GUID which must match the Guid field of EFI_HII_GUID_PACKAGE_HDR. Otherwise, it must be NULL.
HandleBufferLength On input, a pointer to the length of the handle buffer. On output, the length of the
handle buffer that is required for the handles found.
Handle An array of EFI_HII_HANDLE instances returned. Type EFI_HII_HANDLE is
defined in EFI_HII_DATABASE_PROTOCOL.NewPackageList() in the Packages section.
Description:
This function returns a list of the package handles of the specified type that are currently active in the
database. The pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed
이 함수를 사용하면 HandleBufferLength=0으로 한 번 호출하고, EFI_BUFFER_TOO_SMALL 오류를 수신하지만, HandleBufferLength에 대한 값을 가져와야 한다. 필요한 크기만을 할당하고, 이 함수를 다시 호출한다.
말만 들었는데도 조금 지루한 과정이다.
이 작업을 더 쉽게 하기 위해서 HiiLib 에서 HiiGetHiiHandles 함수를 활용해 보겠다.
/**
Retrieves the array of all the HII Handles or the HII handles of a specific
package list GUID in the HII Database.
This array is terminated with a NULL HII Handle.
This function allocates the returned array using AllocatePool().
The caller is responsible for freeing the array with FreePool().
@param[in] PackageListGuid An optional parameter that is used to request
HII Handles associated with a specific
Package List GUID. If this parameter is NULL,
then all the HII Handles in the HII Database
are returned. If this parameter is not NULL,
then zero or more HII Handles associated with
PackageListGuid are returned.
@retval NULL No HII handles were found in the HII database
@retval NULL The array of HII Handles could not be retrieved
@retval Other A pointer to the NULL terminated array of HII Handles
**/
EFI_HII_HANDLE *
EFIAPI
HiiGetHiiHandles (
IN CONST EFI_GUID *PackageListGuid OPTIONAL
)
여기 문자열을 얻기 위해 가능한 모든 문자열 토큰을 반복하여 HiiGetString 함수를 호출하는 것을 볼 수 있다.
이 애플리케이션을 빌드하고 실행하면 다음과 같은 결과를 얻게 된다.
FS0:\> HIIAddLocalization.efi
ID=1, English
ID=2, OVMF Platform Configuration
ID=3, Change various OVMF platform settings.
ID=4, OVMF Settings
ID=5, Preferred Resolution at Next Boot
ID=6, The preferred resolution of the Graphics Console at next boot. It might be unset, or even invalid (hence ignored) wrt. the video RAM size.
ID=7, Change Preferred Resolution for Next Boot
ID=8, You can specify a new preference for the Graphics Console here. The list is filtered against the video RAM size.
ID=9, Commit Changes and Exit
ID=10, Discard Changes and Exit
ID=11, 640x480
ID=12, 800x480
ID=13, 800x600
ID=14, 832x624
ID=15, 960x640
ID=16, 1024x600
ID=17, 1024x768
ID=18, 1152x864
ID=19, 1152x870
ID=20, 1280x720
ID=21, 1280x760
ID=22, 1280x768
ID=23, 1280x800
ID=24, 1280x960
ID=25, 1280x1024
ID=26, 1360x768
ID=27, 1366x768
ID=28, 1400x1050
ID=29, 1440x900
ID=30, 1600x900
ID=31, 1600x1200
ID=32, 1680x1050
ID=33, 1920x1080
ID=34, 1920x1200
ID=35, 1920x1440
ID=36, 2000x2000
ID=37, 2048x1536
ID=38, 2048x2048
ID=39, 2560x1440
ID=40, 2560x1600
프랑스어로 번역된 배열을 만들어 보자.
CHAR16* FrenchStrings[] = {
L"Configuration de la OVMF plateforme",
L"Modifier divers paramètres de la plateforme OVMF",
L"Paramètres OVMF",
L"Résolution préférée au prochain démarrage",
L"La résolution préférée de la console graphique au prochain démarrage. Il peut être non défini, ou même invalide (donc ignoré) wrt. la taille de la RAM vidéo.",
L"Modifier la résolution préférée pour le prochain démarrage",
L"Vous pouvez spécifier ici une nouvelle préférence pour la console graphique. La liste est filtrée en fonction de la taille de la RAM vidéo.",
L"Valider les modifications et quitter",
L"Annuler les changements et quitter",
L"640x480",
L"800x480",
L"800x600",
L"832x624",
L"960x640",
L"1024x600",
L"1024x768",
L"1152x864",
L"1152x870",
L"1280x720",
L"1280x760",
L"1280x768",
L"1280x800",
L"1280x960",
L"1280x1024",
L"1360x768",
L"1366x768",
L"1400x1050",
L"1440x900",
L"1600x900",
L"1600x1200",
L"1680x1050",
L"1920x1080",
L"1920x1200",
L"1920x1440",
L"2000x2000",
L"2048x1536",
L"2048x2048",
L"2560x1440",
L"2560x1600",
};
이제 문자열 출력 반복문에 대한 설명을 해보자면, 문자열 패키지를 생성하고 동일한 패키지 목록 아래 HII 데이터베이스에 채워야 한다. 여기서 우리는 한 가지 방법을 사용할 수 있다.
manual 문자열 패키지를 생성하는 대신, 새 언어의 dummy인 L"" 문자열을 사용하여 gHiiString->NewString 함수를 호출할 수 있다.
en-US 문자열 패키지에 40개의 문자열이 있는 경우, ID=41인 문자열 L"" 하나만 있는 fr-FR 문자열 패키지가 생성된다. 그리고 이 패키지는 자동으로 패키지 목록에 추가된다.
fr-FR 문자열 패키지가 패키지 목록 있으면, 모든 데이터 문자열에 대해 gHiiString->SetString 함수를 간단히 호출할 수 있다.
EFI_STATUS Status;
for (UINTN i=0; i<(sizeof(FrenchStrings)/sizeof(FrenchStrings[0])); i++) {
EFI_STRING_ID StringId;
if (i==0) {
Status = gHiiString->NewString(gHiiString, *Handle, &StringId, "fr-FR", L"French", L"", NULL);
if (EFI_ERROR(Status)) {
Print(L"Error! NewString fail\n");
}
}
StringId = i+2;
Status = gHiiString->SetString(gHiiString, *Handle, StringId, "fr-FR", FrenchStrings[i], NULL);
if (EFI_ERROR(Status)) {
Print(L"Error! SetString fail for ID=%d\n", StringId);
}
}
다음은 EFI_HII_STRING_PROTOCOL의 NewString 및 SetString 함수에 대한 API 설명이다.
EFI_HII_STRING_PROTOCOL.SetString()
Summary:
Change information about the string.
Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_SET_STRING) (
IN CONST EFI_HII_STRING_PROTOCOL *This,
IN EFI_HII_HANDLE PackageList,
IN EFI_STRING_ID StringId,
IN CONST CHAR8 *Language,
IN CONST EFI_STRING String,
IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
);
Parameters:
This A pointer to the EFI_HII_STRING_PROTOCOL instance.
PackageList The package list containing the strings.
Language Points to the language for the updated string.
StringId The string id, which is unique within PackageList.
String Points to the new null-terminated string.
StringFontInfo Points to the string’s font information or NULL if the string font information is not changed.
Description:
This function updates the string specified by StringId in the specified PackageList to the text specified by
String and, optionally, the font information specified by StringFontInfo
EFI_HII_STRING_PROTOCOL.NewString()
Summary:
Creates a new string in a specific language and add it to strings from a specific package list.
Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_NEW_STRING) (
IN CONST EFI_HII_STRING_PROTOCOL *This,
IN EFI_HII_HANDLE PackageList,
OUT EFI_STRING_ID *StringId
IN CONST CHAR8 *Language,
IN CONST CHAR16 *LanguageName OPTIONAL,
IN CONST EFI_STRING String,
IN CONST EFI_FONT_INFO *StringFontInfo
);
Parameters:
This A pointer to the EFI_HII_STRING_PROTOCOL instance.
PackageList Handle of the package list where this string will be added.
Language Points to the language for the new string.
LanguageName Points to the printable language name to associate with the passed in Language
field.
String Points to the new null-terminated string.
StringFontInfo Points to the new string’s font information or NULL if the string should have the
default system font, size and style.
StringId On return, contains the new strings id, which is unique within PackageList.
DescriptionL
This function adds the string String to the group of strings owned by PackageList, with the specified font information StringFontInfo and returns a new string id
gHiiString 프로토콜을 직접 사용하기 위해 UefiHiiServicesLib 라이브러리 클래스와 해당 헤더 Library/UefiHiiServicesLib.h를 추가하는 것을 잊지 않도록 하자.
애플리케이션을 빌드하고 실행한다.
FS0:\> HIIAddLocalization.efi
FS0:\>
그런 다음 exit으로 BIOS 메뉴로 이동한다.
Select Language 옵션으로 언어를 Francais로 변경한다.
그 다음, DeviceManager -> OVMF Platform Configuration으로 이동한다. 이미 번역이 완료되어 있음을 알 수 있다.
메뉴를 종료한 다음 다시 이동하면 Device manager의 문자열도 "Configuration de la OVMF plateforme"로 변경된 것을 볼 수 있다.