UEFI开发探索51 – UEFI下的打印函数

您所在的位置:网站首页 printcenter打印介面 UEFI开发探索51 – UEFI下的打印函数

UEFI开发探索51 – UEFI下的打印函数

2024-07-11 13:25| 来源: 网络整理| 查看: 265

(请保留-> 作者: 罗冰   https://blog.csdn.net/luobing4365)

原计划的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标准不同;    ● 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  );



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3