《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > UEFI驅(qū)動(dòng)程序的研究與開發(fā)
UEFI驅(qū)動(dòng)程序的研究與開發(fā)
來(lái)源:電子技術(shù)應(yīng)用2014年第5期
韓德強(qiáng),馬 駿,張 強(qiáng)
(北京工業(yè)大學(xué) 計(jì)算機(jī)學(xué)院,北京100124)
摘要: UEFI是Intel推出的新一代BIOS技術(shù)。在分析UEFI基本結(jié)構(gòu)和驅(qū)動(dòng)程序模型的基礎(chǔ)上,詳細(xì)論述了基于USB協(xié)議棧的CC2531 ZigBee模塊的設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)與開發(fā)過(guò)程,實(shí)現(xiàn)了在操作系統(tǒng)啟動(dòng)之前主機(jī)與USB設(shè)備間的信息交互,擴(kuò)展了UEFI的功能。
中圖分類號(hào): TP393
文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2014)05-0010-04
Research and development of UEFI driver
Han Deqiang,Ma Jun,Zhang Qiang
College of Computer,Beijing University of Technology,Beijing 100124,China
Abstract: UEFI sponsored by Intel is the new generation of BIOS technology. Based on the analysis of the basic structures of UEFI and driver model, the paper describes the detailed development process of CC2531 ZigBee module driver based on USB stack. This driver will implement the information interaction between host and USB devices in pre-OS, and expand the function of UEFI.
Key words : UEFI BIOS;CC2531;device driver

    統(tǒng)一可擴(kuò)展固件接口UEFI(Unified Extensible Firmware Interface)是Intel推出的新一代BIOS技術(shù),旨在定義一套操作系統(tǒng)與平臺(tái)固件之間完整的接口規(guī)范,為操作系統(tǒng)的引導(dǎo)提供標(biāo)準(zhǔn)環(huán)境[1]。相比于使用匯編語(yǔ)言編寫的傳統(tǒng)BIOS,UEFI采用模塊化的設(shè)計(jì)、C語(yǔ)言風(fēng)格的參數(shù)堆棧傳遞方式,借由動(dòng)態(tài)鏈接的形式所構(gòu)建出來(lái)的系統(tǒng),更易于實(shí)現(xiàn)[2]。同時(shí),UEFI是以32 bit或64 bit CPU保護(hù)模式運(yùn)行,突破了傳統(tǒng)16 bit實(shí)模式代碼的尋址能力,可達(dá)到CPU的最大尋址空間。得益于這些優(yōu)點(diǎn),UEFI經(jīng)過(guò)近10年的推廣,已經(jīng)成為主流,將使用傳統(tǒng)BIOS的微型計(jì)算機(jī)系統(tǒng)逐漸淘汰出市場(chǎng)[3]。
    UEFI中引入了UEFI驅(qū)動(dòng)程序模型的概念,采用驅(qū)動(dòng)/協(xié)議的結(jié)構(gòu)開發(fā)驅(qū)動(dòng)程序,驅(qū)動(dòng)程序和硬件完全獨(dú)立,具有很強(qiáng)的擴(kuò)展性,從而使得UEFI平臺(tái)下添加新的特性變得簡(jiǎn)單[4]。
1 UEFI基本結(jié)構(gòu)分析
    UEFI主要由引導(dǎo)管理器、固件內(nèi)核、協(xié)議、驅(qū)動(dòng)模型等組件構(gòu)成[4]。其中固件內(nèi)核為UEFI的基礎(chǔ),它將底層硬件功能抽象化,為上層的引導(dǎo)管理器提供兩種服務(wù):引導(dǎo)服務(wù)和運(yùn)行時(shí)服務(wù)。引導(dǎo)管理器是一個(gè)策略引擎,它使用固件內(nèi)核提供的服務(wù)加載UEFI驅(qū)動(dòng)程序和應(yīng)用程序,并最終加載操作系統(tǒng)。
    圖1所示為UEFI的系統(tǒng)框架圖。固件內(nèi)核運(yùn)行在PEI和DXE階段,UEFI在PEI階段直接與硬件層打交道,啟動(dòng)必需的硬件資源,譬如完成CPU和芯片組的初始化,進(jìn)而滿足DXE的執(zhí)行啟動(dòng)條件;其后,系統(tǒng)在DXE階段完成其他所有硬件的初始化,并為上層接口實(shí)現(xiàn)引導(dǎo)服務(wù)和運(yùn)行時(shí)服務(wù)。引導(dǎo)管理器運(yùn)行在DXE和BDS階段,它通過(guò)加載框架驅(qū)動(dòng)和平臺(tái)驅(qū)動(dòng)向上層提供UEFI服務(wù)和接口,通過(guò)加載應(yīng)用程序擴(kuò)展系統(tǒng)功能,并在BDS階段提供一個(gè)引導(dǎo)菜單,供用戶選擇引導(dǎo)設(shè)備。最終引導(dǎo)加載器在ROM上加載操作系統(tǒng)加載器,將控制權(quán)移交給操作系統(tǒng),完成操作系統(tǒng)的引導(dǎo)。

2 CC2531 ZigBee模塊的設(shè)備驅(qū)動(dòng)程序開發(fā)
    CC2531是TI公司推出的一款用于IEEE 802.15.4或ZigBee應(yīng)用的片上系統(tǒng)解決方案,它能夠以非常低的成本建立網(wǎng)絡(luò)節(jié)點(diǎn),支持低功耗的無(wú)線通信,主要用于遠(yuǎn)程控制、家庭控制等領(lǐng)域[5]。CC2531集成了USB2.0功能模塊,可以更加方便地與主機(jī)進(jìn)行通信。
    本文將CC2531 ZigBee模塊(以下簡(jiǎn)稱CC2531模塊)通過(guò)USB接口與無(wú)線POS機(jī)的主機(jī)相連,CC2531模塊通過(guò)ZigBee無(wú)線網(wǎng)絡(luò)與POS機(jī)的外設(shè)(如打印機(jī)、客顯、鍵盤等)進(jìn)行信息交互。此方案實(shí)現(xiàn)了在啟動(dòng)操作系統(tǒng)之前對(duì)POS機(jī)及其外設(shè)進(jìn)行相應(yīng)遠(yuǎn)程檢測(cè)和診斷的功能。圖2為無(wú)線POS機(jī)系統(tǒng)的結(jié)構(gòu)框圖。
2.1 UEFI驅(qū)動(dòng)程序模型分析
2.1.1 句柄和協(xié)議

    UEFI驅(qū)動(dòng)程序模型使用句柄代表設(shè)備,每個(gè)設(shè)備對(duì)應(yīng)有自己的句柄,句柄由一個(gè)或多個(gè)協(xié)議組成。協(xié)議是一個(gè)以128 bit的全局唯一標(biāo)識(shí)符GUID(Globally Unique Identifier)命名的結(jié)構(gòu)體,是一些指針和數(shù)據(jù)結(jié)構(gòu)體或者規(guī)范定義的接口函數(shù)指針的集合,協(xié)議代表設(shè)備提供的一類服務(wù),服務(wù)的具體功能在設(shè)備驅(qū)動(dòng)程序(以下簡(jiǎn)稱驅(qū)動(dòng))中實(shí)現(xiàn)。開發(fā)者首先找到指定設(shè)備句柄上掛載的指定協(xié)議,再通過(guò)協(xié)議提供的接口訪問(wèn)設(shè)備驅(qū)動(dòng)中實(shí)現(xiàn)服務(wù)的功能函數(shù),對(duì)設(shè)備進(jìn)行操作。圖3所示為設(shè)備句柄和協(xié)議的結(jié)構(gòu)圖。

