小華的部落格: EFI BIOS相關知識

搜尋此網誌

網頁

顯示具有 EFI BIOS相關知識 標籤的文章。 顯示所有文章
顯示具有 EFI BIOS相關知識 標籤的文章。 顯示所有文章

星期二, 9月 16, 2014

EDK2/EDKII Python Build Tool 兩三事 (Build.py)

EDK2 Python Build Tool 兩三事

最近因為工作需要,所以不得已逼自己去把EDK2 Python Build source code看完,看完後順便整理一下一些小重點,以免過陣子自己又忘記了。

     1)EDK_GLOBAL 
     這種定義的Macro只能給EDK1 driver使用,因為他會去檢查.inf 內的
     INF_VERSION  = 0x00010005 ,如果大於或是等於這個值就是當成EDK2,如果找不到這個值就會當成是EDK1。

因為不好用,所以就隨手改了一下CODE,讓他通吃EDK1 + EDK2 + FDF + DSC + DEC + INF

   2) Build Rule and Package rule
   在EDK2 中,他把EDK1原本的Build Rule & Package Rule 分別描述成:
        Tools_def.txt 
        Build_Rule.txt
        [Rule.$(Arch).$(ModuleType] 

好不好用看個人,不過如果你要支援原本EDK1 Package Rule時那就對不起啦,你要修改Python source code,不然你做不到。  例如說底下的EDK1 的COMPONENT_TYPE = FILE原本對應到某個Package Rule,但是在EDK2內不支援就是不支援,除非自己改python source code.

[Defines]
BASE_NAME               = xxxxx
FILE_GUID                   = 126A4D6A-C404-4200-8779-F327A4A79087
COMPONENT_TYPE  = FILE
BUILD_TYPE               = MAKEFILE

   3) Python v.s SQL
   Python build tool 只是拿SQL當成是存放他收集到的資料的一個地方,然後在另一個地方就可以去撈資料庫內的資訊然後寫對應的CODE去分析要幹嘛,所以rebuild的時候最好把這個資料庫暫存檔案刪除。 EX: Conf\.cache\build.db

   4) GenSection & GenFFS
   以前EDK1的這兩個工具也整合進去Python Build tool內了,所以想了解FDF是怎麼產生FV或是FD的人就請自行研究,不過他是另一隻Tool叫做GenFds.py。

   5) AutoGen.c v.s AutoGen.h
   偷偷產生的檔案用來存放一些PCD操作/有用到的PCD Value,GUID 定義跟一些偷塞的include... 如果是給PCD database使用的,他還會塞Dynamic PCD給PCD 資料庫當成初始化值。

    另外,Library 只會產生AutoGen.h 不會產生AutoGen.c,因為Library通常會跟某個Driver Link,所以等到真正要去產生Module make時,才會去檢查Library 內用到的GUID/PCD ,然後產生在Module's AutoGen.c內。

    6) Hard code
    恩,很多東西都寫死在Python build tool內,像是nmake command 要增加修改時就要改一改他,不過也是個好處,就是我可以偷加很多東西在裡面,然後不給你source code...哈!!!

   7) 產生執行檔
    .py  轉成 .exe 方式我自己再用的有兩種,一種是py2Exe不過版本過舊已經不能支援了,所以我採用EDK2 所建議的cx_Freeze 去轉換,轉換時還要搭配你的Python 版本,目前我看到的codebase內使用的是Python 2.7.3,所以應該以這個為主吧! 底下是EDK2 建議的方式:

Using cx_Freeze 4.2.3 with Python 2.7.2
Using cx_Freeze 3.0.3 with Python 2.5.4

  8) 嗯...有想到再說~


     
   




星期三, 2月 12, 2014

Python v.s UEFI EDK2 (EDKII)

這篇文章主要是幫自己紀錄一下學習EDK2 build process時的前置準備動作有哪些,後面會陸陸續續把這篇文章補齊,所以先留下個紀錄吧~

學習方式

    對於EDK2來說最大的轉變就是我一直提到的Build process,我常跟我周遭朋友說如果你要學好BIOS或是其他大型軟體專案,中間的『眉角』就是要把大型專案的學習方式分成:

     BUILD + CODE

