《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應(yīng)用 > 基于ARM平臺的UEFI開發(fā)與移植
基于ARM平臺的UEFI開發(fā)與移植
來源:電子技術(shù)應(yīng)用2014年第4期
韓德強,馬 駿,王宗俠,高雪圓
(北京工業(yè)大學(xué) 計算機學(xué)院,北京100124)
摘要: 介紹了ARM平臺下UEFI的相關(guān)概念和引導(dǎo)流程,基于TI公司的OMAP4460 Cortex A9處理器開發(fā)平臺分析了ARM-UEFI各個執(zhí)行階段的移植過程。通過具體實例說明了ARM平臺中UEFI設(shè)備驅(qū)動程序的移植及開發(fā)方法。
中圖分類號:TP393
文獻標(biāo)識碼:A
文章編號: 0258-7998(2014)04-0011-04
The porting and development of UEFI based on ARM system
Han Deqiang,Ma Jun,Wang Zongxia,Gao Xueyuan
College of Computer, Beijing University of Technology,Beijing 100124,China
Abstract: This paper introduces the general concepts and boot process of UEFI under ARM system. It analyzed the porting step of each ARM-UEFI phase based on TI Cortex A9 processor OMAP4460 demo board. It illustrated the porting process and method to development the UEFI device driver under ARM system.
Key words : ARM-UEFI;OMAP4460;device driver

    統(tǒng)一可擴展固件接口UEFI(Unified Extensible Firmware Interface)在設(shè)計之初被定義為一種與處理器架構(gòu)無關(guān)的接口標(biāo)準(zhǔn)。UEFI接口可以采用多種不同的架構(gòu)實現(xiàn),對外則都表現(xiàn)為相同的接口。這樣,UEFI就可以最大限度地保證不同設(shè)計間的代碼重用,其中也包括不同處理器架構(gòu)的平臺[1]。2009年發(fā)布的UEFI 2.3規(guī)范與傳統(tǒng)的BIOS和UEFI早期版本只支持X86架構(gòu)的處理器相比,最大的改進在于支持不同架構(gòu)的處理器平臺,ARM-UEFI成為了規(guī)范的一部分。2013年發(fā)布的UEFI2.4規(guī)范中包含了對ARM 64位架構(gòu)處理器的支持。這些都表明UEFI對ARM系統(tǒng)預(yù)引導(dǎo)固件的支持是一個新的機遇。使用基于UEFI標(biāo)準(zhǔn)的ARM預(yù)引導(dǎo)固件具有很多優(yōu)越性,UEFI不僅可以實現(xiàn)不同架構(gòu)平臺之間的代碼共享,還可以共享標(biāo)準(zhǔn)外設(shè)(UART、Ethernet、USB控制器等)的驅(qū)動代碼以及豐富的標(biāo)準(zhǔn)函數(shù)庫接口。同時,ARM-UEFI的實現(xiàn)為ARM系統(tǒng)提供了真正獨立于操作系統(tǒng)的啟動解決方案,而其他大多數(shù)現(xiàn)有的ARM啟動解決方案(UBoot、Redboot等)都是與其所支持的操作系統(tǒng)相耦合[2]。本文詳述了基于OMAP4460嵌入式平臺的ARM-UEFI的移植過程及其外設(shè)的UEFI驅(qū)動程序的開發(fā)方法。
1 OMAP4460處理器及平臺硬件結(jié)構(gòu)
    OMAP4460是TI公司專為智能手機、平板計算機以及具有豐富多媒體功能的移動終端設(shè)計的一款高性能、高集成度的嵌入式異構(gòu)多核處理器[3]。該處理器包括2個Cortex A9內(nèi)核、1個DSP內(nèi)核、2個Cortex-M3內(nèi)核、1個GPU以及豐富的I/O接口資源。在OMAP4460中,嵌入式操作系統(tǒng)運行在ARM內(nèi)核上,算法的運算工作由DSP內(nèi)核完成,二者通過TI提供的Codec Engine機制進行數(shù)據(jù)交互,實現(xiàn)了OMAP4460處理器內(nèi)部多核的協(xié)同工作。
    OMAP4460開發(fā)平臺的硬件結(jié)構(gòu)框圖如圖1所示。硬件平臺由核心模塊和擴展板兩部分組成,核心模塊包括OMAP4460處理器、TWL6032電源管理芯片和1 GB的DRAM;擴展板主要實現(xiàn)外設(shè)接口電路,包括 SD/TF卡接口、UART接口、USB接口、以太網(wǎng)接口和DVI/HDMI接口等。

