

UEFI开发探索51 – UEFI下的打印函数
source link: http://yiiyee.cn/blog/2020/04/01/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a251-uefi%e4%b8%8b%e7%9a%84%e6%89%93%e5%8d%b0%e5%87%bd%e6%95%b0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

UEFI开发探索51 – UEFI下的打印函数
请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
原计划的50篇博客,终于完成了。可惜的是,现有的篇幅无法把最初设想的内容全部覆盖。因此,开发探索系列还会继续写下去,既然原定目标50篇已经达成,新的目标篇数就不设定了。只针对我感兴趣的各方面的内容,继续探索。
在日常的开发中,总会用到各种打印(print)函数。UEFI下的打印函数,其格式有点奇怪,和Windows及Linux下的print函数不大相同。而且又涉及到Ascii字符和Unicode字符的支持,在使用中总是犯一些小错,让人很是恼火。
因此,为了方便后面的开发,我准备将相关的打印函数整理出来,以备参考。
1OutputString()
最基本的打印输出函数,其他Print函数都是基于此函数构建的。其函数原型为:
typedef
EFI_STATUS
(EFIAPI *EFI_TEXT_STRING) (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,//指向
//EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL实例的指针IN CHAR16 *String //以Null结尾的字符串);
此函数向输出设备写入字符串,显示在当前光标处,是最基本的输出机制。
示例如下:
gST->ConOut->OutputString(gST->ConOut,L”Hello, UEFI World!\n\r”);
这是Simple Text Output Protocol最核心的函数,配合此Protocol的其他函数,比如SetAttribute等,可以实现彩色背景和彩色字体。在之前的博客中曾经展示过,可以做出与众不同的命令行式Sell程序。
2 格式化输出
PrintLib提供了格式化输出的支持函数,它支持所有Unicode和ASCII字符串。在Package的dsc文件中,一般都会提供这个库的编译。如下:
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
UEFI的格式化方式,与ANSI C的标准不尽相同,在使用的时候,很容易造成概念混淆。
格式化语法如下:
%[flags][width][.precision]type
[flags]
● – 左对齐标志,如果没有设置,则为右对齐
● 空格 对数字类型字符添加前置空格,对类型X,x和d有效
● + 符号前缀,显示数字的正负,对类型X,x和d有效,与空格同用时,忽略空格
● 0 以先导0补充数字左侧,常配合后续的width(宽度)使用,对类型X,x和d
有效;
● , 以千位分隔符表示数字,只对类型d有效,与标志0同用时,忽略0;
● L,l 将指定的数字以UINT64型打印,对类型X,x和d有效。如果不指定此标志,
则以int型打印;
注意:非上述标志都会被忽略掉
[width]
● * 由参数列表中的数字给出宽度。如Print(L”%0*d”,5,a)表示以宽度5表示变量
a, 不足由前导0补上;
● 数字 由此10进制数给出需要表示的宽度;
注意:如果width的值没有给出,缺省以0指定。
[.precision]
● * 由参数列表中的数字给出宽度;
● 数字 由此10进制数给出需要表示的精度;
注意:如果此域没有给出,缺省以0指定。
type
● % 打印个百分号出来
● c 打印Unicode字符。ASCII字符也可以使用此类型,只要保证其bits8…15为
0;
● x 将需要打印的参数认为是无符号十进制数,以十六进制形式打印参数。与
ANSI C标准不同;
● X 将需要打印的参数认为是无符号十进制数,以十六进制形式打印参数,同时
以前导0填充。与ANSI C标准不同;
● d 将需要打印的参数认为是有符号十进制数,以十进制形式打印参数;
● p 需要打印的参数是指针(Void *),以无符号十六进制形式打印出指针地址;
● a 参数为指向ASCII字符串的指针,与ANSI C标准不同;
● S,s 参数为指向Unicode字符串的指针,与ANSI C标准不同;
● g 参数为指向GUID结构的指针,用来打印GUID的。与ANSI C标准不同;
● t 参数为指向EFI_TIME结构的指针,以mm/dd/yyyy hh:mm的形式打印,不足
位的以0填充。与ANSI C标准不同;
● r 参数为RETURN_STATUS值,将此值代表的含义转换为字符串,打印出来。
与ANSI C标准不同。
以下为部分转换对照:(具体值的含义可参考EDKII代码中的\BaseTools\Source\C\Include\Common\UefiBaseTypes.h)
RETURN_SUCCESS: “Success”
RETURN_LOAD_ERROR: “Load Error”
RETURN_INVALID_PARAMETER: “Invalid Parameter”
RETURN_UNSUPPORTED: “Unsupported”
示例说明:
对于flags的’+’,虽然对type(类型)x和X都有效,不过因为x和X都是以无符号来处理参数的,个人觉得没有什么作用。
INTN a=-234;
Print(“a=%+d\n”,a);
Print(“a=0x%+x\n”,a);
输出为:
a=-234
a=0xFFFFFF16
比较常用,也容易搞错的类型是’a’、’S’和’s’。含义与ANSI中完全不同,主要用来区分UEFI下ANSI字符串和Unicode字符串。
CHAR8 * str=”Hello, UEFI World!\n”;
Print(L”%a”,str);
输出:
Hello,UEFI World!
在编程时,针对两种编码,在使用时需要注意。比如上述例子,习惯性会使用”%s”去打印,当然是什么都打印不出来的,因为str不是有效的Unicode字符串。
3 常用打印相关函数
UINTN EFIAPI Print(IN CONST CHAR* Format, …)
参数:
Format:以Null结尾的Unicode字符串
…:按格式化规则给定的变量参数列表
返回:
按格式输出变量到ConOut
函数说明:
按照Format中给出的格式化字符串,通过ConOut输出变量。输出变量的大小如果大于PcdUefiLibMaxPrintBufferSize,则按照此长度截断,输出到ConOut。
UINTN EFIAPI PrintXY ( IN UINTN PointX,
IN UINTN PointY,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * ForeGround,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BackGround,
IN CONST CHAR16 * Format,
…
)
参数:
PointX: 显示字符串位置的X坐标
PointY: 显示字符串位置的Y坐标
ForeGround: 字符串显示的字体颜色,可设置为NULL,直接使用ConOut设备的
背景色
BackGround: 字符串显示的字体背景颜色,可设置为NULL,直接使用ConOut设
备的背景色
Format: 以NULL结尾的Unicode格式化字符串。
…:按格式化规则给定的变量参数列表
返回:
按格式输出变量
函数说明:
按照Format中给出的格式化字符串,在图形模式下,通过ConOutputHandle输出变量,输出位置在(PointX,PointY)。如果输出位置超过显示规定的边缘,则显示的图像会被截断。可配合HII来实现显示。
UINTN EFIAPI AsciiPrint ( IN CONST CHAR8 * Format, … )
参数:
Format:以Null结尾的ASCII字符串
…:按格式化规则给定的变量参数列表
返回:
按格式输出变量到ConOut
函数说明:
按照Format中给出的格式化字符串,通过ConOut输出变量。输出变量的大小如果大于PcdUefiLibMaxPrintBufferSize,则按照此长度截断,输出到ConOut。
其他函数:
UINTN EFIAPI StrLen ( IN CONST CHAR16 * String ) ;
UINTN EFIAPI AsciiStrLen ( IN CONST CHAR8 * String ) ;
CHAR16* EFIAPI StrCpy ( OUT CHAR16 * Destination,
IN CONST CHAR16 * Source );
CHAR8* EFIAPI AsciiStrCpy ( OUT CHAR8 * Destination,
IN CONST CHAR8 * Source );
INTN EFIAPI StrCmp ( IN CONST CHAR16 * FirstString,
IN CONST CHAR16 * SecondString );
INTN EFIAPI AsciiStrCmp ( IN CONST CHAR8 * FirstString,
IN CONST CHAR8 * SecondString );
CHAR8* EFIAPI UnicodeStrToAsciiStr ( IN CONST CHAR16 * Source,
OUT CHAR8 * Destination );
CHAR16* EFIAPI AsciiStrToUnicodeStr ( IN CONST CHAR8 * Source,
OUT CHAR16 * Destination );
1,119 total views, 3 views today
Recommend
-
16
UEFI开发探索59-UDK Debugger Tool调试Firmware 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.c...
-
15
UEFI开发探索58-UTF-8编码问题 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】...
-
15
UEFI开发探索56-使用WSL编译Arm架构的UEFI镜像 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/aut...
-
18
UEFI开发探索55 – UEFI与网络5(IPv6) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】...
-
10
UEFI开发探索54 – UEFI与网络4(IPv4) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
-
37
UEFI开发探索50 – UEFI与网络2 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
-
10
UEFI开发探索64- VS2015调试UEFI代码(续27、53篇) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiy...
-
13
UEFI开发探索65- YIE001开发板(01开篇) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog...
-
12
UEFI开发探索66- YIE001开发板(02 UEFI驱动) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luob...
-
10
UEFI开发探索72- YIE002USB开发板(01 开篇) 请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK