BIOS知识枝桠——PCD

PCD Overview

PCD的主要目的就是把代码里面的可配置选项抽取出来,抽取出来的好处是倘若平台真的需要一些配置的时候,不需要修改源码,通过修改dsc把这些东西影响到,是最好的。这个PCD不止是要在编译过程中可以配置,还可以在运行时配置。

配置PCD有几种方式,目的是让platform时候更为容易进行定制化,减少effect
1:在build time时候,通过编译选项或者dsc的值进行设置从而影响源码;
2:在Boot过程中,通过某个Driver生成某种状态更改PCD的某些值;
3:作为BIOS,release出来的binary image也要提供可配置性。

PCD数据库保存所有动态类型的PCD信息。 PEI PCD数据库的结构是由构建工具根据指定平台的动态PCD使用情况生成的。 动态PCD,主要用作boot过程中相互进行交互沟通的一种方式,初始值肯定也是在build时候就设置好了。动态类型PCD用于动态确定值的配置/设置。 相反,静态类型PCD (FeatureFlag, FixedPcd, PatchablePcd)的值在构建时固定在最终生成的FD映像中。

PCD TYPES

FixedAtBuild PCD:值是在build time 时候就定好了的,在binary阶段是不可以改的,整个boot level也是不可以改的,可以认为就是一个宏,const 全局变量。这个PCD有一个好处,是一个module level的,非系统级别的,即是说不同模块可以配置不同PCD的值,典型的例子就是DEBUG Message 是否要输出Message的问题,这是由一个PCD来control的,由于是模块级别的,所以可以控制一个模块输出一个模块不输出。

FeatureFlag(control feature Boolean类型) 和FixAtBuild 是一类,可以认为是BOOLEAN类型的FixedAtBuild,只是支持静态build time的设置,而且是module level的。

PatchableInModule:module level,它可以patch(binary level 的patch),在boot time 也可以修改,但是能影响的也只是一个模块,一个Driver,在这个模块的修改不会影响到其他模块,相当于一个inf文件的source范围,但是和FixAtBuild不同的是,这只是一个全局变量,并不是const类型的,binary level可以修改的。

Dynamic/DynamicEx:动态的PCD,在整个boot过程中,有人set有人read,是可以一直修改的,作用域是system,system level,意思就是在整个BIOS,所有的模块访问Dynamic的PCD,都是共享的同一个值,某模块的修改会导致其他模块获取到的值也发生变化。Dynamic 又有三个子类:DynamicHII、DynamicVpd、DynamicEx

Dynamic与DynamicEx的区别:如果只是做source 的build就是说platform是从源码build出来的,没有binary在里面的时候,PCD用的都是Dynamic这种类型,如果在BIOS里面有一些模块是binary方式集成进来的而这些binary又需要用到PCD,那么这些Binary集成的要用到的PCD就必须要设置为Dynamic类型,这就是Dynamic与DynamicEx之间的区别。

Dynamic:PCD的值可以认为存在于hob或者memory中,会导致在下次启动时丢失上一次的值,获取到的是新define的值。

DynamicHII的关于PCD的值存在于EFI Variable中,可能对应的是一个NV的,non-volatile 的,即在某次PCD的值发生set之后,下次启动仍然是本次set的值。

DynamicVpd是属于另一种,ReadOnly,这个PCD的值存在VPD空间的,VPD是放在FLASH上的只读的,通常来说是一些系统的Default Section,工厂出厂的一些配置存放在这里,属于必不会被修改的。

PCD LIBRARY

为了方便code的编写,对PCD的使用引入PCDlib,这里面包含了常用的PCD接口,故而不用去可以学习内部实现是调用PPI 、Protocol或是直接映射,这些都被LIb隐藏了,所以在使用过程中,只需要关注PCD Protocol 和PCD PPI FUNCTION:PcdGetXX()、PcdSetXX()、 PcdGetExXX()、 PcdSetEx()、 PcdToken()、 PcdSetSku()、 PcdGetNextToken() 、PcdGetNextTokenSpace()、 CallBackOnSet() 、CancelCallBack() 。【“XX" = 8 16 32 Size Ptr Boolean】

PCDgetXX()和PCDSetXX()是用得最多的,属于统一化的API接口,无论哪一种Type都可以使用这两个,使用时会根据你具体Type类型,把这个Function map in到具体的PCDType所对应的值的上面。

PCD instrument

FixAtBuild PCD SYNTAX

Define : PCD 在.DEC文件中进行声明,就涉及到了Package,所以说PCD是一个Package的interface,就是说PCD是Package对外提供的接口之一。在定义过程中有两个需要注意的information,TokenSpaceGuid(PCD GUID说明到底在哪个Space 空间里)和TokenName(PCD 名字),这两个决定了PCD的唯一性,不可以重复,也不可以轻易改变。

Value为Default Value,Datum Type描述的是数据类型 UINT 8 16 等,倘若是VOID * 还得在[MaxSize]中填入这块Buffer的最大值128 256等,最后一个为Token number UINT32的。

