2018年11月19日 星期一

安裝與定位PPI

PPI(PEIM to PEIM Interface)是本文章要介紹的重點, 兩個PEIM可以利用PPI來溝通, 本範例是要在一個PEIM安裝PPI然後在另一個PEIM找到這個PPI, 檔案連結如下:

https://drive.google.com/open?id=1oQgOX_olIqEsNo9d-BDsknXM24QGRROW

在CloudPeim和CloudPeim2兩支inf的部分, 我都加入了gEfiCloudPpiSampleGuid這個[Ppis], 這個Guid的值是從Nt32Pkg.dec產生的, 本範例的PPI就是用這個Guid去辨認, 在CloudPpiSample.h的部分, PEI_CLOUD_PPI_SAMPLE_PPI_GUID的值要和dec裡一樣, 接下來的語法雖然是C但比較少見, 我在系微第一次碰到也覺得很神奇, 因為鎖定本部落格的讀者群是略有C語言基礎的新手, 所以大概提一下,
typedef
VOID
(EFIAPI *PEI_CLOUD_PPI_SAMPLE_INTERFACE) (
  IN CONST CHAR8 *Format,
  ...
  );
它是宣告函式的型態, 沒有宣告函示的內容, 但是下面的:
typedef struct {
  PEI_CLOUD_PPI_SAMPLE_INTERFACE  Print;
} EFI_PEI_CLOUD_PPI_SAMPLE_PPI;
正因為有了型態所以可以宣告成一個含有Print這個Function的結構(struct), 再來看到CloudPeim.c, 第8行開始的Print也是函式型態, 用跟H檔相同的手法可以宣告mCloudSamplePpi, 而EFI_PEI_PPI_DESCRIPTOR有固定的格式, 基本上就照抄, 再來看到主程式, 首先InstallPpi, 這是代表把這支PPI裝到PPI database裡, 像InstallPpi這種code專案裡都有原始碼, 但本研究還未進展到去追UEFI核心服務的階段所以現在先不提, LocatePpi是從PPI database去定位出一個PPI實體(Instance)供PEIM使用, 本範例中實體就是CloudPpiTest, 順帶一提如果函數需要傳入雙指標的參數, 那可以先定義一個指標變數再把它的位址用&傳給函式以達成雙指標的需求, 這裡有一個EFI_ERROR(), 它是一個巨集功能是沒錯誤就傳0有錯誤傳錯誤碼, 所以若沒錯誤會先執行一次Print(), 這裡印出的是"1st TonyWu", TonyWu是我主管所以意思就是TonyWu是第一名, 輿論說Tony的目標是追過我前主管Timmy(王榮安), 我是覺得這兩位都很厲害難分軒輊, 當然我的目標又和他們不同我是希望徹徹底底把一套專案精熟, 雖然隔行如隔山比如我去寫Linux Driver功力可能剩兩成, 但至少希望NT32這套專案裡能追至極限, 可惜的是編譯器沒有原始碼所以最後一定會卡在編譯器, 不過可以等退休再去國外討教, 總之我放在Buid裡面的LOG.txt會顯示PPI成功運行的訊息, 接下來簡單介紹Print, 因為偷懶的關係這個Print只能處理十進制, 十六進制, 字元和字串, 相信各位讀者都有C語言基礎所以我不多贅言, \0是代表字串到盡頭, 所以*Format == '\0'代表字串結束就跳出迴圈, 再來介紹不定參數, 它有固定的用法首先要宣告一個VA_LIST, 然後用VA_START使VA_LIST指向第一個參數, 用VA_ARG依序讀取不定參數(不定參數就是不限定個數和型態的參數), 所以要讀十六進制就用VA_ARG(VaListMarker, UINTN), 要讀字串就用VA_ARG(VaListMarker, CHAR16* ), 最後VA_END代表處理結束, 至於這個DebugPrint( )是從Debug.h裡抄出來的, 它的原型是MdeModulePkg\Library\PeiDxeDebugLibReportStatusCode裡的DebugLib.c, 裡面的演算法連我這個有8年多經驗的工程師都覺得很煩懶得看, 相信讀者也不會想了解, 最後看CloudPeim2.c, 為了宣告PPI Instance它include了CloudPpiSample.h, 其他LocatePpi的部分和CloudPeim.c雷同

沒有留言:

張貼留言