當你有辦法分辨以及分開學習時,你才可以精準的掌握住甚麼是BUILD? 甚麼是CODE?
舉例來說,BUILD的部分就是屬於build rule/compiler rule/package rule ,簡單的說就是透過一些方式來把程式碼產生成binary,依照一些特定的layout來產生成一個BIOS ROM image;至於CODE的部分就屬於程式語言,像是C語言,組合語言的學習! 你唯有了解彼此之間的關係,你才能掌握關鍵處! 這也是我常跟朋友開玩笑說,你真的會"build+code"嗎?!

至於BUILD PROCESS的概念中,我也常常教導朋友去思考為什麼要這樣子做? 他解決了甚麼問題? 有沒有其他方式? 因此我常常由一個批次檔的概念外加一些淺而易懂的範例來讓他們知道說原來BUILD PROCESS原理是如此簡單,不過我沒打算在這邊寫詳細的解說,因為配合著畫圖邊解釋效果比較佳,如果大家有興趣又剛好在業界遇到我時再來跟我討論吧! ^^

所以記得,學習的方式就是BUILD + CODE分開來學!!!

前置動作
   有鑑於EDK2 BUILD PROCESS主要的部分已經改成Python 2.5/2.7開發,美其名是為了跨平台而準備,但是實際上卻沒有達成!  畢竟,EDK2在x86中並沒有拿Python 將所有win32 的工具重新寫一次,導致在x86平台中有一部分的python tool跟一部份的win32 tool,所以只能說『某些BUILD TOOLS』跨平台而已! 但是木已成舟,所以現在的x86上就變成了這個怪胎情況了!

   雖然我不討厭Python,但也不是擁護者,因為跨平台方式有很多種,他也不是最好的一種! 但是因為EDK2都選擇了Python,所以我也要強迫自己來學習他,秉持著工欲善其事,必先利其器的方式,我們先把除錯工具安裝好,以方便我們去分析與研究EDK2's Build.py

那有哪些東西要先安裝呢? 我個人偏好Visual Studio,因此我選擇了VS2010+PTVS 來當作是Debugger,安裝簡單! 當然你也可以選擇使用Eclipse Classic IDE + PyDev 的除錯方式 (感謝鳥公司John大大傾囊教學)!

所以如果你也想學Python,請跟著我一起安裝:

1. VS2010

2. Python tool for Visual Studio
https://pytools.codeplex.com/

3. Python 2.7.6 (目前EDK2還沒支援到Python 3.x,建議是安裝2.5.x/2.7.x)
http://www.python.org/download/releases/2.7.6/

Eclipse Classic IDE+PyDev

VS2010+PTVS


(未完待續...)










星期五, 9月 13, 2013

簡略介紹 EDKI與EDKII (EDK2) 的差別

這篇文章主要是簡單闡述一下EDKI 與 EDKII 在BIOS工程師眼中的差別在哪裡? !
在討論之前,我們先簡單說一下Package是甚麼東西?

Package是甚麼?
 
     在EDKI裡面,我們在寫UEFI driver的時候並不會有所謂的 "Module" 的概念在裡面。我們開發的時候都是以 driver為單位,並不會考慮一些模組化的問題。
 
[註] UEFI 的可執行檔案我們的術語是Image或是Driver,所以當你聽到這個術語時把他當成類似EXE執行檔就可以了。
 
    而 EDKII裡面,他加上了 Package這個概念(模組化)。其實可以把它看成是一個目錄,而這個目錄名稱會是"xxxPkg",而目錄裡面就是一堆相關的UEFI driver。
 
所謂的相關的UEFI Driver是說,假如你看到目錄名稱是"NetworkPkg",那麼這個Package裡面的東西就跟Network有關,所以在這個目錄內可以有其他子目錄去存放著 PEI/DXE/SMM/APP  Driver或是 Library
 
而組成一個 Package的元素(一個PKG目錄內)必定包含一個 *.dec  *.dsc
 
Package的好處是甚麼? 就是"獨立"
 
在EDKI 的時候,你想單獨產生一個特定的CODE時,你至少"整套CODE"要先產生一次! 而EDKII使用這種"獨立"的概念就不需要整套CODE build完才產生你要的CODE!
 