[Guids.common]
PcdTokenSpaceGuidName = { 0xXXXXXXXX, 0xXXXX, 0xXXXX, { 0xXX, . . .}}
. . .
[Pcds...]
PcdTokenSpaceGuidName.PcdTokenName|Value[|DatumType[|MaxSize]]|Token

Reference:PCD在.inf文件中进行使用。在inf里一般来说有个Pcd Section,只要把这个PCD列上去就行了,通常也不会写值

[…Pcd…] 
PcdTokenSpaceGuidName.PcdTokenName|[Value]

Modify:PCD在.DSC文件中进行配置,在这里会决定PCD的值和类型,若PCD在.DEC文件中进行了定义,在inf文件中使用,但在DSC中并没有重新set,这时候PCD就会使用默认值(.DEC的Value),类型则是支持的最初的类型,类型也是有一个优先级,优先考虑FixAtBuild,其次PatchInModule,然后Dynamic,DynamicEx。

[Pcds...]
PcdTokenSpaceGuidName.PcdTokenName|Value[|DatumType[|MaximumDatumSize]]

For Example:

Defined:(.dec)
[PcdsFixedAtBuild, PcdsPatchableInModule]->支持的两种类型
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x400|UINT32|0x30000003

Referenced:(.inf)
MdeModulePkg\Universal\Variable\RuntimeDxe\VariableRuntimeDxe.inf
[Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize  ## CONSUMES

Modified:(.dsc)
[PcdsFixedAtBuild]
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x00840 ->0x400改为0x8400

Use:(.c)
MdeModulePkg\Universal\Variable\RuntimeDxe\VariableNonVolatile.c // max NV variable size 
mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize)->UINT32 使用PcdGet32()

PCD SOFTWARE

PCD起作用并不是简简单单通过上述步骤就可以实现的, 在文件中描述完毕后通过Parsing Tool(实际就是Build Tool)进行parse,生成对应的AutoGen code,在code里面可以以PCD类型生成不同的PCD原型,然后被PCD Lib里的PCDGet32()、PCDGet16()等不同的function进行引用,而Driver Source Code里面,调用函数所用到的就是AutoGen中通过Build Tool生成的值,或是访问的方法。
Source Code如何使用PCD的值

关于动态的PCD,通过 build后parse,拿到所有的动态PCD,然后生成到Database里面,Compiler到一起,最后生成Driver Binary。存储在PE32 space,通过隔离Database,使得PCD的值可以进行修改替换,达到动态目的。

在这里插入图片描述

Fixed PCD AutoGen Code

For Example:
Example : MdeModulePkg\Universal\Variable\RuntimeDxe\VariableRuntimeDxe
Autogen.h

#define _PCD_TOKEN_PcdMaxVariableSize 250U
#define _PCD_SIZE_PcdMaxVariableSize 4
#define _PCD_GET_MODE_SIZE_PcdMaxVariableSize _PCD_SIZE_PcdMaxVariableSize 
#define _PCD_VALUE_PcdMaxVariableSize 0x8400U --->在PCD SYNTAX举的例子,通过build生成的宏
extern const UINT32 _gPcd_FixedAtBuild_PcdMaxVariableSize;
#define _PCD_GET_MODE_32_PcdMaxVariableSize _gPcd_FixedAtBuild_PcdMaxVariableSize

Autogen.c

// Definition of PCDs used in this module
• • • 
GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPcd_FixedAtBuild_PcdMaxVariableSize = 
_PCD_VALUE_PcdMaxVariableSize;--->生成的GLobal Variable呼应.h中的宏

DYNAMIC PCD

For Example:

Defined:(.dec)
[PcdsDynamic]->支持类型
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x30000001

Modified:(.dsc)
[PcdsDynamicDefault]->在Dynamic Default这种Section下
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|03

Setting:(.c)
OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
PcdStatus = PcdSet16S (PcdPlatformBootTimeOut,GetFrontPageTimeoutFromQemu ());

Use:(.c)
OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
Timeout = PcdGet16 (PcdPlatformBootTimeOut);

Example Module: (OvmfPkg\Library\PlatformBootManagerLib)

Autogen.h
• • • 
#define _PCD_SET_MODE_16_PcdPlatformBootTimeOut(Value)  LibPcdSet16(_PCD_TOKEN_PcdPlatformBootTimeOut, ( Value ))
#define _PCD_SET_MODE_16_S_PcdPlatformBootTimeOut(Value)  LibPcdSet16S(_PCD_TOKEN_PcdPlatformBootTimeOut, ( Value ))
DYNAMIC PCD AUTOGEN FILES

Autogen.c:Example Module: (MdeModulePkg/Universal/PCD/Dxe/Pcd)

