当前位置: 首页 > news >正文

UEFI实战--------HII之uni文件

uni文件
HII的实现涉及到多种不同类型的文件,uni文件是其中最简单的一种,它用来存放各种语言的字符串以实现本地化。本节主要参考自《edk-ii-uni-specification.pdf》,后面简称为参考文档。

关于uni文件的作用,在参考文档中做了如下的说明:

RFC4646标准中定义了语言标签(Tags for Identifying Languages),在这个标准下,每一个语言标签由一个由2个小写字母组成的语言标签和一个由2个大写字母组成的国家/区域的国际域名缩写构成,比如en-US表示美式英语,zh-CN表示简体中文,在uni文件中,就用这个来表示本地化语言。UCS-2表示用2个字节表示的通用字符集,UCS-2中的2表示的是2个字节,所以uni文件最终转换成二进制的时候,每个字符都是由2个字节组成的。

总的来说,uni文件提供了一系列的**标记(Token)**用来指代字符串,这些字符串可以有不同的语言实现,但是在代码调用中都可以使用这些统一的标记来引用。以前面出现过的Front Page为例:

这里的Select Language就对应一个在uni文件中定义的标记(具体在MdeModulePkg\Application\UiApp\FrontPageStrings.uni文件中):

#string STR_LANGUAGE_SELECT #language en-US “Select Language”
#language fr-FR “Choisir la Langue”

可以看到,这里实际上支持两种语言,一种是英语一种是法语,所以Front Page中可以进行切换:

而在我们的代码中,实际上使用的都只是STR_LANGUAGE_SELECT这个标记:

HiiCreateOneOfOpCode (
StartOpCodeHandle,
FRONT_PAGE_KEY_LANGUAGE,
0,
0,
STRING_TOKEN (STR_LANGUAGE_SELECT), // 这个就是uni文件中定义的Token
STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
EFI_IFR_FLAG_CALLBACK,
EFI_IFR_NUMERIC_SIZE_1,
OptionsOpCodeHandle,
NULL
);

至于具体如何切换,这里暂不深入。

BNF语法表示
uni文件使用一种特定的语法来描述,并且使用了BNF的方式来描述这种语法,所以这里先简单介绍BNF。

BNF全称是巴科斯-诺尔形式(Backus-Naur form),前两个词表示的是人名。BNF是一种形式化的语法表示方式,用来描述语法的一种形式体系,是一种典型的元语言,目前基本所有的编程语言都会用它来表示该语言的语法规则。这里使用uni文件以及之后介绍的vfr文件,也都有对应BNF来描述,不过使用的是扩展的版本,称为EBNF。

要详细介绍EBNF使用规则过于复杂,这里根据实际的示例说明。比如下面的示例来自参考文档,它定义了最基本的一些语法概念:

::= " "
::= {(\u0041-\u005A)} ; Characters A - Z
{(\u0061-\u007A)} ; Characters a - z
::= (\u0030-\u0039) ; Characters 0 - 9
::= +
::= {} {}
::= “//” *
::=
::= (\u0001-\uF6FF)
::= {(\u0020-\uF6FF)} {}
::= “\x” [{} {}]{4} “”
::= (\u0021-\uF6FF)
::=
[ [ ]+]+
::= “language” <M
::= {}
{(\u0041-\u0046)} ; Characters A - F
{(\u0061-\u0066)} ; Characters a - f
::= * “#”
::= “string”
::= [{} {} {}]*
::=
::= {2,8} [ ]
::= “-” [{} {}]{1,8}
::= “-” [{} {}]{1,}
::= \u0022 ; Double Quote Character, "
::=

