UEFI开发探索101 – PCD探究(helloworld中的使用)

Posted 毛毛虫的爹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UEFI开发探索101 – PCD探究(helloworld中的使用)相关的知识,希望对你有一定的参考价值。

2 如何使用PCD
PCD可以使用于UEFI存在的大部分时间,除了在SEC阶段、早期的PEI和DXE阶段,基本都可以访问。在使用前,我们需要搞清楚PCD的结构和类型。

2.1 PCD的类型
PCD变量的格式有点像结构体:

TokenSpaceGuidCName.PcdCName

其中,TokenSpaceGuidCName是GUID,而PcdCName是变量名,两者组合构成了一个PCD变量。

PCD有如下的类型。

FixedAtBuild类型
它在编译阶段确定,是静态值,在运行阶段或二进制形态下都不可改。可以认为它就是一个宏了。

FeatureFlag类型
它实际上和FixedAtBuild是同一类型,返回一个Bool类型(True或False),可用于判断条件。

PatchableInModule类型
此类型的变量值在编译的时候确定,它在编译后的二进制文件上使用工具修改。与FixedAtBuild不同,它只能影响一个模块(作用域在一个模块)。

Dynamic类型、DynamicHii类型和DynamicVpd类型
Dynamic类型变量的作用域是整个系统,它是动态的PCD,可以在UEFI运行过程中修改。

DynamicHii类型与Dynamic类型存储的位置不同,Dynamic类型可以认为是存在于Memory中,再加载是会失去原始设置的;而DynamicHii类型是存在Efi variable中的(NVRAM中),其修改时非易失性的。

而DynamicVpd类型变量是只读的,不可写的,一般出厂确定。

DynamicEx类型
与Dynamic类型类似,相当于加强版。其与Dynamic类型的区别,在于是否使用二进制文件中的PCD。比如FSP,如果要使用其中的PCD变量,则FSP中的PCD类型必须设置为### DynamicEx类型。

2.2 访问PCD变量
为管理PCD变量,PEI提供了PCD_PPI和EFI_PEI_PCD_PPI;DXE提供了PCD_PROTOCOL和EFI_PCD_PROTOCOL。

不过,为了方便使用,EDK2中引入了PCD Library,把这些访问细节隐藏了起来。(MdePkg\\Include\\Library\\PcdLib.h)

库中包含如下函数:

PcdGetXX()
PcdSetXX()
PcdGetExXX()
PcdSetExXX()
PcdToken()
PCDSetSku()
PcdGetNextToken()
PcdGetNextTokenSpace()
CallBackOnSet()
CancelCallBack()

其中,XX可以为8、16、32、Size、Ptr或者Boolean。

2.3 PCD的声明和使用
PCD的使用,基本可以按照如下流程进行。

DEC文件中声明PCD变量的基本信息,比如:
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes|1|UINT32|0x40000005
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString|L"UEFI Hello World!\\n"|VOID*|0x40000004

其格式为:

TokenSpaceGuidCname.PcdCname|DefaultValue|DatumType|Token

如前所述,PcdCname为变量名,DefaultValue为其默认值,DatumType是PCD的数据类型,Token是一个32位的整型,在DEC中每个PCD都有一个独有的Token。

DatumType可以是BOOLEAN、UINT8、UINT16、UINT32、UINT64或VOID *型。

DSC文件中设置PCD变量的值
可以在DSC文件中设置相应PCD变量的值,比如:
[PcdsFixedAtBuild]
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f

此设置过程不是必须的,如果没有设置,则使用DEC文件中的默认值。

INF文件中声明
在模块的INF文件中,需要声明PCD变量,才可以在源码中使用。比如:
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes

只需要列出PCD变量名就可以了,其他信息不用列出。

完成上述工作后,就可以在源代码中,使用PCD库函数访问PCD变量了。示例如下:(摘自MdeModulePkg\\Application\\HelloWorld\\HelloWorld.c)

if (FeaturePcdGet (PcdHelloWorldPrintEnable))
for (Index = 0; Index < PcdGet32 (PcdHelloWorldPrintTimes); Index ++)
//
// Use UefiLib Print API to print string to UEFI console
//
Print ((CHAR16*)PcdGetPtr (PcdHelloWorldPrintString));



以上是关于UEFI开发探索101 – PCD探究(helloworld中的使用)的主要内容,如果未能解决你的问题,请参考以下文章

UEFI--- 探究BIOS NvRam空间的位置以及大小

iOS开发底层之类的底层探究-05

Java原理探索带你探究String类不可变的特性 | Java开发实战

iOS开发底层之RuntimeObjc_msgSend探究下 - 09

iOS开发底层之RuntimeObjc_msgSend探究下 - 09

iOS开发底层之类的底层Cache_t 探究 - 07