DXE_PCD_DATABASE_INIT gDXEPcdDbInit = { 
• • • 
/* LocalTokenNumberTable */
• • • 
offsetof(DXE_PCD_DATABASE, Init.PcdPlatformBootTimeOut_*1) | PCD_TYPE_DATA | PCD_DATUM_TYPE_UINT16,
• • • 
{ 0x3U } /* PcdPlatformBootTimeOut_*1 { 0x3U } [1] */
                                                *1 GUID of PCD Variable PcdPlatformBootTimeOut

Special PCD

PCD的高级用法,确实能解决platform porting1过程中的一些问题,但相对来说比较复杂,所以并没有大范围推广。

Multi-Structure PCD:C data structure and assign the value to each sub-field directly

这个PCD解决的问题是当一个PCD和一个EFI Variable进行关联的时候,通常一个EFI Variable里面是一个C的Structure,就有可能关联到这个C Structure的某一个field,这时候就需要知道这个Struct的offset在哪里,这个对于维护和开发会带来难度,由于并不知道Struct的offset是多少,且当Struct改动之后关于PCD 的dsc也要进行修改,倘若有很多field需要使用,则需要定义更多的PCD,加大code的复杂度,故而引入MUlti—Structure PCD。本身而言,只是一个VOID * 的PCD,这个PCD mapping 到一个Structure,以后访问该PCD就相当于访问Structure,访问Structure中的每个field就相当于访问PCD然后通过PCD引用相应的field。

为了更容易使用Structure PCD,需要DSC能够支持对每个field的赋值,在C code能直接引用PCD,然后再把PCD mapping成一个structure,按照structure layout去访问每个field,总的来说,为了使单个域在dsc里面能够赋值,而且整个PCD在DSC里面也能赋值,这样就把所有的Structure赋值挪到DSC里面,就不需要在C source里面做。同时即便Structure修改了 DSC也不需要做任何改动,

Multi-Sku PCD:Multiple configurations generated at build time & set @ run time, (PI Spec Vol 3 chap. 8)

倘若有一个很大的Structure,如Platform 的setup的structure,这个Structure可能在一个平台有不同版本的board,每个board里面可能有一些细微的差别,可能会导致这个Setup的structure可能有些不同,这种情况下按照原来的配置方法可能要创建好几个DSC,每个DSC里面对PCD设置不同的值,相对来说比较复杂。那么这个PCD相当于有一个base,根据board的差异继承base数据然后只改差异的地方,支撑整个Structure。

DefaultStoresPCD:Support the default stores concept in UEFI specification, (UEFI, HII Chap. 32)

HII在启动起来之后有Reset to default等选项,用户可能在对setup选项进行修改之后,发现系统出现了各种各样的问题,这时候可能需要恢复到初始状态,选择reset to default标准的,相当于重置设置,另外一种manufaction default,相当于恢复出厂设置,那么这个值用StructPCD描述出来,根据对象为标准default还是manu default写入DSC里面,倘若需要使用,则进行配置使用即可。

For Example:声明一个structurePCD然后对每个Field进行赋值,Structure为:SMBIOS_TABLE_TYPE0。

gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation| \
    {0x0}|SMBIOS_TABLE_TYPE0|0x80010000 {
<HeaderFiles>
    IndustryStandard/SmBios.h
<Packages>
    MdePkg/MdePkg.dec
    AdvancedFeaturePkg/AdvancedFeaturePkg.dec
}

gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.Vendor|0x1
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosVersion|0x2
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosSegment|0xF000
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosReleaseDate|0x3
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosSize|0xFF
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosCharacteristics.\
PciIsSupported|1
gAdvancedFeaturePkgTokenSpaceGuid.PcdSmbiosType0BiosInformation.BiosCharacteristics.\
PlugAndPlayIsSupported|1
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MathWorks PCD指的是MathWorks的产品分类之一,也称为基于云的异构分布式计算平台(Parallel Computing Toolbox Cloud Provider)。 MathWorks是一家全球领先的科学和工程计算软件公司,其产品和解决方案被广泛应用于学术研究、工业设计和开发等领域。MathWorks PCD是MathWorks提供的用于并行计算的工具箱,可以帮助用户在云环境下进行高性能计算任务。 MathWorks PCD最主要的特点是为用户提供了一种灵活且高效的云计算环境,可以轻松地进行跨平台和分布式计算。用户可以将计算任务分批发送到云端进行处理,通过并行计算大幅缩短任务完成的时间。同时,MathWorks PCD还支持将不同类型的计算资源进行整合,包括本地计算机、云服务器和集群系统等,最大限度地发挥计算资源的效能。 通过使用MathWorks PCD,用户能够极大地提高计算任务的效率和性能。无论是进行大规模的数据处理、高精度的数值计算、复杂的模拟与建模还是机器学习算法的训练,MathWorks PCD都能提供相应的并行计算技术和工具。用户只需通过简单的几步操作,便可以将计算任务快速部署到云端,并且随时实时监控任务的执行情况。 总而言之,MathWorks PCD是MathWorks提供的一款强大的云计算工具箱,通过其提供的并行计算能力,可以帮助用户更高效地完成各种复杂的计算任务,提升工作效率和准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值