2 ARM-UEFI引導(dǎo)流程
    通用UEFI根據(jù)不同時間段內(nèi)平臺初始化所要完成的任務(wù)將操作系統(tǒng)啟動過程按順序分為SEC、PEI、DXE和BDS[4] 4個階段。其中SEC(安全)階段檢測并驗證固件鏡像的完整性,同時建立C語言執(zhí)行環(huán)境的堆棧;PEI(預(yù)EFI初始化)階段主要完成內(nèi)存初始化,將固件鏡像加載至內(nèi)存中執(zhí)行;DXE(驅(qū)動執(zhí)行環(huán)境)階段完成平臺初始化,并為操作系統(tǒng)引導(dǎo)提供軟件抽象的服務(wù);BDS(引導(dǎo)設(shè)備選擇)階段從引導(dǎo)設(shè)備中啟動操作系統(tǒng),將控制權(quán)交給操作系統(tǒng),完成引導(dǎo)過程。UEFI上電執(zhí)行順序如圖2所示。

    目前ARM平臺的啟動方式多種多樣,Bootloader通常采用多階段的啟動過程[5]。首階段確定啟動方式,執(zhí)行必要的初始化操作,加載后續(xù)階段鏡像,后續(xù)階段提供復(fù)雜的功能用于引導(dǎo)操作系統(tǒng)。這種方式既能夠保證Bootloader的功能性,又具有很好的可移植性。因此對于OMAP4460平臺的啟動方案,采用x-loader + UEFI兩個啟動階段的方式引導(dǎo)操作系統(tǒng)。x-loader作為第一階段的固件,要執(zhí)行時鐘、內(nèi)存控制器等部分硬件的初始化,并確定OMAP4460平臺的啟動方式,最終將UEFI加載到內(nèi)存中并跳轉(zhuǎn)到指定地址執(zhí)行。內(nèi)存初始化已在x-loader中完成,故UEFI不再實現(xiàn)SEC以及PEI階段的大部分功能,OMAP4460平臺ARM-UEFI的PEI階段只需要完成系統(tǒng)內(nèi)存映射和UEFI執(zhí)行環(huán)境堆棧的建立,并執(zhí)行硬件平臺相關(guān)模塊的初始化配置,之后UEFI跳轉(zhuǎn)進入DXE和BDS階段。本方案DXE以及BDS階段的執(zhí)行策略和實現(xiàn)功能與通用UEFI固件基本相同:在DXE階段加載所有的驅(qū)動程序,完成平臺初始化工作;在BDS階段創(chuàng)建控制臺,設(shè)置內(nèi)核的啟動參數(shù),加載引導(dǎo)設(shè)備的內(nèi)核鏡像到內(nèi)存中執(zhí)行。OMAP4460平臺ARM-UEFI引導(dǎo)流程圖如圖3所示。

3 ARM-UEFI開發(fā)與移植
3.1 移植x-loader

    OMAP4460處理器內(nèi)部的SRAM只有64 KB,相對于第二階段UEFI固件鏡像的數(shù)百kB而言過小,OMAP4460處理器無法加載UEFI固件鏡像到SRAM運行,而需要使用外部DRAM加載。因此,本方案采用基于精簡UBoot基本代碼的x-loader作為第一階段的引導(dǎo)固件。由于SRAM容量的限制,x-loader的初始化操作只針對必要的硬件模塊,如引腳復(fù)用和功能設(shè)置、時鐘、內(nèi)存控制器等。初始化操作的目的是將UEFI固件鏡像從OMAP446平臺的SD卡中加載到DRAM中,然后跳轉(zhuǎn)到入口地址執(zhí)行。
    x-loader的入口位于Start.s文件,Start.s首先執(zhí)行CPU的基本初始化,包括禁止Cache和TLB、關(guān)閉中斷等。其次執(zhí)行兩個跳轉(zhuǎn)模塊cpu_init_crit和start_armboot,cpu_init_crit模塊跳轉(zhuǎn)到s_init()函數(shù)執(zhí)行,s_init()中調(diào)用了3個函數(shù)實現(xiàn)平臺基本初始化:set_muxconf_regs()實現(xiàn)處理器芯片引腳復(fù)用和功能設(shè)置;ddr_init()實現(xiàn)內(nèi)存初始化;prcm_init()則實現(xiàn)平臺各個模塊時鐘的初始化配置。這3個函數(shù)的修改要針對OMAP4460平臺的具體硬件結(jié)構(gòu)以及引導(dǎo)過程中所使用到的模塊進行。start_armboot則是在內(nèi)存初始化完成且堆棧建立以后執(zhí)行,程序跳轉(zhuǎn)至lib\board.c文件的start_armboot()函數(shù),實現(xiàn)加載UEFI固件鏡像到指定內(nèi)存位置的過程。第二階段UEFI固件鏡像的入口地址定義為CFG_LOADADDR,它必須與OAMP4460平臺UEFI固件鏡像的起始地址相同,后者由固件的fdf(Flash描述文件)指定。最終x-loader使用函數(shù)指針的方式實現(xiàn)x-loader到UEFI的跳轉(zhuǎn),代碼如下:
    ((init_fnc_t *)CFG_LOADADDR)();
