【三支火把】--- 关于UEFI&PCD的总结介绍
1个人理解
个人理解PCD基本等同于Token,应当算是一种描述性语言,按照规定书写好PCD的配置档,在编译的过程中,会根据你的配置生成同等含义的C文档,而在C文档中对应会出现相应的define或者变量声明定义。下面通过具体的例子来说明PCD档的基本含义和使用方式以及注意事项:首先需要准备EDK的环境,具体到某个案子的代码也可以,因为UEFI的架构下,基本上都是使用EDK编译的。
2 实例介绍
先用一个实际的例子,让大家对于PCD有个直观的感受(以EDKII/MdeModulePkg/Application/HelloWorld为例)
2.1 MdeModulePkg/Application/HelloWorld.c的代码如下所示:
2.2 PCD在MdeModulePkg/MdeModulePkg.dec中的定义如下图所示:
/* PCD的TOKEN值*/
在上图的PCD的定义中,最后都有一些0x0001200a这样的值,这些都是TOKEN的值,它的主要作用是用来区分每个Token,给每个Token一个独立的编号,必须赋值,否则会编译失败。用户在DEC中定义PCD时会指定每个PCD的TOKEN值,编译器编译之后,在 AutoGen.h文件中可以发现TOKEN的值会被宏定义成下列的值,与用户指定的不太一样,这是因为编译器会自动为每一个PCD再次生成一个TOKEN值,以免由于用户方面操作不当,而导致TOKEN的值重复。
2.3 MdeModulePkg/Application/HelloWorld.inf配置档如下图所示:
一般看到的PCD定义如2.2中所示,PCD的定义一般是在*.dec的文件里进行第一次默认声明,比如:MdeModulePkg/Application/HelloWorld.c文档中所用到的这三个PCD就是在MdeMoulePkg/MdeMoulePkg.dec中进行声明。在PCD的定义中,一般需要关注的就是变量名,默认值,变量类型。
*.inf文档配置后可以在*.c文档中使用,之所以能使用,是因为在编译过程中,编译器会帮助生成宏定义或者变量声明的东西。在EDK的环境下直接编译HelloWorld例子,在build/MdeModulePkg/Application/HelloWorld/DEBUG文件夹下有AutoGen.h和AutoGen.c这两个文件,这两个文件中括了PCD的声明和定义,个人理解是编译器解析DEC和INF档中有关PCD的说明,接着首先生成中间文件AutoGen.h和AutoGen.c,接着HelloWorld.c负责去调用这两个文件中的内容。从而达到使用PCD的目的(个人理解,仅供参考)。
我将AutoGen.h和AutoGen.c文件中的内容做了一些截取,筛选出来了一些重要部分show给大家看。根据PCD最开始的描述,在相应的C文档中,都有其对应的宏定义和说明,我们的HelloWorld.c中最终所使用的PCD应该是也是来源于这两个中间文件,从这两个文件怎么与HelloWorld.c联系在一起,如果实现调用生成.efi目标程序,还需要再研究一下(未完待续)
3 PCD基本类型介绍总结
基本可以将PCD当作一个描述性语言,编译工具(例如AutoGen工具)在编译过程中会根据相应DEC文件或这DSC文件中的描述,进行编译然后在生成的AutoGen.h和AutoGen.c或者其他的.h与.C文件中,对每个PCD所表述的变量进行定义或者宏定义。
3.1 PCD涉及的基本文件类型
*.inf是编译某个模块的指导文件。
*.dsc是编译一个Package的指导文件。
*.dec中定义了公开的数据和接口,供其他Package中的某个Moudle使用。
3.2 PCD类别
EDK II中PCD根据其作用的时间,分为两大类:
3.1.1 在编译过程中起作用,
这类PCD等同C语言中的全局静态变量,包含FeatureFlag PCD, FixedAtBuild PCD以及 PatchableInModule PCD三种:
1)PcdsFeatureFlag:
表示一个Feature是On还是Off,Value一般是TRUE或者FALSE,该类型的PCD在编译时会赋予Const类型,定义在AutoGen.h文件中,多用来描述一些BOOL型的变量值。
如1.2实例所示:
在HelloWorld.inf文档中定义了如下的PCD
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable
在最终生成的AutoGen.c和AutoGen.h中可以看到PcdHelloWorldPrintEnable的宏定义以及最终的赋值是赋了一个BOOL型的真值1,如下:
#define _PCD_VALUE_PcdHelloWorldPrintEnable ((BOOLEAN)1U)
2)FixedAtBuild:
与PcdsFeatureFlag类似,最大的不同在于它可以宣告多种不同的变量类型,不仅限于Bool型。可以是UINT32型的变量等.例如,我在MdeModulePkg/MdeModulePkg.dec中增添如下定义:
在其HelloWorld.inf中增添如下声明:
build过之后可以看到在AutoGen.c和AutoGen.h中有如下定义和声明:
3)PatchableInModule:
该种变量与上述最大的不同是在Runtime时可以去变动它的数值,除此之外,它将被宣告成一个Global变量,被宣告成该种变量同一时刻,仅有同一个Module可以存取,不能透过它与各Module相互传递数值。
3.1.2 在平台初始化过程中起作用
包含: DynamicDefaultPCD, DynamicHIIPCD, 和DynamicVpdPCD等几种:
1)DynamicDefault:
DynamicDefault形态的PCD的最大又是在于,各个Module之间可以借由这个PCD来互相传递数值。典型的例子:比如预先把某个不会变动的值从HW中读出来,并且存储到一个DynamicDefault类型的PCD中,这样其他的Module就可以不用再经过繁杂的动作去存取HW上的值,而是可以直接透过PCD读取就好。
PcdsDynamicExDefault:
多了Ex的PCD与上述DynamicDefault很相似,但如果一个Module不是同时间与整个Platform一起Build的,而是一个外部的Binary,Platform与Binary又需要互相存取某个PCD的数值的话,这时候一开始就应该把该PCD宣告成PcdsDynamicExDefault的形态,但是外部的Binary在使用该PCD的时候,必须先知道该PCD的TOKEN值才可通过LibPcdGetExXX或者LibPcdSetExXX来进行存取。
2)DynamicHIIPCD:
HII型態的PCD在DSC需定好它所對應的Variable Name、GUID、Offset(位於Variable Data的哪個Offset)還有Default Value。如果系統中不存在著該Variable,那麼就會從PCD取得DSC所定好的預設值,否則就會回傳該Variable的Data加上Offset。
DynamicExHIIPCD:
多了Ex的DynamicExHii則意思跟DynamicEx很相似。
3)PcdsDynamicVpd and PcdsDynamicExVpd:
VPD (Vital Product Data),在NVS會有一塊區域被用來儲存VPD的資料,與其它Dynamic PCD不同,VPD只能唯讀,無法在執行期間去修改它的數值。關於VPD的部分,目前我還沒有機會用到,故不多说
4 关于PCD默认值和重新赋值
PCD最开始声明定义的地方在*.dec文件中,如果直接使用的该PCD的话,那么编译器从*.dec取出该值作为默认值供使用,多数情况下,用户可能会不使用*.dec中所提供的默认值,那么就需要对默认值进行修改。如何修改呢?仍旧以HelloWorld为例进行说明。
如上图是在MdeModule.dec文件中对HelloWorld所用的PCD的默认定义,在进行编译之后,在AutoGen.h中生成的字符串数组如下如所示:假如你仍旧想使用这个PCD但是不想使用这个UEFI HELLO……的字符串,该如何做呢?
一般是在MdeModule.dsc文件中做如下修改,然后编译:
编译出来的Autogen.c文件中,可以看到原来的PCD所定义的字符串已经改为了你想要的,如下图:
以上是关于PCD的一些基本了解,以上内容为本人自己学习总结,仅供参考如有错误,请及时指出,谢谢!
目前还需要深入了解的是关于Dynamic类型PCD的定义,使用,传递,以后看代码的时候需多加注意。
【三支火把】--- 关于UEFI&PCD的总结介绍的更多相关文章
- 【三支火把】--- 关于BIOS&UEFI查阅资料网站总结
UEFI和BIOS的水太深,网上能找到的资料是那么的少,各个组织之间互有交叉,难弄的很,总结了下常用的BIOS资料网站,仅供参考,如果遗漏之处,请指出,博主将继续完善补充……
- 【三支火把】---CDS5516舵机调试以及自己的感想!
我依然坚持,任何一次自己的心有感触都要及时的记录下来,这样你的努力才是真正的努力. 这两天一直在用STM32调试CDS5516舵机,其实很简单,但是却花了将近两天的时间,过程之曲折我就不说了,先总结一 ...
- 【三支火把】---队列和栈的C程序实现
这几天总结了C语言的队列,栈的实现方法,在此总结一下:一.栈 首先从栈开始,诚然,相信学习过数据结构的你,肯定应该知道栈是什么东西了,如果不知道也没事每一句话我就可以帮你总结--数据只在栈顶进行插入和 ...
- 【三支火把】---C文件学习
---恢复内容开始--- 又看了一遍文件的知识点了,断断续续已经看了2-3遍,也就这次花了点时间做了一下总结,以后我想都不会再去翻书了,哈哈. 1. 基于缓冲区的文件操作2. 打开关闭文件3. 单个字 ...
- 【三支火把】---C指针总结
好久没写博客了,重新学习C语言了的基础课程,发现很多东西都忘记的差不多了,闲来无事,总结一下关于指针的知识,希望能帮到像我一样的菜鸟们: 指针,众所周知是C语言的精华所在,不懂指针的话,你就不要说你学 ...
- 【三支火把】---C语言面试问题总结
看了一份关于HR在面试一名C程序员可能提问的问题手册,学到了很多,很多都是一些琐碎的知识点,总是你写过很多大型的C程序,但是我敢说,里面也有你没掌握的东西. 1.全局变量和局部变量有何区别? 答:全局 ...
- 【三支火把】---C语言const用法总结
C语言关键字const相信对于不少C语言新手是既陌生又熟悉的,好像经常见,但是却不知道为何用,怎么用?学习至此,总结一下const的用法,使用程序来帮助你理解该关键字,希望能帮到像我一样的新手. 我看 ...
- 【三支火把】---常用C语言控制台函数总结(持续更新)
写了这么久的C程序,每次看到输出的结果都是从上往下排列的黑白框,有没有感觉很无聊啊?今天再次总结一个常用的控制台函数,能够帮助你做好一个好看的界面. 1.设置光标位置代码如下: int main(vo ...
- 【三支火把】---一份程序看懂C程序printf()的几种常用用法
闲来继续巩固我的学习之路,今天略微整理了一下,C程序中Printf()的一些常用用法,虽然自己以前好像会,但是不够系统,今天大致整理了一些,先贴上来看看,以后在看到其他,继续补充,希望能帮到一些像我一 ...
随机推荐
- SpringMVC 之URL请求到Action的映射(1)
URL路径映射 1.1.对一个action配置多个URL映射: @RequestMapping(value={"/index", "/hello"}, meth ...
- VisualGDB系列10:快速调试Linux应用程序
根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 本文介绍如何快速调试GCC构建的Linu ...
- Python类(七)-类的特殊成员方法
__doc__ 用来表示类的描述信息 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" class Person(object) ...
- Socket编程, 在server端read()函数调用后显示错误:Transport endpoint is not connected (犯了低级错误)
for(;;){ socklen_t len = sizeof(client_address); connfd = accept(listenfd, (struct sockaddr *)&c ...
- java selenium webdriver第三讲 helloWord
第一步:建立Maven项目 Selenium 支持 maven 工程,这会让你的工作更加简便. 用 Eclipse 建个 Maven 的工程,建成后,修改 pom.xml <dependenci ...
- 数据库连接池在Tomcat中的几种配置方法
数据库连接是一种关键的有限的昂贵的资源,这在多用户网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标,数据库连接池正是针对这个问题提出的. ...
- 关于struts2.3的action
struts2.3中支持实时配置,也就是说不用在struts.xml中进行配置.但是所有的action文件应该放在有路径名含action的包中,否则程序无法发现你的action. 这个问题,难为了我好 ...
- springmvc+spring3+hibernate4框架简单整合,简单实现增删改查功能
转自:https://blog.csdn.net/thinkingcao/article/details/52472252 C 所用到的jar包 数据库表 数据库表就不用教大家了,一张表,很简 ...
- 部署和调优 2.2 squid反向代理
配置反向代理 打开配置文件 vim /etc/squid/squid.conf 修改 http_port 改为 http_port 80 accel vhost vport 在它下面添加一段 cach ...
- Android开发 开启闪光灯 关键代码
在AndroidManifest中注册响应的权限: <uses-permission android:name="android.permission.FLASHLIGHT" ...