2012年5月25日 星期五

UEFI/PI (7) UEFI Firmware Hierarchy


  • UEFI Firmware Hierarchy
      1. Firmware Storage
          Firmware Storage 是非揮發性的memory儲存BISO或Firmware的code。UEFI的其中一個優勢是DXE和PEI 可以把code解壓到firmware storage外。 Firmware Storage最小的單位是UEFI Firmware File,再來是Firmware File System(FFS)、Firmware Volumn(FV)及Firmware Device(FD)。
          • UEFI Firmware Files
              UEFI Firmware Files是最小/少的模組化的code,包含了Code及Data存放在FV中。每一個UEFI Firmware File都有Name、Type、Alignment及Size等四個attribute。 UEFI build tool會建立Firmware Files。Firmware Files的組成如下圖:
                其中,entry point包含在Data區塊裡頭。
            • Firmware File System
                Firmware File System(FFS)描述FV的file及free space的資訊。每一個FFS都有一個unique的GUID來連結FV。FFS參考FAT 32的作法,他的header如下圖。
                  同時,我們也利用UEFI Build tool建立FFS。
              • Firmware Volumes
                  一個Firmware Volumes對應著一個logical firmware device。FV是由FFS來組成的,Firmware file則是FV組成的元件。FV可以表示flash的一部分或是多個flash或甚至一個partition或是network。所有PI component都存放在FV,在PI的過程中,必須透過FFS去讀取。
                • Firmware Devices
                    Firmware Device是指非揮發性的Storage。包含了Firmware Code、Firmware Data及Fault Tolerant。
                      Firmware Device包含了FV Main放置了DXE Driver,FV Recovery放置了security及PEI code。我們以Recovery FV為例作解釋。Recovery FV包含了FFS放置著Boot Block Code(包含了PEI security phase code) 及Recovery code(包含了也許USB stack來讀取USB device)。
                  • Creating UEFI Firmware Files
                      我們如何產生UEFI Image呢?
                      1. 撰寫C code
                      2. 用build tool編譯產生Library及object file
                      3. 產生的Library及object file是intermediate file,利用微軟的compiler把他們轉成PE/COFF格式的image。
                      4. 如果是在Linux的環境,我們可以使用GCC來取代。
                      5. Build Tool會將標準的header置換成UEFI header。
                      在PEI階段,因為我們是run在rom裡面,因此我們希望Image越小越好。所以我們是製作成Terse Image。它簡化了UEFI header的項目如下圖。

                  • Physical Memory Map
                      從下圖我們可以看到各個層級之間的關係。Firmware Device被load進system memory之後,它包含了firmware volume。而firmware volume又包含了許多Firmware File System,Firmware File System又放置著許多Firmware File。

              • UEFI/PI (6) UEFI Drivers



              • UEFI Drivers and Overview
                  1. Driver's Location
                      UEFI Driver run在DXE Phase中,在platform 初始化的過程中可能重複的被active。
                       
                      同時,UEFI Driver是green H的其中一部份,如下圖所示。 


                  2. UEFI Driver's Attributes
                      UEFI Driver是system driven的image。在DXE Phase中由UEFI Loader到系統中。UEFI Driver能提供protocols同時也可能使用其他Driver提供的protocol。我們可以使用UEFI Driver去支援特定硬體或override 已經存在的Driver。
                      1. Supportive
                          UEFI Driver支援複雜的bus hierachies。UEFI Driver可以與bus interface溝通來將device連接到bus。
                      2. Independent
                          UEFI Driver可以存放在任意的storage 中 包含flash。
                      3. Flexible
                          其中一個 UEFI Driver會建立UEFI Driver Binding Protocol.這一個protocol是UEFI定義的protocol用來將Driver與device做配對。同時也支援version info、hot-plug及unload的功能。
                        • Extensible
                            UEFI Driver被設計成可以支援未知的bus或device的種類。
                    • UEFI Driver's Functions

                        1. UEFI Driver是firmware的延伸
                            可以支援新的硬體,與HW、OS無關。
                        2. Portability
                            因為與Platform Arch.無關,因此可以跨平台。
                        3. UEFI SPEC.提供許多API
                            因此可以加速開發。
                    • UEFI Driver's Contents
                        UEFI Driver包含了四大部分,
                        1.會有一個Entry Point作為Driver的進入點。
                        2.會提供Published Function 供其他的Driver使用。
                        3.Consumed Function,參考別的Driver提供出來的功能。
                        4.Data Structure,用來滿足Driver所需要的資料存放。 

                    • UEFI Driver's Entry Point
                        如果前面所提到的,DXE Dispatcher會Load Driver,UEFI Driver透過UEFI Loader將Driver Load到記憶體中。Loader 會先進入Driver的Entry Point,接著Driver會建立Published Protocol。以下圖為例,他提供了Binding Protocol( supported, Start, Stop),最後離開。

                    • Drivers v.s. Applications
                        UEFI Application 與 UEFI Driver本質上非常的類似,下表列出他們的比較。 



                • UEFI Protocols
                    1. UEFI Protocols
                        一個UEFI protocol定義在SPEC中,可能是一塊function pointer、data structure或是API。 下面分成三個部份來解釋。
                        1. Confused with Drivers
                            UEFI Driver是一個可執行的UEFI Image。它包含了許多的protocol而每一個protcol也包含了多個handle。因此,Protocl是Driver建立的。
                            我們可以把UEFI protocl想像成interface。它包含了許多function pointer, data structure或APIs。
                        2. Produced by Driver
                            UEFI Driver可以建立許多protocol。
                        3. Consumed by Anyone
                            UEFI protocol可能被任一的Driver使用。例如UEFI platform Driver可能在其他的Driver啟動時使用。
                    2. Example A: EFI_PCI_IO_PROTOCOL
                        下面的例子是PCI I/O Protocol。這一個Driver run在UEFI boot services/environment來存取memory及PCI controler的I/O。另外,與PCI相關的SPEC也定義在此protocol中。這一個Protocol的目的是要將對PCI device的讀寫抽象化。EFI_PCI_IO_PROTOCOL抽象化了對PCI 裝置的memory,I/O, PCI configuration及DMA interface的操作。每一個PCI Bus的PCI control都有對應的一個EFI_PCI_IO_PROTOCOL instance。對操作PCI裝置的Driver都必須透過對應的instance來操作。PCI controler的handle至少會有EFI_PATH_PROTOCOL及EFI_PCI_IO_PROTOCOL的instance。

                    3. Example B
                        EFI_DISK_IO_PROTOCOL是對block device存取抽象化。File System等等的code都需要依賴這個protocol。

                    4. Example C
                        這個protocl的解釋如下:UEFI Image may use the device path to match its own device Drivers to the particular device. Note that the executing UEFI OS loader and UEFI application images must access all physical devices via Boot Services device handles until ExitBootServices() is successfully called.



                • Driver Design
                    1. Design Process Steps

                    2. Driver Types
                        在撰寫Driver之前,必須先知道我們要寫的是哪一種Driver。在UEFI Image中可以分成兩種,Driver及Application。
                        UEFI Applications中有一種特殊的application叫做OS Loader。與一般的Application不同的是OS Loader會呼叫 ExitBootService然後就將control pass到OS kernel了。
                        接著我們來了解Driver中的幾種類型。
                        1. Service Driver
                            a. 不管理hardware。 
                            b.提供service給其他Driver。 
                            c.不支援Driver binding protocol。 
                            d. 在entry point裡install protocol。  
                            e. 建立一個或多個 service handlers。 
                            f. 產生service-specific protocols。 
                            例如: UEFI Decompress Protocol、UEFI Byte Code Virtual Machine、Boot Integrity Service(BIS)。
                        2. Initialization Drivers
                            a. 與hardware會有溝通。 
                            b. one-time initialization。 
                            c. 不會建立handle及protocol。 
                            d. 結束後就會unload。
                        3. Root Bridge Driver
                            a. 管理部分的core chipset。 
                            b. 直接與HW溝通。 
                            c. 建立一個或多個 root bridge handle。 
                            d. 建立 root bridge I/O protocols,安裝在新的root bridge handle。 例如:PCI Host Bridge。
                        4. Bus Driver
                            他是UEFI Driver Model的Driver。用來管理Bus controller。
                            start()會建立一個或多個child handles及Bus Specific I/O protocols。例如:PCI NIC card、UART controllers。
                        5. Device Driver
                            管理controller或peripheral device。
                            start()不會建立child handle但會建立一個或多個protocols。
                            例如:PCI Video Adapter、USB Host Controller、USB keyboard/Mice。
                        6. Hybrid Driver
                            結合Bus Driver及device Driver。
                            例如:PCI SCSI Host Controller、PCI Fiber Channel Controller。
                    3. Consumed Protocols
                        什麼時候會使用那些Protocl呢?例如 PCI Adapter需要PCI I/O Protocol或加上也許Device Path protocol。 而像USB keyboard/mice, DVD rom這類的裝置就需要USB I/O protocol及device path protocol。
                    4. Produces Protocols
                        那我們可能會產生什麼protocol呢?例如,假設是在寫keyboard Driver,我們可能會建立simple input protocol;滑鼠可能會有simple pointer protocol;USB flash disk可能會有block I/O protocol。Depends on 你寫的裝置。



                • Writing Drivers
                    1. Writing UEFI Drivers
                        接下來,我們寫一個Driver需要那些protocol呢?參考下表:

                    2. Initialized
                        當UEFI Driver被dispatch時,首先會進入entry point然後初始化。在初始化的過程中會宣告此Driver會提供那些protocol。UEFI Driver 是relocatable pickup image,所以可以load在記憶體的任意位置。在Driver initialize的過程中是不會touch HW的,在過程中會呼叫Driver binding protocol,在初始化後,service就被註冊了,這也是會什麼可以快速開機的原因。
                    3. Supported
                        在初始化後,Binding Protocol會開始define Supported、Start及Stop function。
                        接下來以PCI Driver為例。 首先Open PCI Protocol( EFI_PCI_IO_PROTOCOL),然後check這個Driver是否支援這個controller( EFI_DEVICE_PATH_PROTOCOL)再來關閉PCI Protcol並return 是否支援。


                    4. Start
                        Start()會產生EFI_Block_IO_Protocol 建立child protocol(functions)。

                    5. Stop
                        Stop不會產生任何的Protocol,反而他會移除Start()所產生的Protocol。

                    6. Recommended Protocols


                • Tips and Techniques

                    1. Driver Guideline
                        主要有四個原則
                        1. 在Driver entry的地方不要touch HW
                        2. 在Support()保持簡單。
                        3. Start()對應Stop();Driver Entry對應Unload
                        4. 把複雜的事情放到Start()和Stop()去做。
                    2. Design Checklist

                    3. Recommendations
                        在實作Test/Debug的時候有幾點注意的事情如下:

                    4. Start() Code
                        這個範例是儲存PCI的Attributes。

                    5. Stop() Code
                        將Attribute reset回原本的值。

                    6. Library Functions
                        我們應該多利用既有的function來將code size降低,如下:

                    7. Other Helpful Suggestions
                        這裡分成兩大塊。
                        Reducing Option ROM Size
                        1. 使用UEFI支援的Compression來降低ROM Size。
                        2. Compile with EFI Byte Code Compiler(EBC)

                        Improving Protability
                        1. 不要假設max number of children。
                        2. 不要寫死memory address或使用assembly。
                        3. 不要使用floating point arithmetic
                        4. Dome minor ebc point considerations
                        5. Bus Driver應該支援一次產生一個child。(可以加速開機)