::= {} {}
::= “” {“narrow”} {“wide”} {}
{“n”} {“r”} {“t”} {“nbr”} {“”} {“'”}

BNF使用<>来定义一个符号,::=表示的意思是“被定义为”,""里面表示的是真正的字符,所以第一句:

::= " "
1
表示的就是定义了一个符号US,它表示的意思是“单个空格”。

::= {(\u0041-\u005A)} ; Characters A - Z
{(\u0061-\u007A)} ; Characters a - z

;之后的内容是注释,所以上面的话可以写成一句:

::= {(\u0041-\u005A)}{(\u0061-\u007A)}
1
{}表示重复,[]表示可选,()表示分组。不过这样似乎也不能解释上面的代码,可以明确的是表示的是a-z或A-Z中的一个字母。同理表示一个数字。

*表示0个或以上;+表示1个或以上;所以下述语句:

::= +
::= {} {}

表示多个空格。{}表示一行的结尾,所以表示若干个空格组成的一行。

以此类推,之后的内容就不多做介绍了,最终对于所有编程语言的语句都可以通过上述的方式来描述。

语言基础
关于uni文件中的语法可以用一句BNF表示:

::= *

+

以一个实际的例子做对比:

这里可以很明确的看到各个部分。

不过上述例子中还有一部分没有包含进去,就是/=#,它应该属于的一部分,称为ControlRefactor:

::= “/”
::= “=”
::= (0x0021 - 0xF6FF)

其中#的值是0x0023,所以是一个NewCtrlChar。不过目前不清楚这句代码的作用,似乎跟之后和中每行开头的#有关,但是也不是所有的uni文件中都包含它,没有它也能够正常使用字符串。

另外也不是所有的uni文件都包含,关于这些,在参考文档中并没有特别说明原因。

和两部分都比较简单,这里主要说明下,它的定义如下:

::= {} {}
{} {}
{} {}
{}

这里简单说明:

也可以包含,事实上注释可以出现在任何的位置,关于注释的表达式,就是以//开头的行;
空白行也随时可以出现;
是以#string开头的一个字符串(中间可以换行),它算是中最重要的部分,包含了真正用来定义并在其它文件中使用的标记;
在前面已有说明,含义不明;
也可以出现在中;
同样含义不明;
是用来包含其它uni文件的,像下面那样:
#include “MiscBaseBoardManufacturer.uni”
1
上述的定义中,最重要的就是了,它的定义如下:

::= “#string”
[]
[]+
::= “#language” lang-code
::= [] []+
::= [“#font” font-identifier> ]
::=

下面是一个具体的例子:

对于没有找到具体的例子。这里说明下它的定义:

“#fontdef” font-identifier
::= font-name font-size [ font-style-list]
font-style-list ::= [fs-entries]
fs-entries ::= font-style [“|” font-style]*
font-style ::= {“bold”} {“italic”} {“underline”} {“dblunder”}
{“shadow”} {“emboss”} {“normal”}
font-size ::= (1-9) (0-9)*

font是一个需要额外讨论的问题,这里暂时不介绍。

解析和使用
uni文件的解析和使用有两种方式,一种是将字符串解析成数组,然后通过代码手动来安装;另一种是将字符串解析为二进制放到BIOS中,然后会生成自动代码来安装,后续要使用的时候就直接通过打开指定GUID(gEfiHiiPackageListProtocolGuid)的Protocol来获取。

对应的代码示例是MdeModulePkg\Application\UiApp\UiApp.inf。首先通过inf文件查看其中使用的uni文件,有如下的几处:

[Defines]
MODULE_UNI_FILE = UiApp.uni

[Sources]
FrontPageStrings.uni

[UserExtensions.TianoCore.“ExtraFiles”]
UiAppExtra.uni

这个示例中使用到了3处uni文件,这里分别说明:

MODULE_UNI_FILE对应的是模块本身的摘要和描述,一般情况下UEFI中的模块默认有一个英文版本的摘要和描述,如果要增加其它语言版本,就可以通过这个MODULE_UNI_FILE指定uni文件来实现,当然它本身也还可以是英文的。本例中它的内容如下:
#string STR_MODULE_ABSTRACT
#language en-US
“UiApp module is driver for BDS phase.”

#string STR_MODULE_DESCRIPTION
#language en-US
“UiApp module is driver for BDS phase.”

它不会被包含到BIOS二进制里面,不用特别关注。

[Sources]中的是实际BIOS使用的字符串,后面会详细介绍。
[UserExtensions.TianoCore.“ExtraFiles”]中的文件也不会被BIOS二进制包含,对应文件UiAppExtra.uni中的内容:
#string STR_PROPERTIES_MODULE_NAME #language en-US “UiApp module”
1
它用于UEFI发布,也可以不用特别关注。

所以实际上真正有用的仅仅是在[Sources]中的uni文件。

在build工具中会通过uni文件生成hpk二进制文件,对应的文件名可以在BaseTools\Source\Python\AutoGen\ModuleAutoGen.py中找到:

gAutoGenStringFormFileName = “%(module_name)sStrDefs.hpk”
1
所以本例中生成的就是UiAppStrDefs.hpk(注意替换的是%(module_name)s):

hpk文件是一种压缩文件,可以通过工具查看,这里有一个在线的版本:https://filext.com/file-extension/HPK,得到的内容:

对应的FrontPageStrings.uni文件的内容:

/=#

#langdef en-US “English”
#langdef fr-FR “Français”
#langdef en “Standard English”
#langdef fr “Standard Français”

#string STR_FRONT_PAGE_TITLE #language en-US “Front Page”
#language fr-FR “Front Page”
#string STR_FRONT_PAGE_COMPUTER_MODEL #language en-US “”
#language fr-FR “”
#string STR_FRONT_PAGE_CPU_MODEL #language en-US “”
#language fr-FR “”
#string STR_FRONT_PAGE_CPU_SPEED #language en-US “”
#language fr-FR “”
#string STR_FRONT_PAGE_MEMORY_SIZE #language en-US “”
#language fr-FR “”
#string STR_FRONT_PAGE_BIOS_VERSION #language en-US “”
#language fr-FR “”
#string STR_FRONT_PAGE_BANNER_0_LEFT #language en-US “Wonder Computer Model 1000Z Manufactured by Intel®”
#language fr-FR “Demander le Modèle d’Ordinateur 1000Z A Fabriqué par Intel®”
#string STR_FRONT_PAGE_BANNER_0_RIGHT #language en-US “OK”
#language fr-FR “Bon”
#string STR_FRONT_PAGE_BANNER_1_LEFT #language en-US “2 Pentium® X Xeon processors running at 800Thz”
#language fr-FR “2 processeurs Pentium® X Xeon tournants à 800Thz”
#string STR_FRONT_PAGE_BANNER_1_RIGHT #language en-US “24 TB System RAM”
#language fr-FR “24 TB RAM de Système”
#string STR_FRONT_PAGE_BANNER_2_LEFT #language en-US “ACME® EFI BIOS Version 13.5 Release 1039.92”
#language fr-FR “ACME® EFI BIOS Version 13.5 Release 1039.92”
#string STR_FRONT_PAGE_BANNER_3_LEFT #language en-US “Serial Number: 1Z123456789MARMAR (Need SMBIOS entries)”
#language fr-FR “Numéro de série: 1Z123456789MARMAR (Les entrées de SMBIOS de besoin)”
#string STR_CONTINUE_PROMPT #language en-US “Continue”
#language fr-FR “Continuer”
#string STR_CONTINUE_HELP #language en-US “This selection will direct the system to continue to booting process”
#language fr-FR “Cette sélection dirigera le système pour continuer au processus d’amorçage”
#string STR_LANGUAGE_SELECT #language en-US “Select Language”
#language fr-FR “Choisir la Langue”
#string STR_LANGUAGE_SELECT_HELP #language en-US “This is the option one adjusts to change the language for the current system”
#language fr-FR “Ceci est l’option qu’on ajuste pour changer la langue pour le système actuel”
#string STR_MISSING_STRING #language en-US “Missing String”
#language fr-FR “Missing String”
#string STR_EMPTY_STRING #language en-US “”
#language fr-FR “”
#string STR_RESET_STRING #language en-US “Reset”
#language fr-FR “Reset”
#string STR_RESET_STRING_HELP #language en-US “Reset the current setting.”
#language fr-FR “Reset the current setting.”
#string STR_CUSTOMIZE_BANNER_LINE4_LEFT #language en-US “”
#language fr-FR “”
#string STR_CUSTOMIZE_BANNER_LINE4_RIGHT #language en-US “”
#language fr-FR “”
#string STR_CUSTOMIZE_BANNER_LINE5_LEFT #language en-US “”
#language fr-FR “”
#string STR_CUSTOMIZE_BANNER_LINE5_RIGHT #language en-US “”
#language fr-FR “”
#string STR_TEST_KEY_USED #language en-US “WARNING: Test key detected.”
#language fr-FR “WARNING: Test key detected.”
#string STR_NULL_STRING #language en-US " "
#language fr-FR " "

可以看到hpk文件中并没有包含上述所有的字符串,那是因为对于没有在代码中用到的标记,就不会包含到hpk文件中的。

除了二进制文件,在AutoGen.c中同样可以看到字符串转换成的数组:

//
//Unicode String Pack Definition
//
unsigned char UiAppStrings[] = {

// STRGATHER_OUTPUT_HEADER
0x26, 0x04, 0x00, 0x00,

// PACKAGE HEADER

0xB4, 0x01, 0x00, 0x04, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x6E,
0x2D, 0x55, 0x53, 0x00,

// PACKAGE DATA

// 0x0001: $PRINTABLE_LANGUAGE_NAME:0x0001
0x14, 0x45, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x00,
0x00,
// 0x0002: STR_FRONT_PAGE_TITLE:0x0002
0x14, 0x46, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61,
0x00, 0x67, 0x00, 0x65, 0x00, 0x00, 0x00,
// 0x0003: STR_FRONT_PAGE_COMPUTER_MODEL:0x0003
0x14, 0x00, 0x00,
// 0x0004: STR_FRONT_PAGE_CPU_MODEL:0x0004
0x14, 0x00, 0x00,
// 0x0005: STR_FRONT_PAGE_CPU_SPEED:0x0005
0x14, 0x00, 0x00,
// 0x0006: STR_FRONT_PAGE_MEMORY_SIZE:0x0006
0x14, 0x00, 0x00,
// 0x0007: STR_FRONT_PAGE_BIOS_VERSION:0x0007
0x14, 0x00, 0x00,
// 0x0008: STR_CONTINUE_PROMPT:0x0008
0x14, 0x43, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x75, 0x00, 0x65,
0x00, 0x00, 0x00,
// 0x0009: STR_LANGUAGE_SELECT:0x0009
0x14, 0x53, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4C,
0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x75, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x00,
0x00,
// 0x000A: STR_LANGUAGE_SELECT_HELP:0x000A
0x14, 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20,
0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69,
0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61,
0x00, 0x64, 0x00, 0x6A, 0x00, 0x75, 0x00, 0x73, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74,
0x00, 0x6F, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x65,
0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E,
0x00, 0x67, 0x00, 0x75, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6F,
0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x75,
0x00, 0x72, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x20, 0x00, 0x73, 0x00, 0x79,
0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x00, 0x00,
// 0x000B: STR_MISSING_STRING:0x000B
0x14, 0x4D, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x20,
0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x00, 0x00,
// 0x000C: STR_EMPTY_STRING:0x000C
0x14, 0x00, 0x00,
// 0x000D: STR_RESET_STRING:0x000D
0x14, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74, 0x00, 0x00, 0x00,
// 0x000E: STR_CUSTOMIZE_BANNER_LINE4_LEFT:0x000E
0x14, 0x00, 0x00,
// 0x000F: STR_CUSTOMIZE_BANNER_LINE4_RIGHT:0x000F
0x14, 0x00, 0x00,
// 0x0010: STR_CUSTOMIZE_BANNER_LINE5_LEFT:0x0010
0x14, 0x00, 0x00,
// 0x0011: STR_CUSTOMIZE_BANNER_LINE5_RIGHT:0x0011
0x14, 0x00, 0x00,
// 0x0012: STR_TEST_KEY_USED:0x0012
0x14, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x4E, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x47, 0x00, 0x3A,
0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6B, 0x00, 0x65,
0x00, 0x79, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74,
0x00, 0x65, 0x00, 0x64, 0x00, 0x2E, 0x00, 0x00, 0x00,
// 0x0013: STR_NULL_STRING:0x0013
0x14, 0x20, 0x00, 0x00, 0x00,
0x00,
// PACKAGE HEADER

0xBC, 0x01, 0x00, 0x04, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x72,
0x2D, 0x46, 0x52, 0x00,

// PACKAGE DATA

// 0x0001: $PRINTABLE_LANGUAGE_NAME:0x0001
0x14, 0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0xE7, 0x00, 0x61, 0x00, 0x69, 0x00, 0x73,
0x00, 0x00, 0x00,
// 0x0002: STR_FRONT_PAGE_TITLE:0x0002
0x14, 0x46, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61,
0x00, 0x67, 0x00, 0x65, 0x00, 0x00, 0x00,
// 0x0003: STR_FRONT_PAGE_COMPUTER_MODEL:0x0003
0x14, 0x00, 0x00,
// 0x0004: STR_FRONT_PAGE_CPU_MODEL:0x0004
0x14, 0x00, 0x00,
// 0x0005: STR_FRONT_PAGE_CPU_SPEED:0x0005
0x14, 0x00, 0x00,
// 0x0006: STR_FRONT_PAGE_MEMORY_SIZE:0x0006
0x14, 0x00, 0x00,
// 0x0007: STR_FRONT_PAGE_BIOS_VERSION:0x0007
0x14, 0x00, 0x00,
// 0x0008: STR_CONTINUE_PROMPT:0x0008
0x14, 0x43, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x75, 0x00, 0x65,
0x00, 0x72, 0x00, 0x00, 0x00,
// 0x0009: STR_LANGUAGE_SELECT:0x0009
0x14, 0x43, 0x00, 0x68, 0x00, 0x6F, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20,
0x00, 0x6C, 0x00, 0x61, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x75,
0x00, 0x65, 0x00, 0x00, 0x00,
// 0x000A: STR_LANGUAGE_SELECT_HELP:0x000A
0x14, 0x43, 0x00, 0x65, 0x00, 0x63, 0x00, 0x69, 0x00, 0x20, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74,
0x00, 0x20, 0x00, 0x6C, 0x00, 0x27, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F,
0x00, 0x6E, 0x00, 0x20, 0x00, 0x71, 0x00, 0x75, 0x00, 0x27, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20,
0x00, 0x61, 0x00, 0x6A, 0x00, 0x75, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70,
0x00, 0x6F, 0x00, 0x75, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6E,
0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x20, 0x00, 0x6C,
0x00, 0x61, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x75, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x6F,
0x00, 0x75, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x79,
0x00, 0x73, 0x00, 0x74, 0x00, 0xE8, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63,
0x00, 0x74, 0x00, 0x75, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x00, 0x00,
// 0x000B: STR_MISSING_STRING:0x000B
0x14, 0x4D, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x20,
0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x00, 0x00,
// 0x000C: STR_EMPTY_STRING:0x000C
0x14, 0x00, 0x00,
// 0x000D: STR_RESET_STRING:0x000D
0x14, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x74, 0x00, 0x00, 0x00,
// 0x000E: STR_CUSTOMIZE_BANNER_LINE4_LEFT:0x000E
0x14, 0x00, 0x00,
// 0x000F: STR_CUSTOMIZE_BANNER_LINE4_RIGHT:0x000F
0x14, 0x00, 0x00,
// 0x0010: STR_CUSTOMIZE_BANNER_LINE5_LEFT:0x0010
0x14, 0x00, 0x00,
// 0x0011: STR_CUSTOMIZE_BANNER_LINE5_RIGHT:0x0011
0x14, 0x00, 0x00,
// 0x0012: STR_TEST_KEY_USED:0x0012
0x14, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x4E, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x47, 0x00, 0x3A,
0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6B, 0x00, 0x65,
0x00, 0x79, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74,
0x00, 0x65, 0x00, 0x64, 0x00, 0x2E, 0x00, 0x00, 0x00,
// 0x0013: STR_NULL_STRING:0x0013
0x14, 0x20, 0x00, 0x00, 0x00,
0x00,
// PACKAGE HEADER

0x58, 0x00, 0x00, 0x04, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x6E,
0x00,

// PACKAGE DATA

// 0x0001: $PRINTABLE_LANGUAGE_NAME:0x0001
0x14, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64,
0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
0x00, 0x00, 0x00,
0x21, 0x12, 0x00,
0x00,
// PACKAGE HEADER

0x5A, 0x00, 0x00, 0x04, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x72,
0x00,

// PACKAGE DATA

// 0x0001: $PRINTABLE_LANGUAGE_NAME:0x0001
0x14, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00, 0x64,
0x00, 0x20, 0x00, 0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0xE7, 0x00, 0x61, 0x00, 0x69,
0x00, 0x73, 0x00, 0x00, 0x00,
0x21, 0x12, 0x00,
0x00,

};

比较hpk二进制文件,可以看到跟数组是有对应关系的:

AutoGen.c中生成的字符串来自脚本BaseTools\Source\Python\AutoGen\GenC.py:

if EDK2Module:FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.RFCLanguages]
else:FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.ISOLanguages]
Header, Code = GetStringFiles(Info.UnicodeFileList, SrcList, IncList, Info.IncludePathList, ['.uni', '.inf'], Info.Name, CompatibleMode, ShellMode, UniGenCFlag, UniGenBinBuffer, FilterInfo)
if CompatibleMode or UniGenCFlag:AutoGenC.Append("\n//\n//Unicode String Pack Definition\n//\n")AutoGenC.Append(Code)AutoGenC.Append("\n")

