UEFI开发探索16 – 使用HII显示汉字1

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

上一次博客中,我使用自己的方法显示汉字,其核心思想不外乎利用实现的画点函数,将汉字一个像素一个像素地画出来。

很明显,这种方法只能在图形模式下实现。如果想在字符模式下显示(比如UEFI Shell),则无能无力了。虽然目前商用的Option Rom不可能用到字符模式,奈何寻根究底的程序员本性,驱使着我把UEFI本身提供的Human Interface Infrastructure机制搞明白。

于是开始了我这几天的探索之旅。

所有的探索都是从问题开始,对HII,我提的问题如下:

  1. 如何组织汉字库(其他语言也一样,怎么存储字库?);
  2. 是否能在UEFI Shell下显示汉字,如何实现?
  3. 图形模式下如何显示汉字?

我所查询的资料包括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”存放的是系统所支持的全部语言,只有英语和法语。

看来程序中声明支持哪种语言,与系统变量是无关的。程序是自洽的,可以使用系统本身支持的语言,如果要显示系统不支持的语言,得自己去实现了。

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
代码在 09 HiiShellPrint 下。

3,406 total views, 1 views today

发表评论

电子邮件地址不会被公开。