2012年5月25日 星期五

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。(可以加速開機)
    • 2012年5月23日 星期三

      UEFI/PI (5) Driver Execution Environment





    • DXE Overview
        1. DXE Overview
            Driver Execution Enviroment (DXE)是 PI SPEC.裡的第二個phase,在這個phase中有許多的東西被啟動或初始化。同時,EFI services、protocols及driver都在這個時候被implement或support。DXE也建立了許多system table。
          • Importance of DXE
              Without DXE
              1. 每個人的coding style 不同,同時,每家code base也可能不一樣。因此,BIOS的feature的實作方式也會因為vendor不同而有所差異,這造成了移植的困難。
              2. 一個單一的source file控制整個啟動流程,造成開發新的feature或更改上的困難。
              With DXE
              1. DXE參考OS的做法,driver及library都定義得很清楚,因此也很容易實作模組化的 driver。
          • DXE Foundation's Function
              DXE Foundation是DXE Phase的核心,他有許多的functions可以使用。下面分成四個部分來介紹DXE Foundation。
                
              1. Initialize Platform
                  DXE Foundation initial Chipset及platform。 其中一個function會load driver來建構環境,最後boot manager 及OS
              2. Dispatch DXE
                  DXE foundation會先dispatch DXE driver,他會處理相關的相依問題。
              3. Dispatch UEFI
                  在dispatch DXE driver後,DXE foundation會去dispatch UEFI driver,而UEFI driver是沒有相依問題的。
              4. Load Boot Manager
                  每一個driver在entry point的地方都必須註冊與那些protocol相依,因此Load Boot Manager可以依此做initial 的排序。最後會將control交給下一個phase - BDS。
          • DXE Foundation Properties
              DXE Foundation有許多的特性,以下一一介紹。
              1. HOB List Dependent
                  上一個phase PEI會將所有的hardware, reosurce的 state放到HOB傳給DXE,因此,DXE無須知道hard-coded address
              2. No Hardware Specifics
                  DXE drivers必須透過Architecture Protocols(APs)來與硬體溝通。因此不可以假定現在使用的是哪個硬體然後去使用它特定的東西,例如address。
              3. No Hard-Code Address
                  因為沒有hard-coded的address,在system memory任何地方都可以load DXE foundation。
          • DXE Components
              DXE 同樣有許多的component,以下一一介紹。
              1. Drivers
                  負責初始化Processor、Chipset及Platform。而DXE Driver 更是負責建構APs。
              2. Foundation
                  負責Dispatch drivers、建立Boot services、Runtime Services及DXE Services。
              3. Architectural Protocols(APs)
                  因為沒有hard-coded的address,在system memory任何地方都可以load DXE foundation。
              4. EFI System Table
                  EFI system table存放了指標指向包含了UEFI Service tables、 Configuration tables、 Handle databases及console devices
              5. Dispatcher
                  DXE Dispatcher會依照相依以正確的順序啟動 driver。
          • DXE Phase Flow
              DXE的執行階段可以分成幾個步驟:
              1. DXE Foundation Initial Services,包含UEFI Service及DXE Service。
              2. DXE Foundation Dispatch DXE drivers。
              3. DXE Dispatcher 搜尋FV裡面是否有priori file,依照順序將driver load到memory。
              4. 接著尋找FV裡剩下的Driver並Load進memory。




      • Data Structures and Events
          1. Data Structures

          2. Events
              因為Event是與CPU architecture不相關的,因此UEFI使用event來作為object、protocol之間的訊號。 解釋下圖,主要可以分成Singnal events及wait events。
               
              1. Exit Boot Service Events
                  是當呼叫ExitBootService()的時候從wait event轉回signaled state。
              2. Set Virtual Address Map Events
                  SetVirtualAddressState()
              3. Periodic Timer Events
                  是週期性觸發的event
              4. One Shot Timer Events
                  可以指定時間觸發的timer event
              5. Wait Event
            • EFI System Table





        • DXE Foundation
            1. DXE Foundation Code Flow
                DXE Foundation有兩個attributes: Single Threaded Environment and One Interrupt
                1. Single Threaded Environment
                    a. 在DXE Foundation的code只會有Boot Strap Processor(BSP)會執行。 b. 其他的application processor都進入 wait mode。
                2. One Interrupt
                    a. DXE foundation只使用timer tick作為software的interrupt。 b. 因為只使用timer iterrupt,因此所有的devices都會被pulled c. DXE foundation 會使用event取代multiple interrupts。
            2. DXE Main
              • DXE Main Source Code






          • Architecture Protocols
              1. APs Defined
                  DXE藉由DXE Drivers 會產生 Architectural Protocols(APs)抽象化硬體的溝通,以下以三個部份來介紹。
                  1. Function
                      可以把AP's 想像成脫離platform-specific hardware的wrapper function。舉例來說,CPU AP 管理interrupt、取得processor info、取得processor-based的timer。
                  2. Support
                      AP's 是low-level的protocols用來支援啟動以及runtime services。我們可以利用higher-level的platform function來使用AP's提供的功能。
                  3. Dependency
                      有些AP可能會與其他的AP相依,舉例來說,whatchdog 需要IO及timer的access。有三種方式可以解決相依的問題:a. 利用Dependency Grammar來load DXE b. 使用RegistryProtocolNotify()來通知AP被load進去了。 c. 使用Priorl List將預先知道的AP 依照相依順序排好讓dispatcher按照這個順序dispatch。
              2. APs' Role
                  ,藍色的在os runtime會被free掉,灰色則可以繼續使用
              3. APs' Location






          • DXE Dispatcher
              1. DXE Dispatcher
                  DXE Dispatcher 負責load和dispatch FV(Firmware Volume)裡的 DXE及UEFI driver。 DXE Dispatcher主要有幾個目標如下:
                  1. Driver可能是由不同的組織、部門所撰寫。因此Dispatcher必須能處理DXE Driver 之間的dispatch 順序
                  2. DXE Dispatcher支援例如emergency patches。另外,DXE Dispatcher也讓開發人員更容易整合自己開發的driver。
              2. DXE Dispatcher Source Code
                • DXE Dispatcher State Machine
                  • DXE State Machine Example




              3. DXE Drivers
                  1. DXE Driver Type
                      DXE drivers包含了device或service code執行在UEFI driver之前。如同之前所提到的,DXE 階段的driver分成兩種,即DXE Driver和UEFI Driver。下表比較了兩個的不同。 
                    • BDS Driver
                        在DXE階段最後一個driver是BDS( Boot Device Selection) Driver。BDS driver負責建立console( keyboard, video)及執行UEFI Boot Option。 下圖是啟動BDS的示意圖。額外說明的是,因為當Dispatcher load BDS的時候,會先進去她的entry point讀取相依的APs,因此假設仍有未完成的APs則可能回到DXE Dispatcher去load其他的driver。 




                • SMM
                    System Management Mode(SMM)他是CPU的一個模式,當我們觸發CPU的SMI Pin的時候就會進入SMM Mode。 SMM模式下的執行的程序被稱作SMM處理程序,所有的SMM處理程序只能在稱作系統管理內存(System Management RAM,SMRAM)的空間內運行。 
                    1. SMM Service
                        SMM service是高優先權的system management interrupt(SMI),在runtime的時候仍然可以接管系統。下面分成三個特性及兩個service特點來介紹。 Characteristics
                        1. 在SMI的時候,CPU執行pre-defined starting vector。
                        2. SMM的code放在SMRAM中,在SMM初始化後會lock起來。
                        3. SMI是由hardware event或 system interrupt所產生的。它可以被偵測、清除或disable。
                        Services
                        1. SMM service是一個handlers的list。並且都是DXE foundation service的subset。
                        2. SMM services和DXE foundation services提供同樣的functionality但不同的是SMM locate在SMRAM中。
                        3. SMI是由hardware event或 system interrupt所產生的。它可以被偵測、清除或disable。
                • 2012年5月22日 星期二

                  UEFI/PI (4) Pre-EFI Phase

                • PEI Overview
                    Pre-EFI Initialization (PEI) 是Platform Initialization的第二個Phase定義在Platform Initialization Specification, Ver 1.2.1, Volume 1。 
                    所有的machine restart event都會invoke PEI Phase。PEI執行的階段只有on-processor的資源可以使用, 例如以processor cache當作call stack然後來執行Pre-EFI Initialization(PEIM)。PEI主要可以分成6個任務如下:
                    1. Reset
                        PEI consumes Reset, INIT 和 Machine Check Architecture( MCA)。以Itaium來說,reset會call Processor abstraction layer(PAL) 然後call進 firmware。
                    2. Start-up
                        PEI是在rom裡面執行的,因此有非常的小的start-up code。Modular的driver都是absolutly address的。
                    3. Support
                        為了要提供DXE phase以C的環境執行,PEI必須建立暫時的memory以供C使用stack。
                    4. Modules
                        PEI core locate、validates和dispatch 執行PEI modules(PEIM),這些module是用來初始化platform的feature或chipset。
                    5. Publish
                        PEI藉由PEIM to PEIM Interface (PPI)來 溝通。
                    6. Goals
                        PEI主要的目的是Discover boot mode,Launch modules that initialize main memory Discovery & launch DXE core。

                    而上面提到的PEIM負責了主要四個項目:
                    1. 初始化永久記憶體。
                    2. 在Hand-Off Blocks中寫入memory的資訊。
                    3. 在Hand-Off Blocks中 描述firmware volume的location。
                    4. 將control 轉移給DXE Phase。

                    下圖說明了PEI Phase的操作流程,當進入PEI之後,首先會 初始化PEIM的dispatcher,接著執行各個PEIM直到最後一個PEIM存在DXE IPL將control及HOBs 轉移給DXE Phase。
                     
                    HOBs是唯一pass給DXE Phase的資料結構。由於 PEI負責了recovery及S3 resume,PEI Phase必須要越小越好,複雜的運算或演算法應該放到DXE階段執行(這樣開機才會快)。 
                    為什麼我們需要PEI呢?原因是:
                    1. 寫不使用memory的程式是非常困難的。 
                    2. Porting的困難。以assembly來說,某部分的code vendorA使用EBP另外一個vendor 使用EBX,修改起來會比C來的費力。
                    3. 在開發一個feature的時候,我們基本上都會希望可以使用memory以及有基本的chipset被初始化。並且,PEI也負責了S3 (resume )的部分。 
                    下面我們將深入的介紹PEI Phase。
                • PEI Foundation
                  • PEI Foundation Introduction
                      PEI Foundation 是PEI的entity負責了主要四個項目:
                      1. Dispatch PEIMs
                      2. 維護boot mode
                      3. 初始化永久記憶體
                      4. Invoke DXE loader
                      PEI Foundation 包含了SEC 和 Pre-EFI( PEI)被設計成一個很小的一個片段,在SEC結束後,PEI最開始的code是一段platform-specific的machine code, 這也是porting會遭遇的困難。因此,這也是為什麼要讓PEI foundation的code越小越好(事情盡量以C來做,比較好移植)。
                  • PEI Prerequisites
                      在進入PEI Phase之前要滿足兩個條件:
                      1. Processor execution mode。
                      2. 可以access 存在PEI Foundation的Boot Firmware Volume(BFV)。
                      SEC將control交出的對象就是PEI Foundation。而放置PEI Foundation的Firmware Volume(FV)就稱為Boot Firmware Volume。PEIM可能會放在一般FV或是BFV,但是有些特殊的PEIM必須要放在BFV來提供其他PEIM的location。
                  • PEI Foundation Entry Point
                      SEC call進PEI Foundation時包含了下列資訊:
                      1. A set of PPIs
                      2. Size and location of the the Boot Firmware Volume (BFV)
                      3. Size and location of the temporary RAM
                      4. Size and location of the temporary RAM available for use by the PEI Foundation
                      5. Size and location of the stack
                      在SPEC裡面是強制規定SEC一定要將這些資訊放到stack中來invoke PEI Foundation。 
                  • PEI Calling Convention Processor Binding
                      下面將簡述 processor-specific mechanisms 去取得指向PEI Service Table的指標。(EFI_PEI_SERVICES**)
                    • X86
                        以x86而言, EFI_PEI_SERVICES** 放在 4 bytes immediately preceding the Interrupt Descriptor Table,取得的方法如下。
                        IDTR32          STRUCT
                        Limit           DW 1 DUP (?)
                        BaseAddress     DD 1 DUP (?)
                        IDTR32          ENDS
                        sub       esp, SIZEOF IDTR32
                        sidt      FWORD PTR ss:[esp]
                        mov       eax, [esp].IDTR32.BaseAddress
                        mov       eax, DWORD PTR [eax – 4]
                        add       esp, SIZEOF IDTR32
                        
                    • X64
                        x64的系統則是放在8 bytes immediately preceding the Interrupt Descriptor Table,取得的方法如下。
                        IDTR64          STRUCT
                        Limit           DW 1 DUP (?)
                        BaseAddress     DQ 1 DUP (?)
                        IDTR64          ENDS
                        sub       rsp, SIZEOF IDTR64
                        sidt      [rsp]
                        mov       rax, [rsp].IDTR64.BaseAddress
                        mov       rax, QWORD PTR [rax – 8]
                        add       rsp, SIZEOF IDTR64
                    • ARM
                        如果是ARM Processor Family processors的話,EFI_PEI_SERVICES** 是放在 TPIDRURW read/write Software Thread ID register defined in the ARMv7-A Architectural Reference Manual.
                        CpuReadTPIDRURW:
                            MRC p15, 0, r0, c13, c0, 2
                            bx lr
                        EFI_PEI_SERVICES ** 
                        GetPeiServicesTablePointer (
                          VOID
                           )
                        {
                          return (EFI_PEI_SERVICES **)(UINTN)CpuReadTPIDRURW ();
                        }
                        
                • Memory
                    PEI core需要一段暫時的memory,大小會depends on CPU和chipset,以IA32為例就是8K了。IA32使用 Cache As Ram(CAR)的技術來提供暫用的memory。方法是將cache設定成no eviction mode。 下圖是PEI initial的memory map。主要分成幾個部分:
                    1. BFV
                        BFV全名是Boot Firmware Volume,BFV是存放PEI core的地方,同時也是recovery block。
                    2. FV
                        FV全名是Firmware Volume,定義在 Firmware Storage, vol.3。FV有可能是0到多個。
                    3. T-RAM
                        T-RAM就是temporary memory。在初始化memory 之前存放stack, data的地方。
                • PEI Core
                    PEI core 負責dispatching PEIMs 及提供基本的services 如下圖 PEI core 的主要function如下:
                    1. *SecCoreData 存放著例如T-RAM的大小及位置、stack的地方和BFV的地方。
                    2. *PpiList 記錄著要由PEI core initial的PPI description的list。如果這個list是空的則會存放一個結束的tag:EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
                    3. *Data 則是指向舊的PEI core,如果是NULL則代表第一次進入。

                    下圖說明了在系統reset或power-on之後到準備進入DXE的流程
                • PEI Service
                    PEI Foundation會建立一個所有PEIM都可以看到的system table叫PEI Service Table 。 PEI Service有可能被定義成 function、command 或capability manifested。 也因為PEI階段直到最後面才會有memory可以使用,因此相對於後面phase的service,PEI service可以做的事情就相對比較少了。 
                    在build time的時候,PEI Foundation的位置和建立的temporary ram是不可知的,因此指向PEI 的pointer會傳進每一個PEIM的entry point 及PEIM-to-PEIM Interface (PPI)。
                     PEI Foundation提供了下列七種service。
                    1. PPI Service
                        PEIM to PEIM Interface是用來讓PEIM之間做溝通,這個interface存放在T-RAM中。PPI service提供了四種function: InstallPpi()、ReinstallPpi()、LocatePpi() 、NotifyPpi()
                    2. Boot Mode Service
                        管理系統的boot mode( S3, S5, normal boot, diagnostics, etc.)。
                    3. HOB Service
                        Hand-Off Blocks的簡稱,用來將資料傳到下一個phase(DXE)
                    4. Firmware Volume Service
                        在Firmware File System (FFS)中找尋PEIMs及其他的firmware files。 FfsFindNextVolume() 、FfsFindNextFile()、FfsFindSectionData()
                    5. PEI Memory Service
                        管理permanent memory在被discovered之前/後的memory操作。InstallPeiMemory()、AllocatePages()、AllocatePool()、CopyMem()、SetMem()
                    6. Status Code Service
                        提供common progress/error code 的reporting 服務。一般來說是for debug用的。
                    7. Reset Service
                        Initiate warm or cold restart of the system
                • PEI Modules(PEIMs)
                  • PEI Modules 
                      PEIM是一個unit 的code and/or data用來初始化平台、processor。他抽象化了domain-specific logic相似於DXE Driver。 一個platform所擁有的PEIMs可能包含了以下幾種:
                      1. Platform-specific PEIMs
                      2. Processor-specific PEIMs
                      3. Chipset-specific PEIMs
                      4. PEI CIS–prescribed architectural PEIMs
                      5. Miscellaneous PEIMs

                      下表列出了PEIM的幾個特性

                  • PEIM Structure
                      每一個PEIM包存在一個檔案中,包含了:
                      1. Standard header
                      2. Execute-in-place code/data section
                      3. Optional relocation information
                      4. Authentication information, if present
                      PEIM binary image 可以從存放的FV執行或是在永久記憶體被初始化後shadow過去的compressed component中執行。 PEIM可執行的section可能是position-dependent 或 position-independent code. 如果是position-dependent code, relocation information must be provided in the PEIM image to allow FV store software to relocate the image to a different location than it is compiled.  下圖是PEIM的layout,有些是必要的有些則是optional的。 PEIM binary可以是XIP(execute in place)(沒有壓縮的)或是在memary初始化後copy到ram執行(壓縮的binary)。這類的position dependent code 因為base address及entry point已經改變了,因此必須作相對應的修改。
                • PPI Interface
                    PEIM使用 PEIM to PEIM Interface(PPI)來與彼此溝通,而PEIM執行的過程中也有可能會去invoke其他的PEIM靠的就是PPI。PPI包含在EFI_PEI_PPI_DESCRIPTOR 中。
                    要使用PPI必須要透過LocatePpi()來查詢。 要提供PPI則使用InstallPpi()來讓別人使用。我們藉由PPI database來access PPI,這個database 包含了所有的PPI。如同剛剛提到的,我們可以藉由LocatePpi(), NotifyPpi(), 及ReinstallPpi()來access這個 database。
                     PPI有兩種,分別是Architecture PPI Additional PPI
                    1. Architecture PPI的GUID是global的。這類的PPI提供給PEI foundation作為common interface來使用。 而這類的 PPI也會根據不同的platform來實作,例如ReportStatusCode()。
                    2. Additional PPI相較於 Architecture PPI 只會被PEI Foundation使用而不是給其他的PEIMs使用, Additional PPI 定義了兩種PPI可以給其他PEIMs使用。
                      1. Required PPIs
                          CPU I/O PPI 、PCI Configuration PPI 、 Stall PPI、 PEI Variable Services
                      2. Optional PPIs
                          Security (SEC) Platform Information PPI
                • PEI Dispatcher
                    PEIM Dispatcher是一個state machine實作在PEI Foundation裡。他的工作是將control依序地交給PEIM。PEI Dispatcher會檢查Firmware Volume中檔案型態
                    EFI_FV_FILETYPE_PEIMEFI_FV_FILETYPE_COMBINED_PEIM_DRIVER依照他的相依性或參考priori file(optional的file,事先定義好PEIM的順序)來決定何時dispatch 這個PEIM。
                • PEI HOBs and Memory
                  • HOBs
                      HOB是一連串的data structure在PEI階段所建立的。HOB描述platform的feature、設定或資料。在DXE phase,HOB是read only的。以下分開介紹幾個HOB的角色。
                      1. Bridge HOB是PEI跟DXE的溝通橋樑。
                      2. Self-Discribing HOB定義在PI的SPEC.也定義了他的attribute及length.
                      3. Allocated HOB是alloct在block的heap, 是一塊連續的記憶體。
                      4. Snapshot HOB裡面指向的PEIM定義的physical的值例如FVs, Physical memory properties在DXE是不可以更改的。
                      5. Memory PEI建立HOB並存在system memory供DXE使用。
                  • Hand-Off Block (HOB) List
                      在PEI中,DXE IPL PPI會將HOB list pass給DXE Foundation。而這個list必須要至少包含以下7種HOB。
                      1. PEI Hand-off Information Table(PHIT):指向HOB List
                      2. 一個或多個描述physical system memory的Resource Descriptor HOB(s)
                      3. Boot-Strap Processor (BSP)stack HOB:告訴DXE現在的stack location
                      4. BSPStore(Backing Store Pointer Store) HOB: Itanium only
                      5. 一個或多個描述firmware devices的Resource Descriptor HOB(s)
                      6. 一個或多個Firmware Volume HOB(s)
                      7. Memory Allocation Module HOB:DXE會將他放到GCD
                  • Pre-permanent Memory Environment
                      下面分幾個部分介紹PEI Pre-permanent Memory Environment:
                      1. Purpose: 初始化 system memory
                      2. Discovery: Discovery boot type。例如resuming from state, recovery, or normal boot
                      3. Environment: 到這個階段還沒有system memory可以用。因此使用CPU的cache來放置data及stack,模擬出C可以執行的環境。
                      4. Model: Run在32 bit的protected mode
                      5. Input: aware of the location of the firmware volumes and the PEI service table
                  • Post-permanent Memory Environment
                      下面一樣分幾個部分介紹PEI Post-permanent Memory Environment:
                      1. Purpose: Transition 到DXE, 準備HOBs
                      2. Discovery: 擁有stack及HOB list
                      3. Environment: 擁有system memory, XIP from firmware volume
                      4. Model: Run在32 bit的protected mode
                      5. Input: 建立指向第一個HOB的pointer, 也就是PHIT(PEI Hand-Off Information Table)
                  • PEI Memory Map Sample
                      下圖是PEI Memory Map的範例,也就是"可能"的長相。

                      首先,在PEI過程中,我們可能會populate HOBs, 同時,PHIT會指向第一個HOB。PHIT也會記錄著PeiMemoryBottom, PeiFreeMemoryBottom, PeiFreeMemoryTop, PeiMemoryTop。PeiMemoryTop跟PeiFreeMemoryTop之間是fixed memory,也就是DXE不可修改的位置。PeiFreeMemory是供DXE去使用的memory space。
                • Transition To DXE
                  • PEI Transition To DXE
                      總結一下PEI從啟動到移轉給DXE的過程
                      1. 一開始的PEI phase是沒有system memory可以使用的。
                      2. PEI core dispatch PEIMs,在這個階段初始化CPU, Chipset等等裝置並將結果記錄在HOB List中
                      3. 在DXE Initial Program Load(IPL) PEIM被執行的時候,HOBs List就存在了
                      4. DXE IPL將 control傳給DXE core。當傳遞完成後,所有的PEI phase的services及PPI將無法再access。唯一傳遞給DXE的只有HOB list
                  • DXE Initial Program Load(IPL)
                      IPL有很多目的如下:
                      1. 禁止所有的hard coded的address
                      2. 尋找最大的physical memory HOB,一般來說置於memory的top
                      3. 將stack allocate到memory的top
                      4. 尋找HOB LIST的firmware volume給DXE core
                      5. 將DXE core load到memory
                      6. switch stack(從T-RAM轉到system memory)然後轉移到DXE
                  • Sample Code
                    • Call to DXE IPL
                    • PEI Transition
                  • Alternative Boot Path
                    • Alternative Boot Path
                        事實上,PEI並非每次開機都會跳到DXE。PEI有可能根據boot mode的不同改變boot path。PEIM可以使用SetBootMode()來改變boot mode。 
                • 2012年5月21日 星期一

                  UEFI/PI (3) Security(SEC) Phase



                • SEC Phase 簡介
                    SEC是reset 或 power-on 後 PI ( Platform Initialization)的第一個phase定義在Platform Initialization Specification, Ver. 1.2.1, Volume 1, Chapter 13。SEC必須確保firmware的 "完整"。 SEC他是相依於platform及CPU的,也就是說必須針對不同的CPU或平台來做移植。另外,SEC大部分的實作都是在assembly下的,而且是不可以壓縮的。
                • SEC Phase 的責任
                    SEC有四個主要的任務分別如下:
                    1. Restart SEC必須要處理所有的platform restart event,包含開機、重開機或是其他異常的重啟。
                    2. Memory Sotre SEC必須要建立一塊臨時的memory在系統初始化前使用。使用例如CAR( Cache as Ram)或SRAM的技術。
                    3. Root of Trustestart SEC從power on 開始要尋找和驗證PEI的最初步驟。目的是要保證Processor最開始的code是可以信賴的。
                    4. Passing 傳送Handoff訊息和把control給PEI Fondation。傳送的訊息包含了a. 平台狀態、b. BFV(Boot Firmware Volume)位置及大小、c. temporary RAM的位置大小等等。

                      SEC透過EFI_PEI_STARTUP_DESCRIPTOR將上述Passing的資料pass給PEI。EFI_PEI_STARTUP_DESCRIPTOR的資料結構是長這樣子的:
                      typedef struct {
                          UINTN                   BootFirmwareVolume;
                          UINTN                   SizeOfCacheAsRam;
                          EFI_PEI_PPI_DESCRIPTOR  *DispatchTable;
                      } EFI_PEI_STARTUP_DESCRIPTOR;
                  • SEC Platform Information PPI
                      在上面我們有提到SEC利用(強制使用)EFI_PEI_STARTUP_DESCRIPTOR這個資料結構將Handoff德資訊pass給PEI。另外,我們也可以pass"額外"(optional)的PPI EFI_SEC_PLATFORM_INFORMATION_PPI給PEI。這個PPI 抽象化了PEI Fondation所需要用來discover dispatching PEIM的起始位置的platform-specific資訊。這個PPI也可以存在EFI_PEI_STARTUP_DESCRIPTOR這個資料結構的最後一個參數裡(*DispatchTable)。
                  • Health Flag Bit Format
                    • Health Flag Bit Format
                      • SEC_PLATFORM_INFORMATION_PPI.PlatformInformation()定義了PFI_HEALTH_FLAGS存放由microcode、hardware或是Itanium才有的PAL 產生的CPU status。Health Flag的bit format如下圖:

                         

                        下圖則是每一個bit的說明。

                    • Self-Test State Parameter
                        Self-test state定義的參數for IA-32 Intel® processors 和 Intel® Itanium® processor family 是一樣的。某些 bit可能沒辦法直接對應到IA-32的CPU,這時候讀到的值就會是NULL。下圖說明了每一個bit 的意義。

                        如果Status顯示functionally restricted,我們可以從vm,ia,fp得到failure的訊息。下面列出導致functionally restricted的情況:
                        1. Processor 或 PAL偵測到且獨立出錯誤的component,所以不會被使用。
                        2. Processor必須至少要有一個可以用的memory unit、ALU、shifter及branch unit。
                        3. Floating-point may be disable。
                        4. For Itanium,RSE(Register Stack Engine)is  not required to work,但register renaming logic必須要能正常work。
                        5. Processor-controlled caches和register files之間的path在測試的過程中必須要能work。
                        6. 讀取firmware address space必須要能正常work。

                  • Processor-Specific Detail
                      下面以IA-32為例,解釋SEC Phase在IA-32架構下的運作狀況。
                      1. Locating PEI Foundation。
                      2. 使用 architecture define的Handoff state把control交給PEI。
                      3. 初始化processor-controlled memory resource例如processor data cache。
                  • 參考資料:VOLUME 1: Platform Initialization Specification Pre-EFI Initialization Core Interface Version 1.2.1

                    UEFI/PI (2) UEFI and Platform Initialization(PI)

                    • Background

                    • 前一篇說明了UEFI的大概,也提到了Tiano這個OpenSource Project. 這一篇將簡介UEFI的PI。
                      過去Intel發展了 The Intel Platform Innovation framwork for UEFI或是"The Framework" 是一個符合UEFI規範的一個firmware實作。這一個幾乎以C來實作的framework支援了大部分的Intel CPU family。

                      而目前,這個framework已經被更全面支援的UEFI Platform Initialization (PI)所取代了。UEFI和PI有兩個主要不同的點。
                      1.  UEFI定義了OS, add-in driver和system firmware之間的Interface。(下圖藍色部分)
                      2.  PI則定義了偏向Implementation的部分 e.g. 從 power on 到移交control給OS之間的所有操作。 (下圖綠色部分)
                       
                      PI負責從開機到UEFI可以work之間的流程,舉例來說,UEFI是負責跟OS做溝通,然而,UEFI本身並不處理memory initialization、recovery或platform initialization等等跟platform有關的事情。這些都是由PI做掉的。
                        另外,UEFI跟PI的SPEC都是UEFI Fourm所制定的。 
                      • PI 簡介
                      • 如下圖,PI分成六個部分,
                        從開機的過程來看,順序是由左到右。下面一一解釋各個流程在做什麼。
                        1. SEC
                        2. SEC是Security的簡稱,這一個phase是開機後第一個執行的phase。任務是確保在reset 或 power on之後的integraty是完整的。
                        3. PEI
                        4. PEI是pre-EFI initialization的簡稱。任務是先做CPU、Chipset及Memory等等的初始化。在這一個階段,PEI初始化基本的環境 for下一個 phase。另外,PEI執行完會有Hand-off block (HOB)傳給DXE
                        5. DXE
                        6. Driver Execution Environment這個階段負責enumerate及init device、初始化UEFI services、  及 protocol等等
                        7. BDS
                        8. Boot Dev Select這邊負責how and where to boot OS.
                        9. TSL
                        10. Transient System Load這個階段將control transit 給OS
                        11. RT
                        12. Runtime的階段已經脫離boot sequence了,這個階段是由OS執行中
                        13. AL
                        14. After Life指的是系統reboot或shutdown

                      UEFI/PI (1) UEFI 簡介


                      • 什麼是 UEFI ? 
                      •  Unified Extensible Firmware Interface 定義了OSplatform firmware之間溝通的介面。例如跟一般都會有firmware的GPU 卡。

                        UEFI的出現是INTEL為了要取代傳統的 BIOS(Legacy BIOS) 然後發展EFI最後移交出去改名成UEFI
                         
                      • 為什麼UEFI?

                      • 1. Legacy BISO的執行環境都是在16 bit下,之後的CPU儘管支援64 bit還是必須"額外"實作支援16 bit 環境以支援BIOS執行。於是像INTEL的vendor就想改變這點取代傳統的BIOS
                        2. 16 bit的CPUaddressing可以到2^20 Bytes ,也就是說極限到1024 KBytes,這當然大大的限制了BIOS可以做的事情。
                        3. 對開發者來說,Legacy BIOS多以ASM來開發,懂的人相對地少且對於開發速度也會有程度的受限。
                      • UEFI Resource

                        1. Intel 移交EFI後實際管理的單位是Unified EFI Forum 因此在上面我們可以看到最新的SPEC.
                        2. Intel Release了代號為Tiano 的EFI的實作後,我們可以直接從SourceForge去抓代號為Tianocore的Opensource project.
                        更詳盡的UEFI簡介可以參考WIKI