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