UEFI——PCD研究
??今天看UiAPP下的入口函數(shù)InitializeUserInterface()時(shí)看見一個(gè)PcdGet32,不明白是干什么的,VSCode上顯示的是本函數(shù)相關(guān)的信息(顯然不對(duì) ),后面搜索不到相關(guān)的源碼。之后就去補(bǔ)充了相關(guān)的知識(shí),記錄一下,算是一個(gè)比較簡(jiǎn)單淺顯的版本。
UEFI——PCD研究
- 1 PCD OVERVIEW
- 2 PCD USAGE
- 2.1 PCD TYPES
- FixedAtBuild
- FeatureFlag
- PatchableInModule
- Dynamic/DynamicEx
- DynamicHII/DynamicVpd
- 2.2 EXAMPLE
- 3 AutoGen
- 4 PCD LIBRARY
1 PCD OVERVIEW
PCD(Platform Configuration Database),是一個(gè)UEFI下可訪問的數(shù)據(jù)庫(kù),EDK2用來進(jìn)行全局配置,對(duì)代碼復(fù)用,模塊化開發(fā)有巨大的幫助。
??具體來說就是,代碼中進(jìn)行平臺(tái)配置相關(guān)的東西,platform需要改的時(shí)候不用去修改代碼了。在編譯的時(shí)候,運(yùn)行的時(shí)候,甚至是生成了二進(jìn)制的時(shí)候都可以配置、修改。更容易有針對(duì)性的設(shè)計(jì),對(duì)代碼的維護(hù)也會(huì)方便很多。(有點(diǎn)類似于.uni和.Vfr的機(jī)制)
??雖然在EDK2源碼中他涉及到的宏很多,但是這種方式確實(shí)是有別于C/C++的宏,并不是簡(jiǎn)單的公用代碼的提取,或者說完全不是一個(gè)東西。
PCD變量格式
其中TokenSpaceGuidCName是一個(gè)GUID,而PcdCName是這個(gè)PCD變量的名字,這兩個(gè)加在一起構(gòu)成了一個(gè)PCD變量。
2 PCD USAGE
2.1 PCD TYPES
PCD可以分為兩類:
1)有三個(gè)分別是:FixedAtBuild PCD , FeatureFlag PCD,PatchableInModule PCD , 其中 FixedAtBuild PCD 和 FeatureFlag PCD 在編譯的時(shí)候起作用的,靜態(tài)的。類似于C中的靜態(tài)全局變量,但是后面不能修改。在定義的時(shí)候就賦值了,之后是不能用代碼修改的,只能是在.dec/.dsc中修改。
PatchableInModule PCD在編譯完成后的二進(jìn)制文件上是可以用特殊的辦法更改的。后面詳細(xì)介紹。
2)Dynamic/DynamicEx PCD 等其它的 可以稱為動(dòng)態(tài)的,在UEFI運(yùn)行的時(shí)候可以get,還可以用set宏修改,作用域是system級(jí),在代碼中傳遞和使用。(比前面的復(fù)雜一些)
FixedAtBuild
編譯階段確定的值,整個(gè)UEFI運(yùn)行階段不可改的靜態(tài)值,二進(jìn)制下也不可以改,可以認(rèn)為是一個(gè)宏,const全局變量。是一個(gè)module level,并非系統(tǒng)級(jí)別的。即是說不同模塊可以配置不同PCD的值。
FeatureFlag
也是編譯時(shí)確定的靜態(tài)設(shè)置,看名字中有個(gè)Flag也能猜出來這是個(gè)Boolean類型的,他和FixedAtBuild最大的區(qū)別就是他返回值就是一個(gè)TURE或者FALSE。用于判斷條件中,也是一個(gè)module level的。
PatchableInModule
在編譯時(shí)確定值,和FixedAtBuild一樣也是module level,只能影響一個(gè)模塊,不會(huì)影響其他的模塊,相當(dāng)于一個(gè)inf 的 source范圍。不同是他在編譯后的二進(jìn)制文件中可以用工具修改,并且他不是const 的全局變量。
Dynamic/DynamicEx
動(dòng)態(tài)值,在整個(gè)UEFI運(yùn)行的過程中,有人會(huì)get,有人會(huì)set,是一直可以改變的值,system level,作用域是整個(gè)system。整個(gè)BIOS代碼每個(gè)模塊訪問這個(gè)Dynamic PCD 都是共享同一個(gè)值,如果某個(gè)模塊修改了他的值,那么其他模塊訪問的就是修改以后的值了。通過set宏來改變。Dynamic 有三個(gè)子類DynamicHII、DynamicVpd、DynamicEx。區(qū)別目前還不是特別理解,只知道DynamicEx是Dynamic的加強(qiáng)版,如果在代碼中沒有二進(jìn)制形式,或者二進(jìn)制文件沒有用到PCD,那么這里使用的PCD 類型就是Dynamic的,但是如果是用binary方式集成進(jìn)來了,要使用二進(jìn)制中的PCD就必須要用DynamicEx類型的PCD。
DynamicHII/DynamicVpd
DynamicHII與Dynamic不同,后者是放在memory中的,也就是說修改了再加載的話會(huì)丟失上一次的值,獲取到最新define的值。而DynamicHII是放在EFI variable(NVRAM中)的,修改是非易失性的,就是set了以后下次加載還是這次set的值。
DynamicVpd ReadOnly,不可寫。存放系統(tǒng)的default section,廠商的出廠設(shè)置就放在這里,是必不會(huì)也不可被修改的。
2.2 EXAMPLE
原本計(jì)劃介紹 FixedAtBuild 類型的,但是我看到的代碼中的PcdSetupVideoHorizontalResolution是PatchableInModule類型的,這兩個(gè)類型的訪問方式?jīng)]什么不同,后者只是可以在二進(jìn)制文件生成之后修改,而前者不可以。
PcdSetupVideoHorizontalResolution在源碼中的位置:
可以看到也是有這個(gè)PcdGet32宏,我也是因?yàn)闆]找到這個(gè)的定義才進(jìn)行相關(guān)知識(shí)的學(xué)習(xí)。
源碼:
介紹一下聲明的格式:
??他這里有兩句,第一句[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx],聲明了這個(gè)PCD的類型,就前面介紹的PCD類型。
??第二句的規(guī)則是這樣的:
PcdTokenSpaceGuidName.PcdTokenName前面已經(jīng)介紹過了,不可以重復(fù),也不可以輕易改變,這兩個(gè)共同構(gòu)成一個(gè)PCD變量。Value也叫做DefaultValue 就是這個(gè)PCD變量的默認(rèn)值,如果你在后面的.dsc文件中沒有修改他的值,他就是用這個(gè)默認(rèn)值。DatumType是這個(gè)PCD變量的數(shù)據(jù)類型有UINT 8 16 32 等等,如果是VOID * 的話還要在MaxSize部分寫上這個(gè)Buffer的最大值,比如128、256等等。Token是UINT 32類型的,每個(gè).dec文件中的PCD都有獨(dú)一無二的Token。
他是符合BNF的,#后面的是注釋,[ ]內(nèi)的是可選項(xiàng),沒有應(yīng)該也可以。
修改的規(guī)則:
這些字段的值和前面的一樣,[ ]內(nèi)的也是可選的,不是必須包括的。一般的寫法就是PcdTokenSpaceGuidName.PcdTokenName|Value,像圖片里面的那樣。
將原本的800改成了640,當(dāng)然這還不是同一個(gè)文件下的dsc文件,從側(cè)面也證實(shí)了這確實(shí)是一個(gè)全局變量。
PCD可以在.dsc文件中進(jìn)行修改,包括PCD的值和類型,假如PCD在.dec文件中進(jìn)行了定義,在inf文件中使用,但在.dsc中并沒有重新set,這時(shí)候PCD就會(huì)使用默認(rèn)值(.dec中的Value),類型則是支持的最初的類型,類型也是有一個(gè)優(yōu)先級(jí),優(yōu)先考慮FixAtBuild,其次PatchInModule,然后Dynamic,DynamicEx。(這部分不確定)
3.在.inf文件中引用
一般的寫法就是列出這個(gè)變量的名字,值是不管的。
3 AutoGen
AutoGen.h
這里可以看見 在AutoGen.h 中 將 _PCD_PATCHABLE_VALUE_PcdSetupVideoHorizontalResolution 設(shè)置成了800u
AutoGen.c
然后最精彩的操作在于,他通過一些的#define 將_PCD_PATCHABLE_VALUE_PcdSetupVideoHorizontalResolution這個(gè)變量改成PcdSetupVideoHorizontalResolution 加上前綴_PCD_GET_MODE_32_,而后面的PcdGet32()中直接用##拼接這個(gè)變量名就可以直接得到他的值,所以也算知道了PcdGet32()這個(gè)函數(shù)的來龍去脈了。
4 PCD LIBRARY
為了方便代碼的編寫。引入了PCDLib,這里面有常用的接口可以使用,我之前看到的PcdGet32()就在其中。
這里面有許多好用的函數(shù),比如
PcdGetXX()PcdSetXX() PcdGetExXX()PcdSetEx()PcdToken() PcdSetSku()PcdGetNextToken() PcdGetNextTokenSpace()CallBackOnSet() CancelCallBack()其中“XX" = 8 16 32 Size Ptr Boolean
而我們最常使用的就是PcdGetXX() 和 PcdSetXX()
最后:動(dòng)態(tài)的PCD機(jī)制還不太了解,而修改二進(jìn)制文件中的PCD還需要去實(shí)踐。
參考博客:
- https://blog.csdn.net/luobing4365/article/details/120835863
- https://blog.csdn.net/jiangwei0512/article/details/80288001
- https://blog.csdn.net/weixin_45279063/article/details/117704225
- https://blog.csdn.net/szhb5251/article/details/105961860
總結(jié)
以上是生活随笔為你收集整理的UEFI——PCD研究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python绘图设置新罗马字体_更改ma
- 下一篇: 大学综评自招面试 计算机专业,自主招生中