3.2 移植PEI階段代碼
    如上所述,OMAP4460平臺的ARM-UEFI沒有SEC階段,且PEI階段實現(xiàn)功能與通用UEFI的PEI階段也有所不同,PEI階段不再需要完成內(nèi)存初始化任務(wù),而是側(cè)重于系統(tǒng)平臺信息、內(nèi)存資源的收集過程,并通過信息描述塊HOB傳遞給DXE階段。OMAP4460平臺的PEI階段的主體實現(xiàn)代碼位于ArmPlatformPkg\PrePi.c的PrePiMain()函數(shù)中,該函數(shù)主要實現(xiàn)了3個功能: PEI階段的串口調(diào)試信息輸出;調(diào)用PEI模塊MemoryPeim實現(xiàn)MMU的初始化,建立UEFI系統(tǒng)堆棧,并將這些系統(tǒng)資源建立成HOB傳遞給后續(xù)階段;調(diào)用PlatformPeim實現(xiàn)一些硬件模塊的初始化和配置。
    PEI階段的串口輸出是通過調(diào)用SerialPortLib中的庫函數(shù)實現(xiàn)的。SerialPortLib主要包含兩部分:串口初始化函數(shù)和串口讀寫函數(shù)。初始化函數(shù)SerialPortInitialize()首先配置平臺UART接口的引腳復(fù)用,使能時鐘;然后再設(shè)置串口通信模式,配置串口通信的波特率等參數(shù);最后使能FIFO,完成UART接口的初始化。而讀寫函數(shù)則是通過輪詢標(biāo)志位的方式判斷FIFO是否為空,再按字節(jié)讀寫FIFO。PEI階段調(diào)試信息輸出樣例代碼如下:
    SerialPortInitialize (); //UART模塊初始化
    CharCount = AsciiSPrint (Buffer,sizeof(Buffer),"UEFI \n");
    SerialPortWrite((UINT8 *) Buffer, CharCount);//數(shù)據(jù)輸出
    PlatformPeim中再次實現(xiàn)了平臺模塊的初始化,目的是向后兼容未來采用通用UEFI引導(dǎo)方式的ARM平臺的PEI階段所要實現(xiàn)的完整功能。PlatformPeim中包括了3個函數(shù):PadConfiguration()、ClockInit()和GpmcInit()。PadConfiguration()函數(shù)和ClockInit()函數(shù)都通過操作宏定義的方式實現(xiàn)平臺功能。PadConfiguration()完成平臺所有引腳復(fù)用功能的設(shè)置。ClockInit()完成平臺所有模塊時鐘的配置,并使能部分模塊時鐘。這種實現(xiàn)方式的好處是有統(tǒng)一的啟動代碼,開發(fā)DXE階段的外設(shè)驅(qū)動程序時不需要再配置外設(shè)接口的引腳和時鐘。引腳復(fù)用配置代碼如下:
    typedef struct {
        UINTN   Pin;   //引腳寄存器地址
        UINTN   ConfigValue; //引腳屬性功能
    } PAD_CONFIGURATION;
    MmioWrite16(PadConfigurationTableShared[Index].Pin,
        PadConfigurationTableShared[Index].ConfigValue);
    數(shù)據(jù)結(jié)構(gòu)PAD_CONFIGURATION類型的數(shù)組PadConfigurationTableShared中存放的是OMAP4460處理器芯片所有引腳的寄存器地址宏定義和引腳屬性宏定義。MmioWrite16()函數(shù)實現(xiàn)16位寄存器的寫功能,通過獲取指定引腳寄存器的地址,寫入指定的配置屬性,完成引腳復(fù)用功能的配置。
    GpmcInit()則用于配置通用存儲控制器GPMC的片選信號,樣例代碼如下:
    for (i = 0; i < 8; i++)
    MmioAnd32(GPMC_CONFIG7_0 + 0x30*i, ~BIT6);
    PEI的工作完成之后,解壓固件鏡像的壓縮部分到內(nèi)存,并直接跳轉(zhuǎn)至DXE階段執(zhí)行,代碼如下:
    Status = DecompressFirstFv (); //解壓固件卷
    Status = LoadDxeCoreFromFv(NULL, 0);//加載DXE核心