2.1.2 驅(qū)動(dòng)程序模型執(zhí)行流程
    UEFI驅(qū)動(dòng)程序模型是一種用于簡(jiǎn)化設(shè)備驅(qū)動(dòng)設(shè)計(jì)和執(zhí)行的機(jī)制,遵循驅(qū)動(dòng)程序模型規(guī)范的UEFI驅(qū)動(dòng)的可執(zhí)行鏡像大小會(huì)得到有效的減小[6]。UEFI驅(qū)動(dòng)程序模型的執(zhí)行流程圖如圖4所示。

    驅(qū)動(dòng)程序模型采用UEFI 驅(qū)動(dòng)載入、連接的形式來(lái)進(jìn)行硬件的辨識(shí)、控制及系統(tǒng)資源掌控。在DXE階段,系統(tǒng)調(diào)用引導(dǎo)服務(wù)的LoadImage()函數(shù)將驅(qū)動(dòng)鏡像文件加載到內(nèi)存中,調(diào)用StartImage()函數(shù)執(zhí)行驅(qū)動(dòng)的入口函數(shù)來(lái)啟動(dòng)驅(qū)動(dòng)。遵循模型規(guī)范的設(shè)備驅(qū)動(dòng)在入口函數(shù)的初始化中不涉及任何硬件操作,僅僅實(shí)現(xiàn)驅(qū)動(dòng)綁定協(xié)議(Driver Binding Protocol),協(xié)議包含3個(gè)接口函數(shù):Support()、Start()和Stop()。Support()函數(shù)用來(lái)驗(yàn)證驅(qū)動(dòng)程序與給定的設(shè)備句柄是否匹配;Start()函數(shù)負(fù)責(zé)驅(qū)動(dòng)與句柄的連接,即將抽象 I/O 功能的協(xié)議安裝到設(shè)備句柄上;相對(duì)應(yīng)的,Stop()函數(shù)則會(huì)強(qiáng)制停止驅(qū)動(dòng)對(duì)一個(gè)設(shè)備句柄的管理和控制,并卸載設(shè)備句柄在Start()中安裝的所有協(xié)議。
    DXE階段執(zhí)行完成后,雖然加載和啟動(dòng)了驅(qū)動(dòng),但還在等待著連接設(shè)備句柄。因此,在BDS階段引導(dǎo)管理器將會(huì)調(diào)用引導(dǎo)服務(wù)的ConnectController()函數(shù)執(zhí)行驅(qū)動(dòng)的連接過(guò)程。該函數(shù)執(zhí)行所有驅(qū)動(dòng)綁定協(xié)議的Support()進(jìn)行設(shè)備句柄的驗(yàn)證,若驗(yàn)證正確,則會(huì)繼續(xù)調(diào)用Start()連接驅(qū)動(dòng)和設(shè)備句柄,并在設(shè)備句柄上安裝抽象I/O功能的協(xié)議。
2.2 CC2531模塊USB驅(qū)動(dòng)協(xié)議棧
    圖5所示是由一系列驅(qū)動(dòng)組成的多層次的、完整的 USB 驅(qū)動(dòng)協(xié)議棧。處于上層的驅(qū)動(dòng)會(huì)使用下層驅(qū)動(dòng)提供的服務(wù),并為更高層的驅(qū)動(dòng)提供服務(wù)。首先,PCI總線驅(qū)動(dòng)枚舉設(shè)備時(shí)發(fā)現(xiàn)USB主機(jī)控制器,并在控制器句柄上安裝EFI_PCI_IO_PROTOCOL協(xié)議,USB主機(jī)控制器驅(qū)動(dòng)則使用EFI_PCI_IO_PROTOCOL協(xié)議提供的接口實(shí)現(xiàn)EFI_USB_HC_PROTOCOL協(xié)議。然后,USB總線驅(qū)動(dòng)使用EFI_USB_HC_PROTOCOL協(xié)議服務(wù)實(shí)現(xiàn)對(duì)USB設(shè)備的枚舉,生成CC2531設(shè)備句柄,并在設(shè)備句柄上安裝 EFI_USB_IO_PROTOCOL協(xié)議。最后,CC2531模塊設(shè)備驅(qū)動(dòng)使用EFI_USB_IO_PROTOCOL協(xié)議服務(wù),在CC2531模塊設(shè)備句柄上安裝EFI_USB_CCCONTROL_PROTOCOL協(xié)議,完成CC2531模塊驅(qū)動(dòng)協(xié)議棧的加載。

