该文章主要是介绍如何为EDK2的HII界面如何添加中文支持,并且解决中文字符串显示不全的问题, edk2的源码相信各位自己都有哈,不然也不会有这个需求,所以不介绍如何搭建edk2环境了。废话不多说,直接上干货。
1 将中文添加到支持的语言列表
打开 /MdePkg/MdePkg.dec 文件,做如下修改
PcdUefiVariableDefaultLangCodes属性修改为:”zhoengfra”
PcdUefiVariableDefaultLang 属性修改为:”zho”
PcdUefiVariableDefaultPlatformLangCodes 属性修改为:"zh-Hans;en-US;fr-FR"
PcdUefiVariableDefaultPlatformLang 属性修改为:"zh-Hans” (如果HII界面contiune 按钮没反应就改为 “en-US” )
2 添加中文字库
我这边图方便,就没有新建一个模块来添加中文字库了,直接在官方代码里添加了,接下来介绍如何在官方代码里添加中文字库:
2.1 生成中文字库
这边中文字库通过一个js脚本来生成,脚本来自于UEFI 之 中文显示:
<html>
<head>
</head>
<body>
Text:
<canvas id="a" width="32" height="32"></canvas>
<script type="text/javascript">
var a_canvas = document.getElementById("a");
var context = a_canvas.getContext("2d");
const FW = 16; //宽度 单位像素
const FH = 19; //高度, 单位像素
context.strokeRect(10, 10, FW, FH);
context.font = "bold 15px times new roman" //设置想要的字体,与css定义相同,不支持的字体会使用相近的
context.fillstyle='#00f'; //画布初始化
var fontstr="{<BR>";
//for(i=0x4e00; i< 0x4fa5;i++){
function formatHH(x){
var l = x.length;
var s = x;
if (l == 1)
s = "0" + x;
return s;
}
for(i=0x4e00; i< 0x9fa5;i++){//要处理的unicode16 编码的范围,汉子0x4e00到0x9f5
context.clearRect(10, 10, FW, FH);
context.fillText(String.fromCharCode(i), 10, 10+FW); //写字符到画布
var bitmapimg = context.getImageData(10,10, FW,FH); //读画布位图
//var bitmapimg = context.getImageData(0,0, 32,32);
var bitmap = bitmapimg.data;
//document.write(bitmap.length+"<BR>");
//for(var b = 0; b< bitmap.length; b++)
// document.write(" " + bitmap[b] );
//将表述字符的画布位图转化为数据结构
var left = " ";
var right = " ";
for( row =0;row <19; row++){
var a = 0;
for(col =0; col <8; col ++){
if(bitmap[row * 16 *4 + col*4 +3] >10)//判断透明度的值,误差就是这里产生的
a = (a<<1) | 1;
else
a = a<< 1
}
left = left + "0x" + formatHH(a.toString(16)) ;
if(row <18) left = left + ",";
a = 0;
for(;col<16; col++){
if(bitmap[row * 16 *4 + col*4+3] >10)
a = (a<<1) | 1;
else
a = a<< 1;
}
right = right + "0x" + formatHH(a.toString(16)) ;
if(row <18) right= right+ ",";
}
fontstr = fontstr + "{ 0x"+ i.toString(16) + ", 0x00, " + "{" + left +"}, {" + right +"}, {0x00,0x00,0x00} },"+ "<BR>";
}
fontstr = fontstr + "{ 0x00, 0x00, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} <BR> };"
document.write(fontstr);
</script>
</body>
</html>
2.2 将中文字库复制到源码中的
打开/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/LaffStd.c 文件,在文件末尾添加后如下:
2.3 注册字库
/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h 文件中添加:
extern EFI_WIDE_GLYPH gSimpleFontWideGlyphData[];
extern UINT32 gSimpleFontBytes;
/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c 文件中的 RegisterFontPackage 函数中添加:
以上,就完成了edk2中文字库的添加,接下来可以汉化FrontPage界面。
3 汉化FrontPage界面
打开 /MdeModulePkg/Application/UiApp/FrontPageStrings.uni 文件,添加内容如下(只展示部分,其他自行添加):
当前包支持的语言:
中文对应的字符串也要添加,需要使用 \wide 开始,\narrow结束:
完成以上所有步骤后,编译然后运行会发现就以及能显示中文了,但有可能会出现中文字符串显示不全的问题。
所以下面来解决该问题。
4 解决中文显示不全的问题
打开 /MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c 文件,修改其中的 PrintInternal 函数
将其中的 TotalCount += Count ; 通通改为 TotalCount += Count * CharWidth;(俩个地方)
打开 /MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c 文件,修改其中的 PrintStringAtWithWidth 函数,将原函数改为:
UINTN
EFIAPI
PrintStringAtWithWidth (
IN UINTN Column,
IN UINTN Row,
IN CHAR16 *String,
IN UINTN Width
)
{
PrintAt (Width, Column, Row, L" ");
return PrintAt (0, Column, Row, L"%s", String);
}
完成以上步骤,即可完美实现edk2中文显示,本教程到此结束,希望能帮助大家,最后叠个甲,本人是一个刚接触 UEFI 的菜鸟,该功能是我花三天时间从零基础开始查资料、问群友以及阅读源码实现的,欢迎各位大佬指点。
参考资料:
【UEFI实战】HII之FrontPage_hii 之 frontpage-优快云博客(看了这个大佬很多文章,强烈推荐)
UEFI开发探索16 – 使用HII显示汉字1_uefi之hii之中文界面-优快云博客
如何让UEFI BIOS支持汉字显示:汉字编码与显示实践 - 知乎