从这里可以看到一点,AutoGen.c中的字符串数组并不是一定会生成的,而是有一定的条件(if CompatibleMode or UniGenCFlag:)。在更上层的函数调用中有:

Create code for a module

@param Info The ModuleAutoGen object

@param AutoGenC The TemplateString object for C code

@param AutoGenH The TemplateString object for header file

@param StringH The TemplateString object for header file

@param UniGenCFlag UniString is generated into AutoGen C file when it is set to True

@param UniGenBinBuffer Buffer to store uni string package data

@param StringIdf The TemplateString object for header file

@param IdfGenCFlag IdfString is generated into AutoGen C file when it is set to True

@param IdfGenBinBuffer Buffer to store Idf string package data

def CreateCode(Info, AutoGenC, AutoGenH, StringH, UniGenCFlag, UniGenBinBuffer, StringIdf, IdfGenCFlag, IdfGenBinBuffer):
CreateHeaderCode(Info, AutoGenC, AutoGenH)

这里可以看到# @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True,它可以确定是否要在AutoGen.c中创建字符串数组变量。而UniGenCFlag 来自:

AutoGenUniIdf = self.BuildType != ‘UEFI_HII’
1
对于UiApp模块来说,它的BuildType是UEFI_APPLICATION,所以AutoGenUniIdf就是True,这样就一定会在AutoGen.c中创建字符串数组。

