文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào): 0258-7998(2014)04-0011-04
統(tǒng)一可擴(kuò)展固件接口UEFI(Unified Extensible Firmware Interface)在設(shè)計(jì)之初被定義為一種與處理器架構(gòu)無(wú)關(guān)的接口標(biāo)準(zhǔn)。UEFI接口可以采用多種不同的架構(gòu)實(shí)現(xiàn),對(duì)外則都表現(xiàn)為相同的接口。這樣,UEFI就可以最大限度地保證不同設(shè)計(jì)間的代碼重用,其中也包括不同處理器架構(gòu)的平臺(tái)[1]。2009年發(fā)布的UEFI 2.3規(guī)范與傳統(tǒng)的BIOS和UEFI早期版本只支持X86架構(gòu)的處理器相比,最大的改進(jìn)在于支持不同架構(gòu)的處理器平臺(tái),ARM-UEFI成為了規(guī)范的一部分。2013年發(fā)布的UEFI2.4規(guī)范中包含了對(duì)ARM 64位架構(gòu)處理器的支持。這些都表明UEFI對(duì)ARM系統(tǒng)預(yù)引導(dǎo)固件的支持是一個(gè)新的機(jī)遇。使用基于UEFI標(biāo)準(zhǔn)的ARM預(yù)引導(dǎo)固件具有很多優(yōu)越性,UEFI不僅可以實(shí)現(xiàn)不同架構(gòu)平臺(tái)之間的代碼共享,還可以共享標(biāo)準(zhǔn)外設(shè)(UART、Ethernet、USB控制器等)的驅(qū)動(dòng)代碼以及豐富的標(biāo)準(zhǔn)函數(shù)庫(kù)接口。同時(shí),ARM-UEFI的實(shí)現(xiàn)為ARM系統(tǒng)提供了真正獨(dú)立于操作系統(tǒng)的啟動(dòng)解決方案,而其他大多數(shù)現(xiàn)有的ARM啟動(dòng)解決方案(UBoot、Redboot等)都是與其所支持的操作系統(tǒng)相耦合[2]。本文詳述了基于OMAP4460嵌入式平臺(tái)的ARM-UEFI的移植過(guò)程及其外設(shè)的UEFI驅(qū)動(dòng)程序的開發(fā)方法。
1 OMAP4460處理器及平臺(tái)硬件結(jié)構(gòu)
OMAP4460是TI公司專為智能手機(jī)、平板計(jì)算機(jī)以及具有豐富多媒體功能的移動(dòng)終端設(shè)計(jì)的一款高性能、高集成度的嵌入式異構(gòu)多核處理器[3]。該處理器包括2個(gè)Cortex A9內(nèi)核、1個(gè)DSP內(nèi)核、2個(gè)Cortex-M3內(nèi)核、1個(gè)GPU以及豐富的I/O接口資源。在OMAP4460中,嵌入式操作系統(tǒng)運(yùn)行在ARM內(nèi)核上,算法的運(yùn)算工作由DSP內(nèi)核完成,二者通過(guò)TI提供的Codec Engine機(jī)制進(jìn)行數(shù)據(jù)交互,實(shí)現(xiàn)了OMAP4460處理器內(nèi)部多核的協(xié)同工作。
OMAP4460開發(fā)平臺(tái)的硬件結(jié)構(gòu)框圖如圖1所示。硬件平臺(tái)由核心模塊和擴(kuò)展板兩部分組成,核心模塊包括OMAP4460處理器、TWL6032電源管理芯片和1 GB的DRAM;擴(kuò)展板主要實(shí)現(xiàn)外設(shè)接口電路,包括 SD/TF卡接口、UART接口、USB接口、以太網(wǎng)接口和DVI/HDMI接口等。
2 ARM-UEFI引導(dǎo)流程
通用UEFI根據(jù)不同時(shí)間段內(nèi)平臺(tái)初始化所要完成的任務(wù)將操作系統(tǒng)啟動(dòng)過(guò)程按順序分為SEC、PEI、DXE和BDS[4] 4個(gè)階段。其中SEC(安全)階段檢測(cè)并驗(yàn)證固件鏡像的完整性,同時(shí)建立C語(yǔ)言執(zhí)行環(huán)境的堆棧;PEI(預(yù)EFI初始化)階段主要完成內(nèi)存初始化,將固件鏡像加載至內(nèi)存中執(zhí)行;DXE(驅(qū)動(dòng)執(zhí)行環(huán)境)階段完成平臺(tái)初始化,并為操作系統(tǒng)引導(dǎo)提供軟件抽象的服務(wù);BDS(引導(dǎo)設(shè)備選擇)階段從引導(dǎo)設(shè)備中啟動(dòng)操作系統(tǒng),將控制權(quán)交給操作系統(tǒng),完成引導(dǎo)過(guò)程。UEFI上電執(zhí)行順序如圖2所示。
目前ARM平臺(tái)的啟動(dòng)方式多種多樣,Bootloader通常采用多階段的啟動(dòng)過(guò)程[5]。首階段確定啟動(dòng)方式,執(zhí)行必要的初始化操作,加載后續(xù)階段鏡像,后續(xù)階段提供復(fù)雜的功能用于引導(dǎo)操作系統(tǒng)。這種方式既能夠保證Bootloader的功能性,又具有很好的可移植性。因此對(duì)于OMAP4460平臺(tái)的啟動(dòng)方案,采用x-loader + UEFI兩個(gè)啟動(dòng)階段的方式引導(dǎo)操作系統(tǒng)。x-loader作為第一階段的固件,要執(zhí)行時(shí)鐘、內(nèi)存控制器等部分硬件的初始化,并確定OMAP4460平臺(tái)的啟動(dòng)方式,最終將UEFI加載到內(nèi)存中并跳轉(zhuǎn)到指定地址執(zhí)行。內(nèi)存初始化已在x-loader中完成,故UEFI不再實(shí)現(xiàn)SEC以及PEI階段的大部分功能,OMAP4460平臺(tái)ARM-UEFI的PEI階段只需要完成系統(tǒng)內(nèi)存映射和UEFI執(zhí)行環(huán)境堆棧的建立,并執(zhí)行硬件平臺(tái)相關(guān)模塊的初始化配置,之后UEFI跳轉(zhuǎn)進(jìn)入DXE和BDS階段。本方案DXE以及BDS階段的執(zhí)行策略和實(shí)現(xiàn)功能與通用UEFI固件基本相同:在DXE階段加載所有的驅(qū)動(dòng)程序,完成平臺(tái)初始化工作;在BDS階段創(chuàng)建控制臺(tái),設(shè)置內(nèi)核的啟動(dòng)參數(shù),加載引導(dǎo)設(shè)備的內(nèi)核鏡像到內(nèi)存中執(zhí)行。OMAP4460平臺(tái)ARM-UEFI引導(dǎo)流程圖如圖3所示。
3 ARM-UEFI開發(fā)與移植
3.1 移植x-loader
OMAP4460處理器內(nèi)部的SRAM只有64 KB,相對(duì)于第二階段UEFI固件鏡像的數(shù)百kB而言過(guò)小,OMAP4460處理器無(wú)法加載UEFI固件鏡像到SRAM運(yùn)行,而需要使用外部DRAM加載。因此,本方案采用基于精簡(jiǎn)UBoot基本代碼的x-loader作為第一階段的引導(dǎo)固件。由于SRAM容量的限制,x-loader的初始化操作只針對(duì)必要的硬件模塊,如引腳復(fù)用和功能設(shè)置、時(shí)鐘、內(nèi)存控制器等。初始化操作的目的是將UEFI固件鏡像從OMAP446平臺(tái)的SD卡中加載到DRAM中,然后跳轉(zhuǎn)到入口地址執(zhí)行。
x-loader的入口位于Start.s文件,Start.s首先執(zhí)行CPU的基本初始化,包括禁止Cache和TLB、關(guān)閉中斷等。其次執(zhí)行兩個(gè)跳轉(zhuǎn)模塊cpu_init_crit和start_armboot,cpu_init_crit模塊跳轉(zhuǎn)到s_init()函數(shù)執(zhí)行,s_init()中調(diào)用了3個(gè)函數(shù)實(shí)現(xiàn)平臺(tái)基本初始化:set_muxconf_regs()實(shí)現(xiàn)處理器芯片引腳復(fù)用和功能設(shè)置;ddr_init()實(shí)現(xiàn)內(nèi)存初始化;prcm_init()則實(shí)現(xiàn)平臺(tái)各個(gè)模塊時(shí)鐘的初始化配置。這3個(gè)函數(shù)的修改要針對(duì)OMAP4460平臺(tái)的具體硬件結(jié)構(gòu)以及引導(dǎo)過(guò)程中所使用到的模塊進(jìn)行。start_armboot則是在內(nèi)存初始化完成且堆棧建立以后執(zhí)行,程序跳轉(zhuǎn)至lib\board.c文件的start_armboot()函數(shù),實(shí)現(xiàn)加載UEFI固件鏡像到指定內(nèi)存位置的過(guò)程。第二階段UEFI固件鏡像的入口地址定義為CFG_LOADADDR,它必須與OAMP4460平臺(tái)UEFI固件鏡像的起始地址相同,后者由固件的fdf(Flash描述文件)指定。最終x-loader使用函數(shù)指針的方式實(shí)現(xiàn)x-loader到UEFI的跳轉(zhuǎn),代碼如下:
((init_fnc_t *)CFG_LOADADDR)();
3.2 移植PEI階段代碼
如上所述,OMAP4460平臺(tái)的ARM-UEFI沒(méi)有SEC階段,且PEI階段實(shí)現(xiàn)功能與通用UEFI的PEI階段也有所不同,PEI階段不再需要完成內(nèi)存初始化任務(wù),而是側(cè)重于系統(tǒng)平臺(tái)信息、內(nèi)存資源的收集過(guò)程,并通過(guò)信息描述塊HOB傳遞給DXE階段。OMAP4460平臺(tái)的PEI階段的主體實(shí)現(xiàn)代碼位于ArmPlatformPkg\PrePi.c的PrePiMain()函數(shù)中,該函數(shù)主要實(shí)現(xiàn)了3個(gè)功能: PEI階段的串口調(diào)試信息輸出;調(diào)用PEI模塊MemoryPeim實(shí)現(xiàn)MMU的初始化,建立UEFI系統(tǒng)堆棧,并將這些系統(tǒng)資源建立成HOB傳遞給后續(xù)階段;調(diào)用PlatformPeim實(shí)現(xiàn)一些硬件模塊的初始化和配置。
PEI階段的串口輸出是通過(guò)調(diào)用SerialPortLib中的庫(kù)函數(shù)實(shí)現(xiàn)的。SerialPortLib主要包含兩部分:串口初始化函數(shù)和串口讀寫函數(shù)。初始化函數(shù)SerialPortInitialize()首先配置平臺(tái)UART接口的引腳復(fù)用,使能時(shí)鐘;然后再設(shè)置串口通信模式,配置串口通信的波特率等參數(shù);最后使能FIFO,完成UART接口的初始化。而讀寫函數(shù)則是通過(guò)輪詢標(biāo)志位的方式判斷FIFO是否為空,再按字節(jié)讀寫FIFO。PEI階段調(diào)試信息輸出樣例代碼如下:
SerialPortInitialize (); //UART模塊初始化
CharCount = AsciiSPrint (Buffer,sizeof(Buffer),"UEFI \n");
SerialPortWrite((UINT8 *) Buffer, CharCount);//數(shù)據(jù)輸出
PlatformPeim中再次實(shí)現(xiàn)了平臺(tái)模塊的初始化,目的是向后兼容未來(lái)采用通用UEFI引導(dǎo)方式的ARM平臺(tái)的PEI階段所要實(shí)現(xiàn)的完整功能。PlatformPeim中包括了3個(gè)函數(shù):PadConfiguration()、ClockInit()和GpmcInit()。PadConfiguration()函數(shù)和ClockInit()函數(shù)都通過(guò)操作宏定義的方式實(shí)現(xiàn)平臺(tái)功能。PadConfiguration()完成平臺(tái)所有引腳復(fù)用功能的設(shè)置。ClockInit()完成平臺(tái)所有模塊時(shí)鐘的配置,并使能部分模塊時(shí)鐘。這種實(shí)現(xiàn)方式的好處是有統(tǒng)一的啟動(dòng)代碼,開發(fā)DXE階段的外設(shè)驅(qū)動(dòng)程序時(shí)不需要再配置外設(shè)接口的引腳和時(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ù)實(shí)現(xiàn)16位寄存器的寫功能,通過(guò)獲取指定引腳寄存器的地址,寫入指定的配置屬性,完成引腳復(fù)用功能的配置。
GpmcInit()則用于配置通用存儲(chǔ)控制器GPMC的片選信號(hào),樣例代碼如下:
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ū)動(dòng)程序
EDK II開發(fā)工具是基于X86平臺(tái)的PCI總線結(jié)構(gòu)實(shí)現(xiàn)的。當(dāng)用其開發(fā)OMAP4460平臺(tái)ARM-UEFI時(shí),需要重構(gòu)平臺(tái)的接口控制器驅(qū)動(dòng)程序,為上層提供標(biāo)準(zhǔn)的UEFI服務(wù)。同時(shí),完整移植處于上層并滿足工業(yè)標(biāo)準(zhǔn)的接口驅(qū)動(dòng)程序,從而實(shí)現(xiàn)對(duì)原有代碼的重用,加快ARM-UEFI的開發(fā)。
以顯示驅(qū)動(dòng)程序的開發(fā)為例,在OMAP4460平臺(tái)上使用HDMI作為ARM-UEFI引導(dǎo)時(shí)的顯示接口。ARM-UEFI系統(tǒng)中只需實(shí)現(xiàn)HDMI顯示驅(qū)動(dòng)程序即可實(shí)現(xiàn)顯示控制臺(tái)的輸出。HDMI顯示驅(qū)動(dòng)程序?qū)崿F(xiàn)圖像輸出協(xié)議EFI_GRAPHICS_OUTPUT_PROTOCOL,該協(xié)議提供服務(wù)接口給圖像控制臺(tái)驅(qū)動(dòng)程序GraphicsConsoledxe, 再由該驅(qū)動(dòng)程序?qū)崿F(xiàn)簡(jiǎn)單文本輸出協(xié)議EFI_SIMPLE_TEXTOUT_
PROTOCOL,最后由虛擬控制臺(tái)驅(qū)動(dòng)程序Consoleplitterdxe將所有掛載簡(jiǎn)單文本輸出協(xié)議的設(shè)備句柄統(tǒng)一掛載到虛擬控制臺(tái)輸出句柄ConOut上,由ConOut實(shí)現(xiàn)控制臺(tái)的輸出,OMAP4460平臺(tái)UEFI圖形控制臺(tái)結(jié)構(gòu)圖如圖4所示。
HDMI顯示驅(qū)動(dòng)程序包括三部分:顯示模塊硬件初始化、顯示模式的配置以及圖像的顯示。其中GOP協(xié)議的函數(shù)接口實(shí)現(xiàn)顯示模式配置與圖像的顯示,QueryMode、SetMode兩個(gè)接口實(shí)現(xiàn)分辨率、顏色及頻率的配置,Blt接口實(shí)現(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ū)動(dòng)程序的入口函數(shù)中執(zhí)行,具體初始化過(guò)程分為3步:
(1)使能ESD保護(hù)芯片TPD12S016的供電及熱插拔引腳功能,檢測(cè)HDMI接口的HDMI_HPD引腳狀態(tài),檢測(cè)是否接入顯示器。
(2)使能顯示子系統(tǒng)的功能時(shí)鐘和接口時(shí)鐘,同時(shí)使能HDMI物理層的時(shí)鐘。
(3)申請(qǐng)圖像管道內(nèi)存,并記錄基地址。
HDMI接口顯示模式的配置分為顯示子系統(tǒng)和HDMI物理層兩部分的顯示模式配置,由QueryMode和SetMode接口函數(shù)實(shí)現(xiàn)。QueryMode通過(guò)HDMI的I2C接口讀取顯示器的擴(kuò)展顯示標(biāo)識(shí)數(shù)據(jù)EDID(Extended Display Identification Data),EDID中包含了監(jiān)視器時(shí)序、定時(shí)和分辨率等性能參數(shù),使用這些參數(shù)填充Mode結(jié)構(gòu)體,再將Mode作為改變值參數(shù)傳遞給SetMode接口,由SetMode完成顯示子系統(tǒng)和HDMI物理層中顯示輸出時(shí)鐘頻率、圖像分辨率、位寬等寄存器變化值的寫入和重新使能,從而更新顯示分辨率、圖像格式以及顏色模式等參數(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ù),通過(guò)MmioWrite32()函數(shù)將值寫入寄存器,完成配置。
圖像的顯示由GOP協(xié)議的Blt接口函數(shù)實(shí)現(xiàn),Blt函數(shù)首先調(diào)用LcdPlatformGetBpp()函數(shù)獲取平臺(tái)設(shè)置的圖像格式以及位寬,再計(jì)算原圖像像素和目標(biāo)管道內(nèi)存的地址,然后將EFI圖像像素轉(zhuǎn)換成顯示器設(shè)置的像素格式,宏定義LCD_BITS_PER_PIXEL_24表示圖像格式為xRGB24,即每個(gè)像素占用32位,低24位按照藍(lán)綠紅各8位排列,最高8位為空。最后將轉(zhuǎn)換完成的像素?cái)?shù)據(jù)存放在計(jì)算好的目標(biāo)管道內(nèi)存中,使用圖像管道將圖像數(shù)據(jù)輸出。具體代碼如下:
LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
if(BitsPerPixel== LCD_BITS_PER_PIXEL_24)
{
// 計(jì)算原地址和目標(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階段會(huì)連接設(shè)備驅(qū)動(dòng)程序、創(chuàng)建控制臺(tái)并輪詢引導(dǎo)設(shè)備,操作過(guò)程非常耗時(shí)。而對(duì)于嵌入式系統(tǒng)平臺(tái),系統(tǒng)引導(dǎo)時(shí)間有嚴(yán)格要求,需要優(yōu)化ARM-UEFI的BDS階段,以縮短引導(dǎo)時(shí)間。方案采用的策略是使用平臺(tái)配置數(shù)據(jù)庫(kù)PCD(Platform Configuration Database)在平臺(tái)包的dsc文件(平臺(tái)描述文件)中定義控制臺(tái)和引導(dǎo)設(shè)備的路徑,并在BDS階段中分兩階段執(zhí)行:首先讀取控制臺(tái)設(shè)備路徑,連接控制臺(tái)設(shè)備驅(qū)動(dòng)程序;然后讀取引導(dǎo)設(shè)備路徑,連接指定引導(dǎo)設(shè)備的驅(qū)動(dòng)程序,再?gòu)囊龑?dǎo)設(shè)備中加載內(nèi)核,并將控制權(quán)移交給操作系統(tǒng)。至此,ARM-UEFI開發(fā)流程基本完成。
ARM-UEFI在系統(tǒng)耦合、代碼重用方面具有明顯的優(yōu)勢(shì),加速系統(tǒng)開發(fā)的同時(shí),還能減少開發(fā)成本。隨著越來(lái)越多的廠商參與到ARM-UEFI標(biāo)準(zhǔn)的制定和實(shí)現(xiàn)中來(lái),ARM-UEFI將會(huì)成為ARM系統(tǒng)標(biāo)準(zhǔn)的啟動(dòng)解決方案。
參考文獻(xiàn)
[1] 石浚菁.EFI接口 BIOS 驅(qū)動(dòng)體系的設(shè)計(jì)、實(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ū)動(dòng)開發(fā)詳解(第二版)[M].北京:人民郵電出版社,2010.