3.3 開發(fā)設(shè)備驅(qū)動程序
    EDK II開發(fā)工具是基于X86平臺的PCI總線結(jié)構(gòu)實現(xiàn)的。當(dāng)用其開發(fā)OMAP4460平臺ARM-UEFI時,需要重構(gòu)平臺的接口控制器驅(qū)動程序,為上層提供標(biāo)準(zhǔn)的UEFI服務(wù)。同時,完整移植處于上層并滿足工業(yè)標(biāo)準(zhǔn)的接口驅(qū)動程序,從而實現(xiàn)對原有代碼的重用,加快ARM-UEFI的開發(fā)。
    以顯示驅(qū)動程序的開發(fā)為例,在OMAP4460平臺上使用HDMI作為ARM-UEFI引導(dǎo)時的顯示接口。ARM-UEFI系統(tǒng)中只需實現(xiàn)HDMI顯示驅(qū)動程序即可實現(xiàn)顯示控制臺的輸出。HDMI顯示驅(qū)動程序?qū)崿F(xiàn)圖像輸出協(xié)議EFI_GRAPHICS_OUTPUT_PROTOCOL,該協(xié)議提供服務(wù)接口給圖像控制臺驅(qū)動程序GraphicsConsoledxe, 再由該驅(qū)動程序?qū)崿F(xiàn)簡單文本輸出協(xié)議EFI_SIMPLE_TEXTOUT_
PROTOCOL,最后由虛擬控制臺驅(qū)動程序Consoleplitterdxe將所有掛載簡單文本輸出協(xié)議的設(shè)備句柄統(tǒng)一掛載到虛擬控制臺輸出句柄ConOut上,由ConOut實現(xiàn)控制臺的輸出,OMAP4460平臺UEFI圖形控制臺結(jié)構(gòu)圖如圖4所示。

    HDMI顯示驅(qū)動程序包括三部分:顯示模塊硬件初始化、顯示模式的配置以及圖像的顯示。其中GOP協(xié)議的函數(shù)接口實現(xiàn)顯示模式配置與圖像的顯示,QueryMode、SetMode兩個接口實現(xiàn)分辨率、顏色及頻率的配置,Blt接口實現(xiàn)圖像顯示。GOP協(xié)議數(shù)據(jù)結(jié)構(gòu)定義如下:
    struct  _EFI_GRAPHICS_OUTPUT_PROTOCOL {
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE
QueryMode;
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;   
//設(shè)置顯示模式
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT     Blt; //圖像顯示
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE  *Mode;//結(jié)構(gòu)體
    }
    顯示模塊初始化函數(shù)InitializeDisplay()在驅(qū)動程序的入口函數(shù)中執(zhí)行,具體初始化過程分為3步:
    (1)使能ESD保護芯片TPD12S016的供電及熱插拔引腳功能,檢測HDMI接口的HDMI_HPD引腳狀態(tài),檢測是否接入顯示器。
    (2)使能顯示子系統(tǒng)的功能時鐘和接口時鐘,同時使能HDMI物理層的時鐘。
    (3)申請圖像管道內(nèi)存,并記錄基地址。
    HDMI接口顯示模式的配置分為顯示子系統(tǒng)和HDMI物理層兩部分的顯示模式配置,由QueryMode和SetMode接口函數(shù)實現(xiàn)。QueryMode通過HDMI的I2C接口讀取顯示器的擴展顯示標(biāo)識數(shù)據(jù)EDID(Extended Display Identification Data),EDID中包含了監(jiān)視器時序、定時和分辨率等性能參數(shù),使用這些參數(shù)填充Mode結(jié)構(gòu)體,再將Mode作為改變值參數(shù)傳遞給SetMode接口,由SetMode完成顯示子系統(tǒng)和HDMI物理層中顯示輸出時鐘頻率、圖像分辨率、位寬等寄存器變化值的寫入和重新使能,從而更新顯示分辨率、圖像格式以及顏色模式等參數(shù)。寫寄存器樣例代碼如下:
    MmioWrite32(HDMI_WP_VIDEO_SIZE,
        ((LcdModes[ModeNumber].HorizontalResolution)|
        ((LcdModes[ModeNumber].VerticalResolution)<<16)));
