經過三個月的努力,終於完成了階段性的任務,從 NTC 畢業了。
雖然說期末考被我玩炸了,不過看了一下期中考和作業成績,要過關應該還算是容易。
大家紛紛整理裝備往各層移動,一邊和同學說再見,一邊深知這種團體日子應該在今天就會做個總結。
大家都撤了,和 Ian 兩個人在空蕩蕩的會議室等別人來接,心情是很忐忑不安,但潛意識更希望能趕快與工作接軌,畢竟收了錢不是來讀書的,NTC 只是個小門檻。
Vincent 過來把兩人叫出去,分配了位置,結果真的如 mail 所說:暫時座位:x 樓 xx 號。
真囧,仔細想想,我的工作之路好像一路充滿笨點:識別證名字打錯,丟給 HR 重做,到現在還沒來。結果小三梯的學弟都有照片了,我識別證還是白牌,現在連座位都是暫時配置,搞什麼呢。。。
安頓好了之後,跑去問兩位學長接下來該準備什麼。請購單、SVN 申請,去找指導學長,一步步來,穩穩地走。
拷貝 codebase,porting guide,相關 spec。東西都齊了,剩下的就是這三個月磨出來的工程思維,不懂的,搜;不會的,查,心情不能游移,我要變強,我要成為首屈一指的 BIOS 工程師。
不過在達到目標之前,說的話都是屁就是了。
開 Slickedit,導入 codebase 做 tag,開 referrence,比照 code,追函數,查電氣特性,一切都是那麼熟悉,NTC 紮下來的底子果然有用。
接下來就是等 MIS 來新筆電、19" 螢幕、鍵鼠組、Dongle,林林總總的雞絲。
希望接下來的日子大家都能順利,成功就在不遠的地方,加油吧,1004。
2010年7月7日 星期三
PEIM & PPI
入口函式原型 (PeiApi.h @ EDK):
比較常用到的幾個函數:
這個函數要注意的地方就是 CreateHOB 他只幫你弄個 HEADER 出來,要塞 HOB 資料,要自己拉空間出來,算好 OFFSET 是要件。
函數成功的話,HobBuffer 就會指一塊空間出來給你。
再來也是算 OFFSET 把資料 COPY 進去,就行了。
DXE Phase 下:
藉此取得 HOBLIST,然後再用想對應的函數把你要的 HOB 拉出來就行了,如果我上面 HOB 的 TYPE 是 EFI_HOB_TYPE_GUID_EXTENSION,同時這個 HOB.Name 有加以指定一個 GUID,那我在 DXE Phase 下就能使用下列函數把 HOB 倒出來:
關於為什麼 PEI Service Table 要做成雙指標,在 BIOSREN 論壇 srcore 兄做了很漂亮的解釋,這邊借轉載並改成台灣用語:
typedef EFI_STATUS (EFIAPI *EFI_PEIM_ENTRY_POINT)( IN EFI_FFS_FILE_HEADER * FfsHeader, IN EFI_PEI_SERVICES **PeiServices );
比較常用到的幾個函數:
(**PeiServices).LocatePpi這個函數要注意的就是 PEI Phase 下 PPI 的存放和 DXE 下存放 PROTOCOL 略有不同,因為 PEI FOUNDATION 會用來存放 PPI DB,所以很有可能一個 DB 裡 N 個 INSTANCE,第三個參數就是讓你選第幾個 INSTANCE 用的,第一個為 0,以此類推。
Status = (**PeiServices).CreateHob ( PeiServices, EFI_HOB_TYPE_XXX, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + PrivateDataSize), (VOID**) &HobBuffer );
這個函數要注意的地方就是 CreateHOB 他只幫你弄個 HEADER 出來,要塞 HOB 資料,要自己拉空間出來,算好 OFFSET 是要件。
函數成功的話,HobBuffer 就會指一塊空間出來給你。
(**PeiServices).CopyMem ( (VOID*)(((UINT8*) HobBuffer) + sizeof (EFI_HOB_GUID_TYPE)), (VOID*) PrivateData, (UINTN) PrivateDataSize );
再來也是算 OFFSET 把資料 COPY 進去,就行了。
DXE Phase 下:
EFI_HOB_HANDOFF_INFORMATION_TABLE *HobList; LibGetSystemConfigurationTable (&gEfiHobListGuid, (VOID**) &HobList);
藉此取得 HOBLIST,然後再用想對應的函數把你要的 HOB 拉出來就行了,如果我上面 HOB 的 TYPE 是 EFI_HOB_TYPE_GUID_EXTENSION,同時這個 HOB.Name 有加以指定一個 GUID,那我在 DXE Phase 下就能使用下列函數把 HOB 倒出來:
GetNextGuidHob ((VOID**) &HobList, &HobNameGuid, (VOID**) &HobContent, &BufferSize);
關於為什麼 PEI Service Table 要做成雙指標,在 BIOSREN 論壇 srcore 兄做了很漂亮的解釋,這邊借轉載並改成台灣用語:
『這個問題細究起來有點意思。這裡頭有歷史原因,其實依現在看來,定義成直接指標就可以了。』
『PEI 階段中,在 Main Memory 可用之前,PEI Core 和 PEIM 都必須在 flash 上 XIP。XIP 就意味著全域變數只能讀,不能寫。所以PEI Core在 memory 可用並且把自己 Shadow 到 memory 之前,是不可以用全域變數保存自己在 Stack 中分配的 PrivateData 的位址的。』
『這就是說我們必須有一種方法能讓 PEI CORE 在 PEIM 調用 PEI Service 的時候,能從傳進來的指向 PEI Serivces Table 的間接指標得到 PEI CORE 自己私有資料的位址。』
『當初,規範定義 EFI_PEI_SERVICES ** 是期望如下的 PEI CORE 的實現:舉例說明』
typedef struct { ... EFI_PEI_SERVICES *PS, ... } PEI_CORE_DATA;
『PEI_CORE_DATA 在 Stack 上分配,PS 域被初始化為 PEI Core 資料段中 PEI Service Table 的指標。』
『&PEI_CORE_DATA.PS 不就是EFI_PEI_SERVICES ** 嗎?通過 CR 就可能得到 Stack 上 PEI_CORE_DATA 的地址。』
『注意,這裡有個前提,就是 PEI Service Table 中所有域的值都是固定的,作為一個 PEI Core 的全域變數存放在資料段中。』
『對,這就是定義 EFI_PEI_SERVICES ** 的由來。』
『有人會問,如果PEI CORE按照如下實現:』
typedef struct { ... EFI_PEI_SERVICES PSTable, ... } PEI_CORE_DATA;
『就是說在 PEI Core 的 PrivateData 中定義一份 PEI Service Table 而不是指向它的指標,PEI Core 在初始化的時候將自己資料段中 PEI Service Table 作為範本拷到 PEI_CORE_DATA.PSTable 中。』
『這樣,就只用定義 EFI_PEI_SERVICES * (即 &PEI_CORE_DATA.PSTable)就可以了。確實如此,但規範仍然定義 EFI_PEI_SERVICES **,是考慮到 PEI Service Table 是固定的,可以直接放在 flash 上 PEI Core image 的資料段裡,PEI CORE 私有資料裡有一個指標指向它就可以了,這樣可以省掉一些對 temporary memory 的佔用,畢竟 temporary memory 的資源還是比較寶貴的。』
『瞭解了它的最初的設計意圖,那為什麼說回過頭來看,其實定義成直接指標就可以了?』
『因為 PEI CIS 規範的修訂使得 PEI Service Table 裡面的值不再是 build time 決定之後就不變的了。PEI CIS 0.91 在 PEI Service Table 加入了 CPU IO PPI 和 PCI CFG PPI 的指標。這兩個指標必須在執行時填入,所以 PEI Service Table 不能再放在 flash 上了,它必須被放到 memory 裡,這樣它才能被修改。』
『所以現在PEI CORE的實現一般是這樣:』
typedef struct { ... EFI_PEI_SERVICES *PS, ... ... EFI_PEI_SERVICES PSTable, ... } PEI_CORE_DATA;
『PEI Core 在初始化的時候將自己資料段中 PEI Service Table 作為模組拷到 PEI_CORE_DATA.PSTable 中,然後 PEI_CORE_DATA.PS = &PEI_CORE_DATA.PSTable。』
訂閱:
文章 (Atom)