55. PlatformLangCodes EFI 변수 수정 및 다른 언어를 동적 추가하기
우리는 새 언어에 대한 글꼴을 추가해주는 방법을 학습했으며, 시스템의 일부 기존 언어에 대한 문자열을 동적으로 채우는 방법을 알게 되었다. 이번 장에서는 다른 언어를 동적으로 생성할 수 있는지 살펴보겠다.
Select Language 메뉴는 PlatformLangCodes EFI 변수 값에서 가능한 모든 언어 옵션을 가져온다. 그리고 현재 언어 옵션은 PlatformLang EFI 옵션에 반영된다.
이러한 옵션의 값은 https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec서 PCD의 도움으로 설정된다.
## Default platform supported RFC 4646 languages: (American) English & French.
# @Prompt Default Value of PlatformLangCodes Variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes|"en;fr;en-US;fr-FR"|VOID*|0x0000001e
## Default current RFC 4646 language: (American) English.
# @Prompt Default Value of PlatformLang Variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang|"en-US"|VOID*|0x0000001fhttps://github.com/tianocore/edk2/blob/master/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c 에서 UiCreateLanguageMenu 함수의 실제 코드를 볼 수 있다.
PlatformLangCodes를 수정하고, 다른 언어를 추가할 수 있는지 살펴보자.
먼저 PlatformLangCodes 옵션의 값을 출력하는 애플리케이션을 만든다.
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
CHAR8* LanguageString;
Status = GetEfiGlobalVariable2(L"PlatformLangCodes", (VOID**)&LanguageString, NULL);
if (EFI_ERROR(Status)) {
Print(L"Error! Can't perform GetEfiGlobalVariable2, status=%r\n", Status);
return Status;
}
Print(L"Current value of the 'PlatformLangCodes' variable is '%a'\n", LanguageString);
return EFI_SUCCESS;
} 이전에 이미 gRT->GetVariable 프로토콜 함수를 직접 사용한 적이 있으므로, 여기서는 GetEfiGlobalVariable2 라이브러리 함수를 사용하여 코드를 단순화한다. 이 함수는 https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiLib/UefiLib.c 정의되어 있다.
애플리케이션을 빌드하고 실행하면, PCD에서 값을 얻을 수 있다.
이제 변수 끝에 ;ru-RU를 추가하고 다시 작성해보자.
먼저 새 문자열을 구성하고 필요한 데이터로 채운다.
ASCII 문자열 함수가 https://github.com/tianocore/edk2/blob/master/MdePkg/Library/BaseLib/String.c 정의된 경우에 대비. 또한 AllocatePool 함수에 대한 Library/MemoryAllocationLib.h 헤더와 CopyMem 함수에 대한 Library/BaseMemoryLib.h 헤더를 포함하는 것을 잊지 않도록 하자.
이제 SetVariable 호출을 사용하여 변수를 업데이트한다.
SetVariable은 Runtime 서비스이며, UEFI 스펙에서 해당 정의를 찾을 수 있다.
gRT는 UefiRuntimeServicesTableLib 라이브러리의 SystemTable->RuntimeServices에 대한 바로가기이다. 따라서 라이브러리 헤더 <Library/UefiRuntimeServicesTableLib.h>를 포함하는 것을 잊지 않도록 하자.
애플리케이션을 빌드하고 실행하면, 다음과 같은 결과를 얻을 수 있다.
안타깝게도, 'PlatformLangCodes' EFI 변수가 쓰기 금지되어 있으므로 Runtime 시, 새 언어를 추가할 수 없다. 따라서 Runtime에 다른 로컬화 언어를 추가할 수 없다.
UEFI 스펙을 보면 다음과 같이 표시된다.
EDKII_VARIABLE_POLICY_PROTOCOL
PlatformLangCodes는 gEdkiiVariablePolicyProtocolGuid 프로토콜의 도움으로 수정할 수 있도록 잠겨 있다. 이는 변수에 대해 다른 정책을 설정하기 위한 사용자 정의 EDKII 프로토콜이다.
https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md 보면, UEFI 변수 정책 프로토콜에 대한 자세한 내용을 알 수 있다.
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Protocol/VariablePolicy.h 아래에 헤더파일이 존재한다.
PlatformLangCodes EFI 변수에 대한 정책은 몇가지 다른 변수와 함께 https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/BdsDxe/BdsEntry.c 설정된다.
Try to execute DisableVariablePolicy()
DisableVariablePolicy()를 수행하여, VariablePolicyProtocol을 비활성화할 수 있다.
하지만, 이 호출에 에러가 발생한다.
이는 DXE UEFI 단계의 변수 정책이 VariableDxe.c에서 잠겨있기 때문에 발생하는 것이다.
Locking(잠금)은 더 이상 변수에 대한 정책을 변경하거나, 비활성화할 수 없음을 의미한다. 따라서 Runtime에 PlatformLangCodes를 변경할 방법이 없다.
Last updated