其中宏定義HDMI_WP_VIDEO_SIZE是HDMI模塊定義顯示器分辨率的32位寄存器地址,該寄存器低16位為水平像素,高16位為垂直像素。結(jié)構(gòu)體LcdModes的HorizontalResolution和VerticalResolution參數(shù)代表顯示模式需要配置的分辨率參數(shù),通過MmioWrite32()函數(shù)將值寫入寄存器,完成配置。
    圖像的顯示由GOP協(xié)議的Blt接口函數(shù)實現(xiàn),Blt函數(shù)首先調(diào)用LcdPlatformGetBpp()函數(shù)獲取平臺設(shè)置的圖像格式以及位寬,再計算原圖像像素和目標(biāo)管道內(nèi)存的地址,然后將EFI圖像像素轉(zhuǎn)換成顯示器設(shè)置的像素格式,宏定義LCD_BITS_PER_PIXEL_24表示圖像格式為xRGB24,即每個像素占用32位,低24位按照藍綠紅各8位排列,最高8位為空。最后將轉(zhuǎn)換完成的像素數(shù)據(jù)存放在計算好的目標(biāo)管道內(nèi)存中,使用圖像管道將圖像數(shù)據(jù)輸出。具體代碼如下:
    LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
    if(BitsPerPixel== LCD_BITS_PER_PIXEL_24)
    {
    // 計算原地址和目標(biāo)地址
    EfiSourcePixel    = BltBuffer + SourceLine * BltBufferHori-
zontalResolution + SourcePixelX;
    DestinationPixel32bit = (UINT32 *)FrameBufferBase +
DestinationLine * HorizontalResolution + DestinationPixelX;
    //將原像素轉(zhuǎn)換后復(fù)制到目標(biāo)地址中
    *DestinationPixel32bit = (UINT32) ((EfiSourcePixel->
    Red<<16)|(EfiSourcePixel->Green<<8)|
    (EfiSourcePixel->Blue<<0) );
    }
3.4 優(yōu)化BDS階段
    UEFI在BDS階段會連接設(shè)備驅(qū)動程序、創(chuàng)建控制臺并輪詢引導(dǎo)設(shè)備,操作過程非常耗時。而對于嵌入式系統(tǒng)平臺,系統(tǒng)引導(dǎo)時間有嚴(yán)格要求,需要優(yōu)化ARM-UEFI的BDS階段,以縮短引導(dǎo)時間。方案采用的策略是使用平臺配置數(shù)據(jù)庫PCD(Platform Configuration Database)在平臺包的dsc文件(平臺描述文件)中定義控制臺和引導(dǎo)設(shè)備的路徑,并在BDS階段中分兩階段執(zhí)行:首先讀取控制臺設(shè)備路徑,連接控制臺設(shè)備驅(qū)動程序;然后讀取引導(dǎo)設(shè)備路徑,連接指定引導(dǎo)設(shè)備的驅(qū)動程序,再從引導(dǎo)設(shè)備中加載內(nèi)核,并將控制權(quán)移交給操作系統(tǒng)。至此,ARM-UEFI開發(fā)流程基本完成。
    ARM-UEFI在系統(tǒng)耦合、代碼重用方面具有明顯的優(yōu)勢,加速系統(tǒng)開發(fā)的同時,還能減少開發(fā)成本。隨著越來越多的廠商參與到ARM-UEFI標(biāo)準(zhǔn)的制定和實現(xiàn)中來,ARM-UEFI將會成為ARM系統(tǒng)標(biāo)準(zhǔn)的啟動解決方案。
參考文獻
[1] 石浚菁.EFI接口 BIOS 驅(qū)動體系的設(shè)計、實現(xiàn)與應(yīng)用[D]. 南京:南京航空航天大學(xué),2006.
[2] 魏東.UEFI-A new opportunity for preboot firmware on ARM-based system[Z].2013.
[3] TI.OMAP4460 multimedia device silicon revision:technical reference manual[Z].2012.
[4] ZIMMER V,ROTHMAN M,MARISETTY S.Beyond BIOS:developing with the unified extensible firmware interface (2 Edition)[M].Intel Press,2010.
[5] 宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解(第二版)[M].北京:人民郵電出版社,2010.

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