但也是因為獨立,所以有很多地方都是為了解決獨立出來問題而去改了一堆Build tool動作跟你描述.dsc還有.FDF的動作。
 

EDKI與EDKII主要的差別?

- Build process的改變
EDKI : ProcessDsc.exe執行將 *.inf 轉換成 makefile 的動作
EDKII: Build.py  去處理,同時還會產生  AutoGen.c & AutoGen.h (Parsing *.dec )

- DSC file / FDF file
EDKI裡,決定一個 driver要放在那一個 firmware volume裡是在"1個.dsc"就可以決定的,通常都會是叫做PlatformDsc.dsc或是 Build.dsc這個檔案!
 
在檔案內你會透過FV=FVREVOVERY的方式把底下的UEFI Driver通通放進去FVREVOVERY.FV,接著透過Flashmap.fdf去規劃ROM的區域,然後決定 FVMAIN.FV放進去哪個區域。
 
但是 EDKII為了實現 Package這個概念,所以.dsc不再用來描述UEFI driver要放到哪個FV,而只是拿來決定要不要BUILD這目錄下的UEFI driver而已!
描述那些UEFI DRIVER放到ROM的哪個位置的動作就變成EDKII新的FDF SPEC所描述的那些動作,所以你必須要新的FDF 格式中描述你那些UEFI driver是要放進去ROM裡面的。
 
- PCD/DEC
因為EDKII還希望做到不用改到Source code就能夠改變CODE的行為,所以延伸出了PCD這種控制方式,不過我是覺得它需要額外寫TOOL去達到他的理念而增加了許多BIOS工程師的麻煩。
 
  PCD我自己是分成兩部分學習,一部分是屬於如何在RUNTIME管理PCD Database的部分,另一部分就是如何透過DEC FILE去產生PCD的預設值以及有哪些PCD LIB與Header file可以存取他,因為這部分牽扯到實作面(靠的是C語言巨集),所以需要邊開著CODE邊解釋,所以很難使用文章解釋,希望大家有機會在業界遇到我時在幫大家解釋吧^^.
 
  你暫時可以簡單把他想像成是一個變數宣告的方式,變數會有生命週期(整個RUNTIME或是某一個DRIVER而已)與屬性(唯讀/可讀寫),可以方便你在CODE裡面存取他!
 
  以上的部分大致上就是EDKI 與EDKII的差別,對於BIOS工程師來說可能會需要去習慣新的DSC/INF/DEC/FDF寫法,以及BUILD.py這個工具的用法,其他的就是要去習慣各家IBV對於PCD的作法!
 
EDKI與EDKII Reference Code的差別?
 
EDKI 與 EDKII Reference code的部分,以目前我接觸到的部分來說最大的差別在於"移植的觀念"。
 
EDKI 身不好移植到不同平台,所以EDKII在這部分是希望能夠好移植,而他的使用的方式是約束大家使用同一個EntryPoint,也就是說在EDKII RC code部分,如果大家的EntryPoint都能指向同一個地方做完一些跟Platform相關的事情之後再跳回去Driver EntryPont,那麼下次如果要移植到不同平台時,我只要把這個共通的EntryPoint改寫就好了。
 
所以在 RC CODE部分,你會看到他先透過共同的_ModuleEntryPoint,然後再從C_FLAG設定的給EDKII Gule Library的EntryPoint 跳回去你設定的Driver EntryPoint,這就是他主要的改變!
 
因為EDKII Glue Library做掉一些事情了,所以以前在UEFI Driver內可能一開始會去呼叫InitDxeLib()來初始化gBS/gRT/gST的動作就不用做了,另外Smm Driver寫法也略有不同,其實都是因為被偷做,所以你可以少做!
 
EDKI與EDKII Code Size的差別?
由於EDKI 本身在LIBRARY撰寫部分並沒有明確規範,所以連結出來的可執行檔的CODE SIZE會比較大,在EDKII上也針對了這部分重新改寫了原來的LIBRARY以減少連結時的CODE SIZE,因此理論上EDKII 環境下產生出來的可執行檔SIZE應該要寫一些。
 
希望簡略的解釋能更幫助大家在學習EDKII 甚至轉換到EDKII的時候不會驚慌失措,也比較知道為什麼要改成這樣子。




星期三, 5月 23, 2012

uEFI EDKII Using Re-Mapped Functions

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。

感覺就像是抽換掉底層的東西,上層不用改變,這樣說不知道看倌們有沒有那種感覺?!

今天就說到這邊,下課!

星期三, 10月 19, 2011

UEFI #pragma intrinsic( function1 [, function2, ...] )

在UEFI C語言中使用 #pragma intrinsic( function1 [, function2, ...] )方式可以簡化你拉Library的動作,但是這個功能是與Compiler相關,因此當你不使用Microsoft Compiler時,可能就要注意原本的UEFI CODE中使用這些方法的地方可能會有問題!
使用方式是在任何xxx.c 中宣告函數原型跟 #pragma intrinsic(),之後就可以在你的CODE中使用他!
//宣告函數原型int            _inp (unsigned short port);
int            _outp (unsigned short port, int databyte );


#pragma intrinsic(_inp)
#pragma intrinsic(_outp)


VOID CMOSWrite(UINT8 Port,UINT8 databyte)
{
_outp(0×70, Port);
_outp(0×71, databyte);
}



參考網站 : 
http://msdn.microsoft.com/zh-tw/library/tzkfha43.aspx

星期二, 9月 06, 2011

UEFI Screenshot (Capture screen)

EFI Shell 底下螢幕抓圖(抓屏)方式:

1) 切換到Graphic mode
    ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenGraphics);

2)使用Gop->Blt將螢幕圖抓下來

  GraphicsOutput->Blt(GraphicsOutput,
                      Image.PixelData,
                      EfiBltVideoToBltBuffer,  <--此參數決定你要抓圖還是顯示圖
                      0,
                      0,
                      0,
                      0,
                      Image.Width,
                      Image.Height,
                      0);


3)切換回Text Mode

[Note] 單純在Text Mode呼叫GOP->Blt會抓不到東西.

星期二, 7月 05, 2011

USB Class

底下這個網站記錄著一些跟USB有關的Class資訊,可以方便你查詢:

像是一般我們常會去使用Descriptor 去判斷這個DEVICE的類別是甚麼:



  Status = UsbIoPpi->UsbGetInterfaceDescriptor (
                 ...
                 &InterfaceDesc);
...

  if ((InterfaceDesc->InterfaceClass != 0x08) ...) {
    return EFI_NOT_FOUND;
  }


參考網站:

http://www.xat.nl/en/riscos/sw/usb/class.htm

星期四, 6月 30, 2011

EFI需要注意的一些C語言小細節

底下是節錄一些我們Team自己內部分享的一些心得,讓大家知道其實C語言有許許多多的小地方是需要大家注意的!

1.指標最大的問題是Compiler不會做邊界檢查

    ex: a[10];
          p=&a[0];
          *(p+13];  <--這種操作Compiler並不會跟你說有問題


2. Free(p) ;同一個指標只能free 一次,當free(p) 兩次就會出事情
 ...


3.memcopy(dst,src,size)時記得size不能比目的大
 ex:
      src[100],dsc[50];
      memcopy(dsc,src,sizeof(src));  <--溢位
      memcopy(dsc,src,sizeof(dsc));  <--沒事

...


UEFI 開發過程中最大的問題~

大家都知道UEFI已經變成這個世代中的BIOS代名詞,但是這個環境下在開發BIOS的時候最怕遇到甚麼事情呢?

答案就是: C語言指標的邊界檢查

指標這個東西在C的環境中讓人又愛又怕。愛的地方是因為指標可以任意的轉型態、任意的操作你想存取的記憶體區塊,但是往往致命的吸引力中就會有他無可避免的壞處!

例如,你可以宣告一個陣列 a[10]; 然後拿一個指標 p指向這個陣列
但是當你的code寫成 *(p+13) 時,就會是個大麻煩!

因為Compiler 並不會告訴你說,嘿! 兄弟你的指標超出存取範圍了! 然後當CODE執行到那邊的時候就出現當機或是難以解釋的事件發生! 往往悲劇就是出現在不注意的小地方~