而另外一个变量来自CompatibleMode:

if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-c') > -1:CompatibleMode = True
else:CompatibleMode = False

它判断构建参数,可以通过Makefile看到,也可以通过修改对应的Python脚本增加打印查看,比如当前模块:

Building … defaultdict(<function PlatformInfo.ApplyBuildOption.. at 0x000001D88B6D96C0>, {‘ASLPP’: defaultdict(<class ‘str’>, {‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’, ‘FLAGS’: ’ /nologo /E /C /FIAutoGen.h’, ‘FAMILY’: ’ MSFT’}), ‘PKCS7SIGN’: defaultdict(<class ‘str’>, {‘PATH’: ‘Pkcs7Sign’, ‘GUID’: ’ 4AAFD29D-68DF-49EE-8AA9-347D375665A7’, ‘FAMILY’: ’ MSFT’}), ‘VPDTOOL’: defaultdict(<class ‘str’>, {‘PATH’: ‘BPDG’, ‘GUID’: ’ 8C3D856A-9BE6-468E-850A-24F7A8D38E08’, ‘FAMILY’: ’ MSFT’}), ‘ASLDLINK’: defaultdict(<class ‘str’>, {‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\link.exe’, ‘FLAGS’: ’ /NODEFAULTLIB /ENTRY:ReferenceAcpiTable /SUBSYSTEM:CONSOLE’, ‘FAMILY’: ’ MSFT’}), ‘GENFW’: defaultdict(<class ‘str’>, {‘PATH’: ‘GenFw’, ‘FLAGS’: ’ ‘, ‘FAMILY’: ’ MSFT’}), ‘SLINK’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\lib.exe’, ‘FLAGS’: ’ /NOLOGO /LTCG’}), ‘OBJCOPY’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘ADDDEBUGFLAG’: ’ --add-gnu-debuglink=(DEBUGDIR)/(DEBUG_DIR)/(DEBUGDIR)/(MODULE_NAME).debug’, ‘PATH’: ‘echo’, ‘FLAGS’: ’ objcopy not needed for’}), ‘DEPS’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ /showIncludes’}), ‘ASM’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ /nologo /c /WX /W3 /Cx /Zd /Zi’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\ml64.exe’}), ‘CC’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Z7 /Gw /D DISABLE_NEW_DEPRECATED_INTERFACES /D ENABLE_MD5_DEPRECATED_INTERFACES’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’}), ‘ASMLINK’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\WINDDK\3790.1830\bin\bin16\link16.exe’, ‘FLAGS’: ’ /nologo /tiny’}), ‘TIANO’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘TianoCompress’, ‘GUID’: ’ A31280AD-481E-41B6-95E8-127F4C984779’}), ‘LZMA’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘LzmaCompress’, ‘GUID’: ’ EE4E5898-3914-4259-9D6E-DC7BD79403CF’}), ‘VFR’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘VfrCompile’, ‘FLAGS’: ’ -l -n’}), ‘ASLCC’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’, ‘FLAGS’: ’ /nologo /c /FIAutoGen.h /TC /Dmain=ReferenceAcpiTable’}), ‘APP’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’, ‘FLAGS’: ’ /nologo /E /TC’}), ‘NASM’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ -Ox -f win64 -g’, ‘PATH’: ‘C:\nasm\nasm’}), ‘OPTROM’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘EfiRom’, ‘FLAGS’: ’ -e’}), ‘DTC’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ -H epapr’, ‘PATH’: ‘dtc’}), ‘MAKE’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\nmake.exe’, ‘FLAGS’: ’ /nologo’}), ‘SYMRENAME’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘echo’, ‘FLAGS’: ’ Symbol renaming not needed for’}), ‘ASM16’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\ml.exe’}), ‘LZMAF86’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘LzmaF86Compress’, ‘GUID’: ’ D42AE6BD-1352-4bfb-909A-CA72A6EAE889’}), ‘CRC32’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘GenCrc32’, ‘GUID’: ’ FC1BCDB0-7D31-49AA-936A-A4600D9DD083’}), ‘BROTLI’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘BrotliCompress’, ‘GUID’: ’ 3D532050-5CDA-4FD0-879E-0F7F630D5AFB’}), ‘RC’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Windows Kits\10\bin\10.0.20348.0\x86\rc.exe’}), ‘PP’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’, ‘FLAGS’: ’ /nologo /E /TC /FIAutoGen.h’}), ‘VFRPP’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\cl.exe’, ‘FLAGS’: ’ /nologo /E /TC /DVFRCOMPILE /FIKaTeX parse error: Expected 'EOF', got '}' at position 24: …NAME)StrDefs.h'}̲), 'DLINK': def…(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG’, ‘PATH’: ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x64\link.exe’}), ‘RSA2048SHA256SIGN’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘Rsa2048Sha256Sign’, ‘GUID’: ’ A7717414-C616-4977-9420-844712A735BF’}), ‘ASL’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’: ‘C:\ASL\iasl.exe’, ‘FLAGS’: ’ ‘, ‘OUTFLAGS’: ’ -p’}), ‘NASMB’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ -f bin’}), ‘DLINK2’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘FLAGS’: ’ /WHOLEARCHIVE’}), ‘DTCPP’: defaultdict(<class ‘str’>, {‘FAMILY’: ’ MSFT’, ‘PATH’:
‘cpp’}), ‘BUILD’: defaultdict(<class ‘str’>, {‘FLAGS’: ‘’})})
1
2
这里面并没有-c这个参数,所以CompatibleMode的值就是False。不过因为AutoGenUniIdf是True,所以还是会创建字符串数组的。

