【UEFI】--- 關於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的定義,使用,傳遞,以后看代碼的時候需多加注意。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM