BIOS最近熱門話題除了Windows 8之外,就是EDK II / EDK 2了。
想必大家應該也都開始在玩EDK II了,不過這個EDKII有沒有甚麼地方是跟EDK 衝突的呢?
答案是: 【有】
在你使用 EDKII Glue Library時,裡面有一個東西是需要大家注意的地方,就是所謂的Re-Mapped Functions.
在使用手冊中就開宗明義地跟你說,他為了解決EDKII Glue Library與EDK codebase的函數名稱衝突,所以【有些】函數名稱被他使用了巨集(Macro)來重新定義了。
這是甚麼意思呢? 他提出了一個範例:
如果你的Driver有include到這個Header file 叫做 "EdkIIGlueBaseMemoryLib.h" 或是"EdkIIGlueMemoryAllocationLib.h",他會使用C語言的#define重定義定CopyMem函數名稱 (不只這一個函數名稱還有很多個) :
#define CopyMem(_DESTINATIONBUFFER, _SOURCEBUFFER, _LENGTH)
GlueCopyMem(_DESTINATIONBUFFER, _SOURCEBUFFER, _LENGTH)
這個定義會造成你原本在EDK source code內呼叫:
gBS->CopyMem (Dest, Source, Length);
的這個動作,會在C 語言的Preprocessor時被換名稱成:
gBS->GlueCopyMem (Dest, Source, Length);
然後在Compiler過程中就會造成一個錯誤訊息,而這個錯誤訊息會告訴你GlueCopyMem並不是EFI_BOOT_SERVICES中的一個成員(Members),這是因為那個#define 的關係,所以你的函數名稱會在Preprocessor時被偷偷換掉,因此為了避免這個Re-Mapped function的問題,請把你原先的CODE加上括號來避免Compiler error問題,如下所示:
(gBS->CopyMem) (Dest, Source, Length);
那...............幹嘛搞那麼麻煩呢?
我個人認為EDKII這些Library 就是想把大家平常會幹的事情又可能跟硬體相依性高的事情全部指向一個共同的Library內(ex: EntryPoint/Functions),以後如果要換不同平台的時候,只要把Library抽換換掉就可以了。
用說的不清楚,我來個範例好了:
以前我們會在source code中直接呼叫 gBS->FreePool();來釋放記憶體,如果導入/使用 EDKII Glue Library,你就應該寫成呼叫EDKII Glue Library所提供的FreePool(); 來取代你原來的做法,而 EdkIIGlueBaseMemoryLib.h/EdkIIGlueMemoryAllocationLib.h 中會去重新定義名稱,所以實際上是呼叫FreePool() 等於呼叫 GlueFreePool() :
#define FreePool(_BUFFER) GlueFreePool(_BUFFER)
而在Glue Library中,以目前EDK中,其實他還是去呼叫 gBS->FreePool(); 來釋放記憶體:
GlueFreePool (IN VOID *Buffer)
{
...
Status = (gBS->FreePool) (Buffer);
...
}
幹嘛繞一大圈??? 其實那這樣子做的好處是如果有一天,你釋放記憶體的方式不再是gBS->FreePool();時,你只要換掉你Link的那一個 Library,就可以做到你要的目的,而不用直接改到你原來的Source Code。
感覺就像是抽換掉底層的東西,上層不用改變,這樣說不知道看倌們有沒有那種感覺?!
今天就說到這邊,下課!