对应的有另外一个示例MdeModulePkg\Universal\HiiResourcesSampleDxe\HiiResourcesSampleDxe.inf,它的类型是UEFI_HII的,且没有-c参数,所以就不会在AutoGen.c中创建字符串数组。查看HiiResourcesSampleDxe.inf这个模块,有一个选项:

[Defines]

This flag specifies whether HII resource section is generated into PE image.

UEFI_HII_RESOURCE_SECTION = TRUE

UEFI_HII_RESOURCE_SECTION表示是否要将hpk文件放到efi二进制中。默认是FALSE的,所以对于UiApp来说hpk文件是不会包含在二进制中。当值是TRUE的时候,这个模块就变成了UEFI_HII,此时如果不涉及兼容性的话,就不会在AutoGen.c中创建字符串了,如果将上述代码加到UiApp这个模块中,就会报错:

f:\gitee\edk2-beni\MdeModulePkg\Application\UiApp\FrontPage.c(285): error C2065: ‘UiAppStrings’: undeclared identifier
1
这两种创建字符串的方式目前都有在使用,且使用hpk二进制文件的方式似乎比较新一点(不过也是2010年的事情了)。

以上介绍的是创建字符串资源的方式,下面介绍如何使用。

对于通过中间文件生成数组的方式,直接在代码中使用该数组即可,比如这里使用的UiAppStrings,可以找到对应的安装资源的代码,位于MdeModulePkg\Application\UiApp\FrontPage.c:

//
// Publish our HII data
//
gFrontPagePrivate.HiiHandle = HiiAddPackages (
&mFrontPageGuid,
gFrontPagePrivate.DriverHandle,
FrontPageVfrBin,
UiAppStrings,
NULL
);
ASSERT (gFrontPagePrivate.HiiHandle != NULL);

对于使用二进制文件过的方式,可以参看前面提到的HiiResourcesSampleDxe.inf模块,在MdeModulePkg\Universal\HiiResourcesSampleDxe\HiiResourcesSample.c代码中有:

//
// Retrieve HII package list from ImageHandle
//
Status = gBS->OpenProtocol (
ImageHandle,
&gEfiHiiPackageListProtocolGuid,
(VOID **) &PackageList,
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}

