---恢復內容開始---
BIOS發展至今傳統的匯編實現早已被拋棄,UEFI作為目前一套主流的標准定義接口,被廣泛使用。之前被一些有關GUID和一些Lib函數的使用以及跨Pkg調用給折騰的不行,每次改代碼都要build好多次,才能build過。趁着這次的一個Bug,針對GUID和Lib的跨Pkg使用做下小結。
/*GUID*/
顧名思義--globally unique identifier,全局唯一標識符。GUID是一個由128bit=16Byte的二進制數據組成,此數據的生成一般由專門的GUID生成器(千萬別自己亂寫哦),而且每次生成的GUID基本是不能重復的。BIOS中使用GUID的地方很多,大部分的全局變量以及Protocol等都需要通過GUID來locate或install。今天通過之前解的問題來介紹GUID的1. 格式 2. 用法。 (問題背景: InsydeMoudlePkg中的Moudle1中的某個程序要設置Variable1,Moudle2中的某個程序要去讀取Variable1)
(看之前,請先對UEFI的Pkg Moudle等概念以及dec/inf/dsc文檔由個基本的掌握)
1. 格式--同樣我們從最終的需求處入手,一步步來。
最終需求:在Password.c中需要將一個功能,將變量EncryptedHashData保存並掛載到gInspurUserPassWordFlagGuid的下面(如下圖左一)。
- Step1: 查看Password.c在哪個Pkg中如下圖右一,
- Step2: 確定在InsydeMoudlPkg后,找到該Pkg的Dec文檔,並把gInspurUserPassWordFlagGuid的定義添加進去即可(添加至dec的目的是為了能在其他Pkg中直接調用該GUID,為了不給未來自己挖坑,此步驟建議一定要做。因為同Pkg下跨Mould調用GUID或者跨Pkg調用GUID都是極其常見的)
- Step3: Dec中添加之后,你可以在該Pkg的各個Mouldle中使用該GUID。Password.c是屬於GenericUtilityLib這個mouldle的,同樣第一步先將gInspurUserPassWordFlagGuid添加到moudle的INF描述文檔中。
- Step4: 在inf添加了以后,該Moudle下的.c文檔即可以使用該Guild,編譯在編譯解析INF文檔時會變編譯處一個.c文檔並且把定義gInspurUserPassWordFlagGuid,那么處在該Mouldle下的所有.c文檔均可以使用extern聲明的方式,聲明GUID並且直接使用它。如下圖,我們是在Password.c中SetVaribale時使用的這個GUID,那么就可以直接在文件開始extern聲明該GUID。
梳理至此,大家對GUID的使用格式應該有個大概的掌握,總結如下:
1.1在dec中定義該GUID,其一是為了讓該Pkg下所有moudle都能看到該GUID且直接調用,其二是為跨Pkg使用該GUID時提供一個聲明接口。其他Pkg的程序若要使用該GUID只需要在INF文檔中添加DEC文件和GUID的聲明即可
1.2 INF文檔添加GUID是表明該GUID對本Moudle所有程序可見且可用
2. 用法
GUID作為全球唯一標識符,那么UEFI中GUID到底是如何使用的呢?常說的某個某個變量或者某個Protocol掛載在某個GUID下面又是什么意思呢?
/*以gRT->GetVariable()函數為例*/
1 typedef 2 EFI_RUNTIMESERVICE 3 EFI_STATUS 4 (EFIAPI *EFI_GET_VARIABLE) ( 5 IN CHAR16 *VariableName, 6 IN EFI_GUID * VendorGuid, 7 OUT UINT32 *Attributes OPTIONAL, 8 IN OUT UINTN *DataSize, 9 OUT VOID *Data 10 );
- gRT->GetVariable()得函數實體如下,樓主使用得是Insyde代碼,因此這里需要注意Insyde對這塊應該做了較大得修改封裝為了InsydeMoudlePkg,樓主為了照這個實體函數,花了好多時間,實在不應該。在此提示,不要用DEBUG()函數來定位,應該該模塊中得DebugLib中定義是NULL,所以我加了DEBUG()后沒有顯示。最終是采用CMOS方法,才找到這個函數。找到了函數實體,那我們就去追下code,看到底是如何索引GUID,並找到該GUID下掛載得變量數據得。