UEFI开发学习12 – 中文显示(Ⅱ)
接上一篇,继续探究UEFI的中文显示问题,主要有两个部分,一个是shell下显示中文,另一个是汉化UDK配置界面。这两个问题都是需要安装中文的,所以,首先介绍下如何安装中文字库。
安装中文字库
1.生成字库
由于字体是有版权的,商业使用需要授权,所以可以使用免费开源字体,当然我们用来学习的就无关紧要了,文末我会附上谷歌的免费字体,可自由使用。
上一篇中我已经介绍过使用我修改过的字体生成工具了,这里照样还是需要用到它( 点阵字库生成工具 直接生成UEFI字库)。启动这个工具,右下角“文件格式”选择UEFI,“编辑码表”可输入要生成的字库,文末有我从百度文库找到的常用汉字3754个(汉字有几万个,全部生成就没必要了,常用的即可),可直接载入,再设置要生成的字体名,要注意一下的是,如果默认的16号字体不能填满黑色部分,可适当调大,我用谷歌字体调到22,而宋体默认就可以了。然后再看看字体有无居中,没有的话可以适量调一下水平跟垂直偏移,最后点击保存字库。
2.安装字库
UDK的代码中有安装字库的部分,位于MdeModulePkg\Universal\Console\GraphicsConsoleDxe目录,LaffStd.c是默认字库文件,我们就在这里添加中文字库。
① 在生成的中文字库文件加上头文件
#include "GraphicsConsole.h"
最后一行添加数组大小
UINT32 mWideFontSize = sizeof (gFontWideGlyphData);
② 打开MdeModulePkg\Universal\Console\GraphicsConsoleDxe\GraphicsConsole.h,添加
extern EFI_WIDE_GLYPH gFontWideGlyphData[]; extern UINT32 mWideFontSize;
③ 打开MdeModulePkg\Universal\Console\GraphicsConsoleDxe\GraphicsConsole.c,找到RegisterFontPackage函数,照葫芦画瓢,做如下修改:
/** HII Database Protocol notification event handler. Register font package when HII Database Protocol has been installed. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI RegisterFontPackage ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimplifiedFont; UINT32 PackageLength; UINT8 *Package; UINT8 *Location; EFI_HII_DATABASE_PROTOCOL *HiiDatabase; EFI_GUID mChineseFontPackageListGuid = {0x9f7bc74d, 0x0549, 0x4416, {0x86, 0x85, 0xc7, 0x16, 0xcd, 0x61, 0x0b, 0x74}}; // // Locate HII Database Protocol // Status = gBS->LocateProtocol ( &gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase ); if (EFI_ERROR (Status)) { return; } // // Add 4 bytes to the header for entire length for HiiAddPackages use only. // // +--------------------------------+ <-- Package // | | // | PackageLength(4 bytes) | // | | // |--------------------------------| <-- SimplifiedFont // | | // |EFI_HII_SIMPLE_FONT_PACKAGE_HDR | // | | // |--------------------------------| <-- Location // | | // | gUsStdNarrowGlyphData | // | | // +--------------------------------+ PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mNarrowFontSize + 4; Package = AllocateZeroPool (PackageLength); ASSERT (Package != NULL); WriteUnaligned32((UINT32 *) Package,PackageLength); SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4); SimplifiedFont->Header.Length = (UINT32) (PackageLength - 4); SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS; SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (mNarrowFontSize / sizeof (EFI_NARROW_GLYPH)); Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1); CopyMem (Location, gUsStdNarrowGlyphData, mNarrowFontSize); // // Add this simplified font package to a package list then install it. // mHiiHandle = HiiAddPackages ( &mFontPackageListGuid, NULL, Package, NULL ); ASSERT (mHiiHandle != NULL); FreePool (Package); /* Add Chinese font */ PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mWideFontSize + 4; Package = AllocateZeroPool (PackageLength); ASSERT (Package != NULL); WriteUnaligned32((UINT32 *) Package,PackageLength); SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4); SimplifiedFont->Header.Length = (UINT32) (PackageLength - 4); SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS; SimplifiedFont->NumberOfWideGlyphs = (UINT16) (mWideFontSize / sizeof (EFI_WIDE_GLYPH)); Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1); CopyMem (Location, gFontWideGlyphData, mWideFontSize); // // Add this simplified font package to a package list then install it. // mHiiHandle = HiiAddPackages ( &mChineseFontPackageListGuid, NULL, Package, NULL ); ASSERT (mHiiHandle != NULL); FreePool (Package); }
④ 将字库文件加入GraphicsConsoleDxe.inf,保存重新编译Nt32Pkg。
3.测试
在SecMain.exe所在目录新建一个中文名字的文件,然后在shell用ls命令查看,中文安装成功则可以显示。
EFI APP使用中文
EFI app使用中文直接用Print就可以了,但是有个问题,c文件中出现中文会有编译报错的问题,需要参考这篇解决-> 解决VS编译中文报错 error C2001:常量中有换行符,不过还是建议用uni文件做,这样规范一些,而且还可以比较方便地实现多语言切换。实例如下:
// ShellFont.c #include <Uefi.h> #include <Library/UefiLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/HiiLib.h> #include <Library/UefiHiiServicesLib.h> #include <Library/MemoryAllocationLib.h> #pragma execution_character_set("utf-8") EFI_GUID mPackageListGuid = {0xd8ebc548, 0xd7ea, 0x46e6, {0x98, 0x0d, 0x0e, 0xa0, 0x04, 0xfd, 0xc7, 0x00}}; int main ( IN int Argc, IN char **Argv ) { #if 0 EFI_HANDLE HiiHandle; EFI_STRING String; EFI_STATUS Status; UINTN StringSize; //CHAR8 * Language = "en-US"; CHAR8 * Language = "zh-Hans"; HiiHandle = HiiAddPackages (&mPackageListGuid, gImageHandle, ShellFontStrings, NULL); StringSize = 0; Status = gHiiString->GetString(gHiiString, Language, HiiHandle, STRING_TOKEN (STR_TITLE), String, &StringSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { String = AllocateZeroPool (StringSize); Status = gHiiString->GetString (gHiiString, Language, HiiHandle, STRING_TOKEN (STR_TITLE), String, &StringSize, NULL,); if (EFI_ERROR(Status)) return 0; } Print(L"Test String:%s\n\r", String); #else // 更简洁的写法 EFI_HANDLE HiiHandle; EFI_STRING String; //CHAR8 * Language = "en-US"; CHAR8 * Language = "zh-Hans"; HiiHandle = HiiAddPackages (&mPackageListGuid, gImageHandle, ShellFontStrings, NULL); String = HiiGetString (HiiHandle, STRING_TOKEN (STR_TITLE), Language); Print(L"Test String:%s 0x%X\n\r", String, *String); //Print(L"Test: %s\n\r", L"我是中国人"); // 使用Print直接打印 #endif return(0); }
# ShellFont.inf ## @file # A simple, basic, EDK II native, "hello" application. # # Copyright (c) 2010, Intel Corporation. All rights reserved.<BR> # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at # http://opensource.org/licenses/bsd-license. # # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. # ## [Defines] INF_VERSION = 0x00010006 BASE_NAME = ShellFont FILE_GUID = 941d0b52-c64c-43a4-8fc7-2305c6a40185 MODULE_TYPE = UEFI_APPLICATION VERSION_STRING = 0.1 ENTRY_POINT = ShellCEntryLib # # VALID_ARCHITECTURES = IA32 X64 IPF # [Sources] ShellFont.c ShellFont.uni [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec [LibraryClasses] LibC UefiHiiServicesLib HiiLib [Protocols] gEfiGraphicsOutputProtocolGuid
// ShellFont.uni #langdef en-US "English" #langdef zh-Hans "中文" #string STR_TITLE #language en-US "This is a title" #language zh-Hans "这是一个标题"
运行结果:
注意c文件的ShellFontStrings变量,这是编译uni文件后自动生成的,名字由包名+Strings组成!通过更改Language的值可切换多种语言,所以EFI APP 也可实现多语言版本。
附件
https://gitee.com/ay123net/uefistudy
版权声明:
作者:bin
链接:https://ay123.net/mystudy/887/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论