(请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365)
上一次博客中,我使用自己的方法显示汉字,其核心思想不外乎利用实现的画点函数,将汉字一个像素一个像素地画出来。
很明显,这种方法只能在图形模式下实现。如果想在字符模式下显示(比如UEFI Shell),则无能无力了。虽然目前商用的Option Rom不可能用到字符模式,奈何寻根究底的程序员本性,驱使着我把UEFI本身提供的Human Interface Infrastructure机制搞明白。
于是开始了我这几天的探索之旅。
所有的探索都是从问题开始,对HII,我提的问题如下:
- 如何组织汉字库(其他语言也一样,怎么存储字库?);
- 是否能在UEFI Shell下显示汉字,如何实现?
- 图形模式下如何显示汉字?
我所查询的资料包括UEFI Spec、《UEFI原理与编程》以及《Harnessing the uefi shell》,还有之前我自己写的一些代码。
图1 HII in the uefi spec2.8
UEFI Spec中用了三个章节来介绍HII,内容也比较丰富,真要全部看懂需要花很多时间。我还是从比较简单的入手:各种语言的字符串是怎么存储的?这也是《UEFI原理与编程》第11章首先介绍的。
我准备将书上的例程移植到我的程序中,我使用的模板程序是04 ReadKey,之前的博客中介绍过。
1 字符串资源的组织
字符串资源以*.uni文件来组织,使用#langdef、#string等标识符来定义字段。以这篇博客提供的example.uni(来源于《UEFI原理与编程》chap 11)为例:
#langdef en-US “English”
#langdef zh-Hans “简体中文”
…
#string STR_LANGUAGE_SELECT #language en-US “Select Language”
#language zh-Hans “选择语言”
…
其中,#langdef用于申明本字符串资源文件所支持的语言,第一个参数是字符标识符;第二个参数是该语言可显示的名字字符串。
我很好奇,以显示中文为例,虽然定义中名字字符串为“简体中文”,如果我想在shell下打印它的话,会怎么样?
估计什么都不会显示吧。这又回到了如何在UEFI Shell中显示汉字的问题了,没有提供字库,也没法显示什么。
#string用于定义字符串。第一个参数为字符串标识符,相当于变量定义;第二个参数是该语言下的字符串。
编译example.uni后生成的字符包组合,会定义在生成的AutoGen.c中,仔细研究这个文件,会了解不少东西。
需要注意的是,example.uni内部定义的字符串,在编译后,在本例中不是生成exampleStrings,而是生成了Luo2Strings。我猜测编译器是将*.inf中的BASE_NAME加上“Strings”组成的(Luo.inf中BASE_NAME为Luo2),没有去找资料证明,估计如此。
2 AutoGen.c中的字符串
*.uni编译之后的的字符串,在AutoGen.c中可以找到。
最开始,我以为中文的字符串,仍旧是以国标码的方式存储。汉字的国标码能很方便的查到,很多编辑器都提供了二进制查看的功能,直接就能查到。
我仔细读了AutoGen.c的字符串部分,Pack的首4字节为长度,剩余部分为字符串,可我怎么也没法将汉字意义一一对应起来。
突然意识到,字符串应该是以Unicode的编码存储的。代码中都是以L”xx”的形式在定义字符串,已经说明了这点,我怎么会没早点想到?
找来UCS-2的字符表,一个个查,果然对了。
图2 AutoGen.c中字符串的组织
3 管理字符串资源
UEFI中提供了EFI_HII_STRING_PROTOCOL管理字符串资源。具体的使用方法,可以参考上面提到的参考书,里面非常详细。
我主要使用了GetString来获取字符串,打印出来。
图3 GetString函数说明
主要关注两个参数,一是Language,制定需要显示的语言类型;二是String,相当于字符串变量名。
这篇博客提供的例子中,主要关注TestString和TestLanguage,以及使用HiiAddPackages添加字符串到数据库就行了,其他函数与Hii无关。
4 编译测试
将程序编译后,实现的效果如下:
图4 TianoCore模拟环境中运行程序
值得注意的是,使用Shell命令dmpstore -b,得到的信息如下:
图5 TianoCore模拟环境中支持的语言
全局变量L”PlatformLangCodes”存放的是系统所支持的全部语言,只有英语和法语。
看来程序中声明支持哪种语言,与系统变量是无关的。程序是自洽的,可以使用系统本身支持的语言,如果要显示系统不支持的语言,得自己去实现了。
Gitee地址:https://gitee.com/luobing4365/uefi-explorer
项目代码位于:/09 HiiShellPrint 下。