所以BIOS工程師在撰寫CODE的時候就必須對於指標操作很清楚,不然在UEFI BIOS環境下一定會出現許許多多靈異事件的~ (以前Legacy BIOS最被忽略的是堆疊PUSH/POP沒對齊,現在變成指標 >.<)

不過可喜可賀的是我們家的BIOS工程師對於這一點都很講究啦~

星期三, 9月 15, 2010

#include 用法

很多朋友在問我 EFI 中如果把#include 寫成下面兩種形式,差別在哪裡?

#include
#include "AAA.h"

我個人認為差別只有在一個不會去當前目錄找,只參考[includes.common],另一個會先去當前目錄找,然後再參考[includes.common]。

而Compiler 在找AAA.h 時並不會連同子目錄一起找,因此你要指定好完整的路徑給他。

另外要注意的事情是[includes.common]路徑中,被先找到的AAA.h 會先被參考,所以同樣兩個路徑內都有AAA.h時,會參考先找到的那一個。

星期二, 7月 27, 2010

Memory Access

前陣子在幫同事看一個BUG,他的問題是由 ASL code 透過我們BIOS端的所提供的 ACPI NVS buffer傳遞資料,然後在SMI callback的Function內我們透過一個Data structure指標去存取資料,但是位址會偏移兩個Byte.

他原來的Data Structure定義如下:
UINT16;
UINT32;
UINT8;

當他存取UINT8欄位時,資料位址卻偏移了!

後來發現,OS的ASL code內在存取記憶體時是Byte為單位,也就是有做過記憶體對齊!
因此,在我們EFI code內,我們就必須透過 #pragma pack(1) 來做相對應的事情,不然你在存取記憶體內容時會讀到錯誤的值。


星期日, 7月 11, 2010

EFI_DRIVER_ENTRY_POINT() 的意義

很多人剛開始學習EFI的時候,一定會看到你的Driver.c內有一個EFI_DRIVER_ENTRY_POINT()巨集,那他到底是幹甚麼的呢?

如果你有追進去看他的定義,你就會發現在一般的情況下,他其實是一個空的巨集定義
也就是不代表任何意義,在你Compiler code之後,也不會產生任何東西! 因此,在你的Driver.c內有沒有這個巨集並不會影響到你的code的執行!

不過,一般我們都還是會定義成跟你的Driver EntryPoint函數名稱一樣,來增加"可讀性"

除了一般的情況之外,如果你想把你的Driver放到NT模擬器下面執行時,這個巨集就非常重要了! 因為Window 32 bit環境下的執行檔案的進入點跟EFI不同,所以你的Driver想要在模擬器下執行時,你就必須透過這個巨集來重新定義函數原型宣告,不然你就沒辦法在NT下的模擬器執行你的EFI Driver.

所以結論就是:
如果你沒有要在NT模擬器跑你的EFI Driver,那你是可以忽略這個寫法! 但是,還是建議你保持良好的寫code習慣,增加可讀性,所以多一行code應該是不會花你太多時間啦~

星期三, 6月 30, 2010

EFI_SOURCE

一般在.dsc 中都會去描述你的EFI Driver所在位置
而加入$(EFI_SOURCE)跟沒有加入的差別在哪裡?

答案就是:

有加 $(EFI_SOURCE) 就會是絕對位置
沒加 $(EFI_SOURCE) 就會是相對位置

星期四, 5月 20, 2010

Unicode 字元查詢

在寫UEFI code的人一定常常會用到一些unicode字元,尤其是在SetupMenu.
而有一些特殊字元顯示在畫面上時可能會需要做一些修改,此時如果能知道那個字元的形狀,修改起來就更方便。

這邊就介紹一下我常用的網站,用來查詢 Unicode 字元的地方:

http://www.fileformat.info/info/unicode/char/search.htm?q=U%2B25ba&preview=entity

這個網站可以方便你搜尋你要的字元,你只要在Unicode Character Search的地方的Query輸入你想要的搜尋字元 (格式: U + Unicode) ,例如我要查詢0x25BA這個字元我就輸入:


按下Search 後,就會在下面的地方出現相關的資訊,如下圖所示:

你可以看到我查詢的字元是一個"右箭頭"........ 很方便吧! ^^

星期三, 3月 03, 2010

有趣的Code-BootOption 的建立