2.3 CC2531模塊驅(qū)動(dòng)程序設(shè)計(jì)
    CC2531模塊驅(qū)動(dòng)作為設(shè)備驅(qū)動(dòng),遵循UEFI驅(qū)動(dòng)程序模型規(guī)范,使用驅(qū)動(dòng)綁定協(xié)議的方式實(shí)現(xiàn)設(shè)備驅(qū)動(dòng)的加載和連接。同時(shí),驅(qū)動(dòng)還提供通信協(xié)議EFI_USB_CCCONTROL_PROTOCOL用于系統(tǒng)與CC2531模塊間的通信,并通過(guò)ZigBee網(wǎng)絡(luò)與無(wú)線POS機(jī)外設(shè)進(jìn)行通信。
2.3.1 綁定協(xié)議接口函數(shù)的實(shí)現(xiàn)

 


    (1)Support():圖6所示為Support函數(shù)實(shí)現(xiàn)流程圖,函數(shù)首先檢查給定的目標(biāo)設(shè)備句柄是否安裝有 EFI_USB_IO_PROTOCOL協(xié)議,若有,則說(shuō)明USB總線驅(qū)動(dòng)已經(jīng)辨認(rèn)出該USB設(shè)備。其次,使用EFI_USB_IO_PROTOCOL協(xié)議提供的功能接口函數(shù)獲取目標(biāo)USB設(shè)備的設(shè)備描述符,描述符中的接口號(hào)、接口類型、子類型和協(xié)議等字段指定了的USB設(shè)備的類型,檢查這些字段就可得知驅(qū)動(dòng)是否為CC2531模塊設(shè)備驅(qū)動(dòng),如果匹配則說(shuō)明加載的驅(qū)動(dòng)正確,就會(huì)執(zhí)行Start()函數(shù)。以下是部分實(shí)現(xiàn)代碼:

    EFI_STATUS USBCC2531DriverBindingSupported(…)
    {…
    //檢查目標(biāo)設(shè)備句柄是否安裝有USB_IO協(xié)議
        Status = gBS->OpenProtocol (Controller,
&gEfiUsbIoProtocolGuid,
    (VOID **) &UsbIo, This->DriverBindingHandle,
    Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
    …
    //讀出目標(biāo)USB設(shè)備的設(shè)備描述符
    Status = UsbIo->UsbGetInterfaceDescriptor (
            UsbIo, &InterfaceDescriptor);
    //檢查是否為USB-CC2531的驅(qū)動(dòng)
    if(InterfaceDescriptor.InterfaceNumber==1
    &&InterfaceDescriptor.InterfaceClass ==0x0a
    && InterfaceDescriptor.InterfaceSubClass==0
    && InterfaceDescriptor.InterfaceProtocol == 0 ) { … }
    //關(guān)閉USB_IO協(xié)議
        gBS->CloseProtocol (…);
        return Status;
    }
    (2)Start():Start()函數(shù)的目標(biāo)是使用USB總線驅(qū)動(dòng)提供的協(xié)議服務(wù)在CC2531模塊設(shè)備驅(qū)動(dòng)中安裝通信協(xié)議EFI_USB_CCCONTROL_PROTOCOL。函數(shù)首先打開設(shè)備句柄上掛載的EFI_USB_IO_PROTOCOL協(xié)議,使用該協(xié)議提供的接口函數(shù)UsbGetInterfaceDescriptor()和UsbGetEndpointDescriptor()得到USB設(shè)備的接口描述符和端點(diǎn)描述符,分析設(shè)備描述符中的字段以確定USB設(shè)備信息和接口類型等參數(shù)。其次,為驅(qū)動(dòng)私有數(shù)據(jù)結(jié)構(gòu)體分配內(nèi)存,并使用設(shè)備描述符中的字段信息進(jìn)行初始化。最后,安裝EFI_USB_CCCONTROL_PROTOCOL協(xié)議,完成驅(qū)動(dòng)與設(shè)備的連接。圖7所示為Start()函數(shù)實(shí)現(xiàn)流程圖。
    (3)Stop():Stop()是Start執(zhí)行流程的逆過(guò)程,該函數(shù)用于卸載EFI_USB_CCCONTROL_PROTOCOL協(xié)議,釋放驅(qū)動(dòng)私有數(shù)據(jù)結(jié)構(gòu)體占用的內(nèi)存資源,關(guān)閉EFI_USB_IO_PROTOCOL協(xié)議,斷開CC2531模塊驅(qū)動(dòng)與設(shè)備句柄的連接。

2.3.2 設(shè)備通信協(xié)議結(jié)構(gòu)體
    為了實(shí)現(xiàn)UEFI系統(tǒng)與CC2531模塊之間的數(shù)據(jù)通信,本文設(shè)計(jì)了EFI_USB_CCCONTROL_PROTOCOL作為驅(qū)動(dòng)的通信協(xié)議。該協(xié)議中包括了UEFI系統(tǒng)與CC2531模塊間數(shù)據(jù)發(fā)送和接收的接口函數(shù),還有部分與POS機(jī)系統(tǒng)外設(shè)交互的命令函數(shù),如系統(tǒng)外設(shè)啟動(dòng)和復(fù)位命令的接口函數(shù)。協(xié)議的部分成員函數(shù)定義如下:
struct _EFI_USB_CCCONTROL_PROTOCOL {…
    EFI_USB_CONTROLL_RESET Reset;//復(fù)位設(shè)備
    EFI_USB_TEXTOUTPUT_STRING OutputString;
//數(shù)據(jù)發(fā)送
    EFI_USBINPUT_STRING    ReadInput;  //數(shù)據(jù)讀取
    EFI_USB_DETECTDEVICE    DetectDevice;
//設(shè)備啟動(dòng)命令
    EFI_EVENT WaitForInputString;//等待讀入事件
    };
2.3.3 設(shè)備通信協(xié)議接口函數(shù)的實(shí)現(xiàn)
    CC2531 模塊的USB接口固件代碼是基于USB通信設(shè)備類CDC(Communication Device Class)協(xié)議實(shí)現(xiàn)的。CDC由通信接口類和數(shù)據(jù)接口類組成,通信接口類主要負(fù)責(zé)設(shè)備的管理和控制,數(shù)據(jù)接口類則負(fù)責(zé)數(shù)據(jù)的傳輸。CC2531模塊的USB接口采用端點(diǎn)0作為通信接口類中的控制端點(diǎn)來(lái)管理設(shè)備的枚舉和命令控制,數(shù)據(jù)接口類使用塊傳輸輸入(IN)端點(diǎn)和塊傳輸輸出(OUT)端點(diǎn)實(shí)現(xiàn)數(shù)據(jù)的雙向傳輸。因此,UEFI系統(tǒng)對(duì)CC2531模塊的枚舉和識(shí)別采用控制傳輸方式,數(shù)據(jù)通信則采用批量傳輸方式。
    協(xié)議的發(fā)送接口函數(shù)為UsbCCDataTransmit(),該函數(shù)調(diào)用EFI_USB_IO_PROTOCOL協(xié)議提供的服務(wù)函數(shù)UsbBulkTransfer(),通過(guò)將數(shù)據(jù)寫入輸出端口完成數(shù)據(jù)從主機(jī)到CC2531模塊的批量傳輸。設(shè)備驅(qū)動(dòng)發(fā)送數(shù)據(jù)接口函數(shù)的部分代碼實(shí)現(xiàn)如下所示:
    EFI_STATUS UsbCCDataTransmit (…)
    { …
    //選擇發(fā)送數(shù)據(jù)的輸出端口
    Endpoint=UsbCC2531Device->BulkOutEndpointDescriptor;
    //等待發(fā)送或接收的超時(shí)時(shí)間
    Timeout = Timeout / USB_MASS_1_MILLISECOND;
        //發(fā)送數(shù)據(jù)
        Status=UsbCC2531Device->UsbIo->UsbBulkTransfer (
        UsbCC2531Device->UsbIo, Endpoint.EndpointAddress,
Data, TransLen, Timeout, &Result);
        if (EFI_ERROR (Status)) { …}
        return Status;
    }
    CC2531模塊設(shè)備驅(qū)動(dòng)的數(shù)據(jù)接收操作亦通過(guò)調(diào)用函數(shù)UsbBulkTransfer()檢測(cè)輸入端口的緩沖隊(duì)列完成。由于數(shù)據(jù)接收操作的被動(dòng)性,驅(qū)動(dòng)需要建立一套讀操作的響應(yīng)觸發(fā)機(jī)制。本方案使用UEFI的事件(EVENT)機(jī)制實(shí)現(xiàn)對(duì)數(shù)據(jù)接收操作的響應(yīng):首先在驅(qū)動(dòng)的Start()創(chuàng)建一個(gè)定時(shí)器事件,并在定時(shí)器的響應(yīng)函數(shù)USBCC2531Timer-
Handler()中周期性調(diào)用UsbCCDataRecevice()執(zhí)行對(duì)輸入端口緩沖隊(duì)列的讀操作,如果成功讀到數(shù)據(jù),則將讀回的數(shù)據(jù)存入私有數(shù)據(jù)結(jié)構(gòu)體的循環(huán)隊(duì)列UsbDataQueue中。其次,創(chuàng)建一個(gè)等待事件WaitForInputString,并在等待事件的觸發(fā)函數(shù)中檢查循環(huán)隊(duì)列,如有數(shù)據(jù)則讀取,否則循環(huán)等待。部分?jǐn)?shù)據(jù)讀取操作的代碼如下:
    EFI_STATUS UsbCCDataRecevice ( …)
    { …
        Status=UsbCC2531Device->UsbIo->UsbBulkTransfer (…);
        if (EFI_ERROR (Status)) {  …  }
        else {
            //將讀取的數(shù)據(jù)存入鏈表
            Enqueue (UsbCC2531Device->UsbDataQueue,
Data,MaxItemSize);
                }
        return Status;
    }
    UEFI采用的模塊化設(shè)計(jì)和驅(qū)動(dòng)程序模型都為整體系統(tǒng)提供了良好的兼容性和擴(kuò)展性,簡(jiǎn)化了UEFI驅(qū)動(dòng)和應(yīng)用程序的開發(fā)難度,提高了可維護(hù)性,有助于計(jì)算機(jī)固件的進(jìn)一步發(fā)展。相對(duì)于傳統(tǒng)BIOS,UEFI具有明顯的優(yōu)越性,越來(lái)越得到業(yè)界和市場(chǎng)的認(rèn)可。本文從UEFI功能擴(kuò)展的角度考慮,分析了UEFI的架構(gòu)和驅(qū)動(dòng)程序模型,設(shè)計(jì)并實(shí)現(xiàn)了CC2531模塊的設(shè)備驅(qū)動(dòng)程序,最終實(shí)現(xiàn)了在啟動(dòng)操作系統(tǒng)之前通過(guò)CC2531模塊與無(wú)線POS機(jī)外設(shè)進(jìn)行通信的目標(biāo)。本方案的下一目標(biāo)是擴(kuò)展UEFI下的網(wǎng)絡(luò)應(yīng)用,實(shí)現(xiàn)對(duì)POS機(jī)系統(tǒng)的遠(yuǎn)程管理和診斷。
參考文獻(xiàn)
[1] Unified EFI,Inc.Unified extensible firmware interface specification[S].Version2.3.1 Errata C.2012:1-22.
[2] 朱賀新.基于UEFI的可信BIOS平臺(tái)研究與應(yīng)用[D].西安:西安科技大學(xué),2008:11-15.
[3] 萬(wàn)象.基于UEFI系統(tǒng)的LINUX通用應(yīng)用平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)[D].上海:上海交通大學(xué),2012.
[4] 潘登,劉光明.EFI結(jié)構(gòu)分析及Driver開發(fā)[J].計(jì)算機(jī)工程與科學(xué),2006,28(2):115-117.
[5] Texas Instruments.CC2531 SOC solution for IEEE 802.15.4 and ZigBee applications(Rev.A)[Z].2011.
[6] ZIMMER V,ROTHMAN M,MARISETTY S.Beyond BIOS:developing with the unified extensible firmware interface(2  Edition)[M].Intel Press,2010.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。