//
// Publish HII package list to HII Database.
//
Status = gHiiDatabase->NewPackageList (
gHiiDatabase,
PackageList,
mDriverHandle,
&mHiiHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
————————————————

相关文章:

UEFI实战--------HII之uni文件

uni文件 HII的实现涉及到多种不同类型的文件&#xff0c;uni文件是其中最简单的一种&#xff0c;它用来存放各种语言的字符串以实现本地化。本节主要参考自《edk-ii-uni-specification.pdf》&#xff0c;后面简称为参考文档。 关于uni文件的作用&#xff0c;在参考文档中做了如…...

基于Spring Boot集成MyBatis-3.5.9操作数据库

记录&#xff1a;382场景&#xff1a;在Spring Boot 2.6.3中集成MyBatis 3.5.9操作数据库。实现MyBatis的查、增、改、删操作数据库示例。MyBatis官网&#xff1a;http://www.mybatis.org/MyBatis源码&#xff1a;https://github.com/mybatis/1.初始化准备1.1创建Maven工程使用…...

了解国外SEO负面压制的现状与应对策略!

随着全球化的发展&#xff0c;越来越多的企业和品牌开始将目光转向海外市场&#xff0c;而谷歌作为全球最大的搜索引擎之一&#xff0c;也成为了外贸企业最主要的搜索引擎之一。 然而&#xff0c;随着谷歌的不断发展&#xff0c;国外SEO负面压制的现状也愈发严峻&#xff0c;外…...

Yolov5-交通标志检测与识别

项目介绍 上一篇文章介绍了基于卷积神经网络的交通标志分类识别Python交通标志识别基于卷积神经网络的保姆级教程&#xff08;Tensorflow&#xff09;&#xff0c;并且最后实现了一个pyqt5的GUI界面&#xff0c;并且还制作了一个简单的Falsk前端网页实现了前后端的一个简单交互…...

Linux内核Thermal框架详解五、Thermal Core(4)

本文部分内容参考Linux Thermal 学习笔记 - 爱码网。特此致谢&#xff01; 接前一篇文章Linux内核Thermal框架详解四、Thermal Core&#xff08;3&#xff09; 三、相关源码及分析 2. thermal_register_governors 上一回说到这一段代码&#xff1a; for (__governor __gove…...

gcc 编译的过程

#include <stdio.h> #define PI 3.14 int main(int argc, char const *argv[]) { //打印IP的值printf("PI %lf\n", PI);return 0; }编译的过程&#xff1a;预处理、编译、汇编、链接1.预处理&#xff1a;宏替换、删除注释、头文件包含、条件编译 -E &#xf…...

Hadoop入个门

文章目录1️⃣、Hadoop概述1.1、Hadoop是什么1.2、三大发行版本1.3、优势1.4、组成HDFSYARNMapReduceHDFS、YARN、MapReduce三者关系1.6、大数据技术生态体系image-202303111027195802️⃣、Hadoop运行环境搭建2.1、虚拟机环境准备2.2、克隆虚拟机2.3、在hadoop2上安装JDK2.4、…...

python 从0到批量下载某站视频

简介&#xff1a;真实从0到1&#xff0c;童叟无欺&#xff5e; 目标&#xff1a;用python批量下载某站搜索视频&#xff0c;以“CG 服装”为例 本章主要介绍如何用python把搜索到的视频直接下载到自己的本地文件夹中&#xff5e; 介绍一下工作流1. 下载并安装python2. 测试pyt…...

【深度学习】神经网络和深度学习--卷积和池化的作用

深度学习通常指训练大型深度的神经网络的过程。 与传统的神经网络模型相比&#xff0c;深度学习模型在结构上与之非常相似&#xff1b;不同的是&#xff0c;深度学习模型的“深度”更大&#xff0c;“深度”的体现就是神经网络层数多&#xff0c;神经网络每一层的结点数多。 本…...

锦正茂风冷系列电源JCP-10-80的技术参数

JCP-10-80为高稳定度的双极性恒流电源&#xff0c;广泛应用于电磁铁、亥姆霍兹线圈等感性负载的励磁。电源采用线性电源结构&#xff0c;输出电流稳定度高&#xff0c;纹波和噪声低。电源输出电流可在正负额定电流*值之间连续变化&#xff0c;电流平滑连续过零&#xff0c;可使…...

Idea+maven+spring-cloud项目搭建系列--11-1 dubbo(zookeeper,nacos)注册中心

前言&#xff1a;dubbo rpc 服务需要将服务提供者和消费者信息进行注册&#xff0c;以便于消费端可以完成远程接口调用&#xff1b;注册中心是 Dubbo 服务治理的核心组件&#xff0c;Dubbo 依赖注册中心的协调实现服务&#xff08;地址&#xff09;发现&#xff0c;自动化的服务…...

Python3入门教程||Python3 迭代器与生成器||Python3 函数

Python3 迭代器与生成器 迭代器 迭代是 Python 最强大的功能之一&#xff0c;是访问集合元素的一种方式。。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器有两…...

快速幂算法

快速幂算法 文章目录快速幂算法一、简单介绍二、计算7107^{10}710三、一般化1、计算ana^nan的快速方法&#xff1a;2、时间复杂度分析&#xff1a;四、代码五、参考资料一、简单介绍 ​ 快速幂&#xff08;Exponentiation by squaring&#xff0c;平方求幂&#xff09;是一种简…...

Hudi:问题总结(2)Flink-1.13.1消费kafka并插入hudi

问题一&#xff1a;java.lang.ClassNotFoundException: com.google.protobuf.MessageOrBuilder) 解决&#xff1a;字面意思&#xff0c;没找到类&#xff0c;将protobuf-java-3.2.0-jar包放到fink/lib/下 如果报commons-cli相关的错&#xff0c;就将commons-cli-1.4.jar放到f…...

Application工具方法

//注册这个接口registerActivityLifecycleCallbacks(activityLifecycleCallbacks);}Overridepublic void onTerminate() {//注销这个接口。unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);super.onTerminate();}public static List<Activity> activi…...

电脑游戏怎么录屏?其实很简单,只需要简单3步

电脑游戏一直是游戏爱好者最热衷的游戏之一。但是&#xff0c;有时候我们想分享我们在游戏中的精彩时刻&#xff0c;或者记录我们的游戏过程以便后续观看和学习。在这种情况下&#xff0c;录屏就成了必不可少的工具。但是&#xff0c;许多人可能不知道电脑游戏怎么录屏。在本文…...

【设计模式】go语言中的 [函数选项,单例,工厂,责任链] 常用的设计模式

文章目录前言一、函数选项模式二、单例模式三、工厂模式四、责任链模式前言 宿舍每人 温度38℃&#xff0b; 大寄 设计模式很重要&#xff0c;设计模式其实就是为了解决某一类问题而形成的代码写法&#xff0c;设计模式很多&#xff0c;但是并不是每个都很常用&#xff0c;我们…...

2017系统分析师案例分析真题背记内容

前言 以下内容仅为个人根据当年系分案例真题问题整理的偏需要记背的考点答案&#xff0c;方便个人背诵和记忆使用。方便文字转语音&#xff0c;所以内容全为纯文字内容&#xff0c;以下内容仅供参考。 背记内容 微服务 微服务中应该包含的内容有&#xff1a;资源、对资源的…...

C++和C的区别

答&#xff1a;从宏观角度和微观角度分析微观角度&#xff1a;函数原型有区别&#xff0c;在c中&#xff0c;函数原型有参数和没有参数是不同的&#xff0c;并且允许申明多个同名的函数&#xff0c;只要他们的参数列表不同或者返回值不同即可&#xff0c;但是在c语言中不能。C引…...

【React教程】一、React简介

一、React简介 React是一个用于构建用户界面的JavaScript库&#xff0c;它是Facebook的内部项目&#xff0c;用来架设Instagram的网站,并于2013年5月开源。React主要用于构建Ul&#xff0c;很多人认为React 是 MVC 中的 V&#xff08;视图&#xff09;。由于拥有较高的性能&…...

运动蓝牙耳机什么牌子好,比较好的运动蓝牙耳机推荐

现在市面上的运动蓝牙耳机越来越多&#xff0c;在选择耳机的时候应该如何入手呢&#xff1f;最重要的是需要按照自己的需求来选择&#xff0c;但在耳机的配置上不能忽视的是耳机的防水等级&#xff0c;运动耳机对防水等级的要求更高&#xff0c;这样能够更好地防御汗水浸湿耳机…...

[深入理解SSD系列 闪存实战2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?

前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...

DJI ROS dji_sdk 源码分析|整体框架

DJI ROS dji_sdk 源码分析|整体框架launch文件CMakeLists.txtcpp文件main.cppOSDK 是一个用于开发无人机应用程序的开发工具包&#xff0c;基于OSDK 开发的应用程序能够运行在机载计算机上&#xff08;如Manifold 2&#xff09;&#xff0c;开发者通过调用OSDK 中指定的接口能够…...

HT32合泰单片机开发环境搭建和配置教程

HT32合泰(Holtek)单片机开发环境搭建安装教程 前言 最近在准备合泰杯的比赛&#xff0c;在看合泰官方的PPT和数据手册学习&#xff0c;顺便做个合泰单片机的开发环境搭建教程。 合泰杯比赛发放的开发板是ESK32-30501&#xff0c;用的单片机是HT32F52352。 合泰杯官网地址&a…...

动态内存分配之伙伴算法

伙伴算法 伙伴算法是一种在计算机内存管理中使用的算法&#xff0c;用于分配和释放内存。它是一种基于二叉树的动态内存分配算法&#xff0c;可以高效地分配和合并内存块。伙伴算法是一种按照固定大小分配内存的算法&#xff0c;例如&#xff0c;每个内存块的大小为2的n次幂&a…...

CGAL 根据扫描线方向和角度对法向量进行重定向

目录一、算法原理1、主要函数二、代码实现一、算法原理 最小生成树对法向量定向的结果在具有许多尖锐特征和遮挡的机载点云数据中结果并不理想。scanline_orient_normals()是专门用于具有扫描线特性的点云法向量重定向的替代方法。它充分利用了某些激光雷达扫描器的LAS特性&…...

一个C#开发的开源的快速启动工具

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 平常计算机安装软件比较多、或者工作涉及的文件比较多&#xff0c;很多人都会直接放在桌面&#xff0c;一方面不安全&#xff0c;还不容易查找&#xff0c;这时候我们往往&#xff0c;都会放在其他硬盘内&#x…...

Paddle项目调试记录

PaddlePaddle是百度公司提出的深度学习框架。近年来深度学习在很多机器学习领域都有着非常出色的表现&#xff0c;在图像识别、语音识别、自然语言处理、机器人、网络广告投放、医学自动诊断和金融等领域有着广泛应用。面对繁多的应用场景&#xff0c;深度学习框架有助于建模者…...

3月11日,30秒知全网,精选7个热点

///微盟集团宣布接入百度文心一言 据介绍&#xff0c;微盟SaaS产品和数字营销服务将与文心一言的技术能力实现深度融合&#xff0c;通过AIGC技术&#xff0c;深化微盟在营销AI创意内容生产、智能营销、智能客服、智能经营等方面的布局 ///T3出行与华为云深化业务合作 双方将在…...

C win32基础学习(四)

上一篇我们已经介绍了关于窗口处理函数的知识。本篇我们说一下注册窗口类&#xff0c;创建窗口和显示窗口的内容。 前文 窗口创建过程 定义WinMain函数 定义窗口处理函数(自定义&#xff0c;处理消息) 注册窗口类&#xff08;向操作系统写入一些数据&#xff09; 创建窗口&…...

Java 日期时间API(Java 8及以上)

Java 8及以上版本提供了新的日期时间API&#xff0c;其中包括了LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Duration、Period等类&#xff0c;这些类提供了更加丰富和灵活的日期时间操作方法。 LocalDate LocalDate类表示一个本地日期&#xff0c;不包含时间和时区…...

DHCP的配置

实验目的熟悉DHCP的应用场景掌握DHCP的配置方法实验拓扑DHCP的配置如图15-2所示: 图15-2:DHCP的配置 实验步骤配置IP地址<Huawei>system-view Enter system view, return user view with Ctrl+Z....

JavaWeb14-线程池

目录 1.传统线程的缺点 2.线程池的定义 3.线程池的优点 4.线程池的创建/使用&#xff08;2类7种&#xff09; 4.1.通过Executors&#xff08;执行器&#xff09;自动创建&#xff08;6种&#xff09; ①Executors.newFixedThreadPool&#xff1a;创建⼀个固定⼤⼩的线程池…...

[qiankun+nuxt]子应用请求本地文件报错404

前言 目前公司的前端架构是qiankunnuxt做的微前端项目 问题说明 在子应用中&#xff0c;前端需要模拟一些数据&#xff0c;方便后期演示调整而不需要重新打包 所以将一些数据存储到了本地的json文件中&#xff0c;但是获取时报了404的错误&#xff0c;找不到该文件。 页面报错…...

【Qt网络编程】实现TCP协议通信

文章目录概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。一、TCP协议二、Qt中TCP协议处理1.QTcpSocket2.QTcpServer三、Qt实现TCP通信1.客户端2.服务器端结尾概要&#xff1a;本期主要讲解QT中对于TCP协议通信的实现。 一、TCP协议 传输控制协议&#xff08;TCP&am…...

Webpack打包———处理样式资源

基本使用 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个模块组合成一个或多个 bundles&a…...

VP记录:Codeforces Round 857 (Div. 2) A~D

传送门:CF A题 Likes: 这道题的题意很变态,十分的难懂,简直就是一坨shit,这场比赛最后被骂是有原因的 简单来说就是对于一个项目,每一个人都能对此加一或者减一,最后问你这个项目每一时刻最大和最小是多少.题目中只说明了只能点赞后才能取消,并没有解释存在取消操作必存在点…...

Docker常用项目实战演练

docker镜像源的修改 linux环境下编辑 /etc/docker/daemon.json vi /etc/docker/daemon.json #如添加如下网易镜像源 { "registry-mirrors": ["http://hub-mirror.c.163.com"] }docker run命令详细解释 日常工作中用的比较多的是docker run命令&#xff…...

Linux进程间通信-FIFO命名管道

Linux进程间通信-FIFO命名管道 1、概述 管道因为没有名称&#xff0c;所以只用于进程间的亲缘通信。为了克服这一缺点&#xff0c;提出了命名管道(FIFO)&#xff0c;又称命名管道、FIFO文件。 FIFO不同于无名管道&#xff0c;它提供与之关联的路径名&#xff0c;该路径名以FIF…...

【Kafka】记录一次基于connect-mirror-maker做的Kafka集群迁移完整过程

文章目录背景环境工具选型实操MM1MM2以MM2集群运行以Standalone模式运行验证附录MM2配置表其他背景 一个测试环境的kafka集群&#xff0c;Topic有360&#xff0c;Partition有2000&#xff0c;部署在虚拟机上&#xff0c;由于多方面原因&#xff0c;要求迁移至k8s容器内&#x…...

实现VOC数据集与COCO数据集格式转换

实现VOC数据集与COCO数据集格式转换2、将voc数据集的xml转化为coco数据集的json格式2、COCO格式的json文件转化为VOC格式的xml文件3、将 txt 文件转换为 Pascal VOC 的 XML 格式<annotation><folder>文件夹目录</folder><filename>图片名.jpg</file…...

常用的密码算法有哪些?

我们将密码算法分为两大类。 对称密码&#xff08;密钥密码&#xff09;——算法只有一个密钥。如果多个参与者都知道该密钥&#xff0c;该密钥 也称为共享密钥。非对称密码&#xff08;公钥密码&#xff09;——参与者对密钥的可见性是非对称的。例如&#xff0c;一些参与者仅…...

SNS (Simple Notification Service)简介

SNS (Simple Notification Service) 是一种完全托管的发布/订阅消息收发和移动通知服务&#xff0c;用于协调向订阅终端节点和客户端的消息分发。 和SQS (Simple Queue Service)一样&#xff0c;SNS也可以轻松分离和扩展微服务&#xff0c;分布式系统和无服务应用程序&#xf…...

JVM初步理解浅析

一、JVM的位置 JVM的位置 JVM在操作系统的上一层&#xff0c;是运行在操作系统上的。JRE是运行环境&#xff0c;而JVM是包含在JRE中 二、JVM体系结构 垃圾回收主要在方法区和堆&#xff0c;所以”JVM调优“大部分也是发生在方法区和堆中 可以说调优就是发生在堆中&#xf…...

【巨人的肩膀】MySQL面试总结(一)

&#x1f4aa; 目录&#x1f4aa;1、什么是ER图2、数据库范式了解吗3、超键、候选键、主键、外键分别是什么&#xff1f;4、为什么不推荐使用外键与级联5、什么是存储过程6、drop、delete与truncate区别7、数据库设计通常分为那几步8、什么是关系型数据库9、什么是SQL10、MySQL…...

【数据结构之树】——什么是树,树的特点,树的相关概念和表示方法以及在实际的应用。

文章目录一、1.树是什么&#xff1f;2.树的特点二、树的相关概念三、树的表示方法1.常规方法表示树2.使用左孩子右兄弟表示法3. 使用顺序表来存储父亲节点的下标三、树在实际的应用总结一、1.树是什么&#xff1f; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n&…...

JavaScript语法

文章目录一、JavaScript是什么&#xff1f;JavaScript引入方式二、基础语法书写语法输出语句变量数据类型运算符流程控制语句数组函数JS变量作用域对象一、JavaScript是什么&#xff1f; JavaScript&#xff1a;是一门跨平台的脚本语言&#xff0c;用来控制网页行为&#xff0…...

【BIOS/UEFI】HII 基本框架及概述

HII&#xff08;Human Interface Infrastructure &#xff09;定义了一套管理用户输入的基础框架。HII数据库主要提供用户安装、卸载以及使用各种字符串、字体和图片等资源的接口。 HID Devices 是用户输入设备&#xff0c;如键盘、串口和网络&#xff1b;Display Devices 是输…...

sprintf(...)溢出边界导致程序崩溃的问题

文章目录小结问题及解决参考小结 使用sprintf(...)进行格式化是一种标准的做法&#xff0c;但是这样做是有一个极大的风险&#xff0c;由于sprintf(...)不进行边界检查&#xff0c;这样会有写操作溢出边界的风险&#xff0c;并导致程序崩溃。本文进行了简单写操作溢出边界的测…...

公式推导+dfs简版

写在前面的话&#xff1a;心可以冷&#xff0c;但手不能停 第一题&#xff1a;C. Flexible String 题目大意&#xff1a;给一个aaa字符串和bbb字符串和数字kkk&#xff0c;首先设置一个计数器cntcntcnt,其中可以对aaa字符串做以下操作&#xff1a;替换aaa中的一个字母xxx&#…...