今天在看BootOption建立的code時發現他會去跳掉同時有SimpleFileSystem&BlkIo protocol的Handle,只留下Hanlde 上面有SimpleFileSystem的!

雖然很搞不清楚他為什麼要這樣做,但是一般情況下不可能只有SimpleFileSystem存在!
所以應該是要防呆吧! 怕哪一天真的有Hanlde上面只掛SimpleFileSystem而沒有BlkIo.

這種Hanlde他還是會幫他建立出一個BootOption!


gBS->LocateHandleBuffer (
...
&gEfiSimpleFileSystemProtocolGuid,
...
);
for (Index = 0; Index < NumberFileSystemHandles; Index++) {
Status = gBS->HandleProtocol (
...
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (!EFI_ERROR (Status)) {

continue; //這邊會Skip
}
...
}

星期一, 10月 19, 2009

InsertList

最近常看EFI的code,所以就順便整理一下一些C的資料結構的東東。

1.EFI中都是喜歡使用雙向鏈結串列(doubly linked list)
在雙向鏈結串列中的節點(Node)至少有2個欄位,一個為向後結欄 (BackLink) ,另一個為向前鏈結欄 ( ForwardLink ) 。其必要的宣告為:
 
    typedef struct node *node_ptr ;
    typedef struct node {
        node_ptr Flink ;
        node_ptr Blink ;
        } ;

2.插入鏈結串列可以從頭插入或是從尾插入兩種,底下是圖示來表示這兩種差別。
InsertHeadList();
InsertTailList();



這些鏈結的運用在EFI中隨處可見,所以在這邊留下筆記來紀錄一下學習心得!

星期日, 5月 17, 2009

Intel EFI Specs資訊

整理一下以前在Intel網站抓的一些Specs資訊。
怕自己忘記去哪下載!
所以就留下筆記記錄一下!

這些都是Intel 所提供的相關文件,有興趣的可以去Intel網站抓。

ftp://download.intel.com/technology/framework/docs
















































































































































































ftp://download.intel.com/technology/framework/docs
Reference
www.intel.com

星期日, 1月 11, 2009

EFI 的新體驗~

以前在做案子的時候只管如何去把OEM/ODM features做出來,所以比較少時間去慢慢的消化EFI code的內容,其實在EFI中有很多小地方的事情是以前學C語言的時候從來都沒有注意過的事情!而這些小地方也讓我對C語言有了更進一步的體驗~

像是最近研究EFI code的過程中發現了一個好玩的東西,原來C也有類似 Strong/Weak 的寫法!
以前一直笨笨的想說C要怎麼去做這部份的東西,還一直以為做不到! 原來這些東西都已經有參考範例在EFI code之中了! 只是以前壓根子都沒想過原來C可以這樣玩~在慢慢消化EFI code的過程中還真的是驚奇不斷咧!

從最近學習EFI code的過程之中,真的讓我對C語言有了更深一層的了解;在此時回頭去想想以前自己在學校中老是以為我已經對C有一定層度的認知~現在才發現 "原來我只是個井底之蛙啊"....

星期一, 1月 21, 2008

EFI ㄧ些小筆記

紀錄一些EFI中有關Firmware Device 內的專有名詞的解釋。
如下圖所示,這是EFI 模組化後在Firmware Device 內擺放一些模組化的範例圖:


其中:
1.FD=Firmware Device,他是一個實體的物體容器,用來儲存EFI code以及一些資料。

2.FV=Firmware volume ,卷,他是類似檔案系統的一種管理方式。
1 個FD中可以有很多個 FV

3.ㄧ般常見的FV :
(a) 儲存EFI code,你的BIOS Code可能會分成好幾個不同的FV
(b) 非揮發性資料,像是一些NV Store 變數、config 文件...等。

4. FFS = Firmware File System ,每一個FV都遵循這種檔案格式。
1 個FV 內可以有很多個FFS。

5. Section = 每一個FFS內還可以分成不同的Section。

FD > FV > FFS > Section

Reference
www.intel.com

星期四, 11月 15, 2007

EFI Framework 概述

如果有下載Intel EFI Spec的人就知道每次提到EFI的時候就會有一個很大的綠色的H,這個就是EFI 的framework。

什麼是Framework呢? 這邊就簡單說一下整個EFI framework架構。

我個人猜想,當初Intel 開發EFI其實只是為了要擴充BIOS的功能,因為在Legacy BIOS的年代,很多的東西都沒有模組化,因此當硬體或是Platform有比較大的變動的時候,對於整個BIOS開發的時間就會延長,那種感覺就好像是你每次都要對一個新的硬體重新寫一次你的BIOS程式碼,很沒有效率。

另外在Legacy BIOS年代,所有的BIOS程式碼的開發幾乎都是不同的BIOS vendor與Chipset 廠商ㄧ同合作,因此不同家的BIOS Vendor對於相同Chipset 廠商所寫出來的程式碼的穩定度就會不同,這對於 Intel 來說就等於要多花好幾倍的時間去跟不同BIOS Vendor 來討論以及處理問題。

因此,假如Intel 能夠把底層的BIOS程式碼變成模組化容易抽換,那麼BIOS在開發的過程中就會快速以及方便許多,而這種概念就像是Windows裡面的HAL 層的概念,簡單說在Windows系統中實際存取硬體是透過ㄧ個叫做HAL介面的處理,所以當Windows想要在不同的硬體上執行的時候,他只要把HAL的介面換成新的硬體的處理方式就可以了,而在Windows可以不用再重新改寫,例如你把Windows拿到Apple上面去執行,對於微軟的工程師來說,只要把HAL從新改寫就可以了。

而EFI的Framework 就像是HAL,Intel 本身提供了一些Protocol以及一些Lib來存取他們的硬體,而這一層就叫做Framework。對於Intel來說,不管你是哪一家的BIOS Vendor就不會再出現A廠商存取Intel Chipset有問題而B廠商不會,因為最底層都是Intel 自己負責。

而建構在Framework 上的一些功能就是各家BIOS Vendor自己去負責,感覺就像我之前說的,Inetl 留下一些地方給BIOS Vendor填寫他們的程式碼,然後BIOS Vendor在留下一些地方給OEM/ODM BIOS填寫ㄧ些程式碼,彼此關係就是一層一層環環相扣。

這邊還要提到EFI Framework 除了前面說的那些之外,他還提供了一些Boot Flow的控制,這就像是說從Power On--->POST--->Boot to OS的一些流程的控制也是由這個Framework 提供,感覺就像是你寫了一個main{},而裡面的FunA()/FunB()/FunC() 的先後順序的執行你也都寫好了,之後FunA() 內要填什麼樣的子程式碼就屬於BIOS Vendor跟OEM/ODM BIOS自己決定了。
//--------------------------------------------------
// EFI Framework 的概念與C語言對應的示意圖
//--------------------------------------------------
#include <--Intel提供的函數
main() <--Intel 提供的Boot Flow
{
Dispatch FunA(); <--SEC
Dispatch FunB(); <--PEI
Dispatch FunC(); <--DXE
Dispatch FunD(); <--BDS
...
}

EFI Framework還有另一個優點就是移植性高,例如Intel 可以把整個EFI Framework概念移到嵌入式系統上去實做BIOS,這樣子他們能夠開發的市場就會越來越大。

前面提到這些都是Intel提供的EFI Framework,那麼AMD/其他廠商怎麼辦? 對,我也在想這個問題,由上面的說法可以看出Intel 的野心,他想把原本BIOS Vendor做的事情自己拿來做,為了不讓人家知道太多Chipset內的秘密,他自己寫Chipset的函數並做成Framework給BIOS vendor使用,所以我個人在思考幾個問題:

a) 假設不同 BIOS Vendor 都使用相同的函數的情況下,彼此的優缺點是不是只剩下誰提供的OEM/ODM Features比較多 ?

b) 假設不同 BIOS Vendor 都使用相同的Framework下,當底層換成AMD或是其他廠商後,彼此的優缺點是不是只剩下誰對不同廠商的支援度比較高,市場佔有率就比較高?

c)假設OEM/ODM BIOS 都使用相同的Framework後,開發時間縮短相對的被取代的性質是否也相對提高?

d) Others..

以上大致上就是個人對於EFI Framework 的一些理解跟想法,如有誤請先進不吝指正,謝謝!