日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ARM64的启动过程之(五):UEFI

發(fā)布時間:2025/3/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ARM64的启动过程之(五):UEFI 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址: http://www.wowotech.net/linux_kenrel/UEFI.html

一、前言

在準(zhǔn)備大刀闊斧進(jìn)入start_kernel之際,我又重新review了一下head.S文件,看看是否有一些遺漏的知識點(diǎn),很不幸,看到了CONFIG_EFI這個配置項。當(dāng)然,在一年前閱讀kernel代碼的時候就了解過相關(guān)的內(nèi)容,但是,做為一個嵌入式工程師總是或多或少對其有些排斥,因此習(xí)慣性的忽略掉CONFIG_EFI相關(guān)的代碼,逃避總不是辦法,在本文中,我們一起來探討ARM64平臺上UEFI相關(guān)的內(nèi)容。

二、背景介紹

1、UEFI是什么鬼?

在個人電腦剛興趣的時代,能夠進(jìn)入BIOS(Basic Input/Output System)解決一些計算機(jī)的問題絕對是高手中的高手(當(dāng)年我就是這么騙到老婆的)。所謂BIOS實際上就是IBM PC兼容機(jī)(多么古老的一個詞匯啊)主板上的固件(firmware),這些固件可以在系統(tǒng)啟動過程中初始化硬件,self test,加載bootloader或者OS kernel,并且能為OS提供一些基礎(chǔ)的服務(wù)。由于各種存在的問題,后來,Intel提出來EFI(Extensible Firmware Interface)來取代BIOS interface。2005年,Intel終止了EFI規(guī)范的開發(fā),替代它的是Unified EFI Forum負(fù)責(zé)的UEFI(Unified Extensible Firmware Interface)specification。UEFI在系統(tǒng)中的位置如下(圖片來自wiki):

隨著PC和服務(wù)器的飛速發(fā)展,軟件和硬件廠商都不斷的研發(fā)各種新的產(chǎn)品來應(yīng)對客戶的需求,在整合成系統(tǒng)的時候,有大量的協(xié)調(diào)的工作需要做,并且是越來越復(fù)雜。為了加快整合,降低設(shè)計復(fù)雜度,需要一個統(tǒng)一的接口標(biāo)準(zhǔn),也就是傳說中的UEFI了。有了UEFI,OS(軟件廠商陣營)和固件(硬件廠商陣營)就有了接口規(guī)格,這樣,大家可以各自進(jìn)行開發(fā),只要符合UEFI規(guī)格就OK了。如果硬件廠商有了創(chuàng)新性的硬件特性,如果不需要修改UEFI接口,那么系統(tǒng)還是可以無縫的銜接,如果需要修改接口,那么提前修改接口規(guī)格,讓參與整個系統(tǒng)構(gòu)建的廠商可以同步前進(jìn)。同樣的,從軟件角度看,如果創(chuàng)新性的軟件算法需要HW的支持,那么可以通過UEFI這樣的接口和硬件廠商陣營進(jìn)行交互,大大加快了將整個系統(tǒng)交付給客戶的時間。

2、UEFI關(guān)ARM什么事?

如果ARM僅僅是將目光放在移動(嵌入式)市場,那么UEFI當(dāng)然不關(guān)ARM什么事情。在嵌入式ARM平臺上,ROM code + bootloader(例如Uboot)+ linux kernel這樣的組合可以很好的工作。但是,在推出ARMv8以及64 bit架構(gòu)的的處理器之后,ARM的野心已經(jīng)不滿足在移動市場上稱王了。不過嵌入式平臺和server或者PC類的平臺是有區(qū)別的:嵌入式平臺往往是高度定制化的平臺,各個硬件模塊都是不可分割的。如果你購買了一個手機(jī),如果你覺得LCD不滿意,是不可能單獨(dú)去市場購買一個LCD屏更換的。而server(PC)類產(chǎn)品則不然,各個模塊是可以更換的。例如:可以自由的去購買一個硬盤或者顯卡進(jìn)行更換。

在移動平臺上,firmware(ROM code)怎么做是自己的事情,只要在應(yīng)用層面提供一致性的接口就OK了,反正硬件以及OS不會更換。來到服務(wù)器平臺,ARM必須和她的合作伙伴(SOC,外圍硬件,OS廠商等等)一起面對這樣的問題:

(1)硬件平臺(firmware)和OS之間的接口如何定義?

(2)如何向OS傳遞硬件信息?

為了讓各個廠商能夠協(xié)同工作,盡快將ARM服務(wù)器推向市場,選擇一個標(biāo)準(zhǔn)讓大家follow是一個不錯的主意。我們以O(shè)S提供商為例描述選擇標(biāo)準(zhǔn)的好處。如果定義了硬件平臺和OS之間的標(biāo)準(zhǔn),OS提供商可以為ARMv8 server發(fā)布一個image而不會因為任何一點(diǎn)硬件平臺的修改就得發(fā)布一個新的OS。因此,ARMv8 server選擇UEFI是很自然的事情了。

3、UEFI如何定義系統(tǒng)的啟動過程?

相信大家對傳統(tǒng)的嵌入式ARM平臺的啟動過程都是有所了解的,系統(tǒng)reset后,各個ARM SOC的從ROM代碼開始執(zhí)行(一般ARM reset之后,PC=0,而ROM缺省地址就是0)。根據(jù)SOC廠商約定的規(guī)則,ROM code會從外部設(shè)備(串口、網(wǎng)絡(luò)、NAND flash、USB磁盤設(shè)備或者其他磁盤設(shè)備)加載linux bootloader,bootloader會收集硬件信息,之后加載linux kernel。在UEFI規(guī)范中定義了BOOT manager,它會根據(jù)保存在NVRAM參數(shù)來決定如何load EFI Application(可能是bootloader或者其他的image file)。EFI Application的格式必須符合PE(Portable Executable )格式。PE是一種二進(jìn)制可執(zhí)行文件的格式(在linux世界中,我們多半熟悉的是ELF格式),由微軟開發(fā),廣泛應(yīng)用在Windows平臺上。

在ARMv8平臺上,firmware中的boot manager可以加載支持UEFI的傳統(tǒng)的bootloader(例如uboot),然后由uboot加載kernel,這樣,kernel其實不必關(guān)心什么UEFI。當(dāng)然這樣有些不直觀,本來OS kernel關(guān)心的那些firmeare提供的各種信息都是由bootloader進(jìn)行轉(zhuǎn)接,嚴(yán)重影響了系統(tǒng)整合的效率(bootloader和kernel是由不同的團(tuán)隊開發(fā)),因此,linux kernel image自身也可以包裝成一個EFI image,由boot manager直接加載,完成啟動過程。

4、PE格式介紹

下面的圖片是一個PE文件格式的示意圖:

PE文件主要由兩部分組成,一部分是為了兼容MS-DOS操作系統(tǒng)而包裝的外殼(灰色block),主要由64B的MZ header和MS-DOS stub代碼區(qū)組成。在遙遠(yuǎn)的MSDOS時代,其可執(zhí)行文件就需要這樣的一個header,MSDOS的program loader就會根據(jù)這個header加載程序運(yùn)行。在Windows時代,微軟提出了PE這種格式文件,它主要是運(yùn)行在windows系列的操作系統(tǒng)中,但是,還需要考慮MSDSO的兼容性(也就是說當(dāng)MSDOS執(zhí)行PE格式的文件也能夠提供足夠的信息讓用戶知道如何處理)。MS-DOS stub block是一段stub code,這段區(qū)域的主要作用是:當(dāng)PE格式的image在MS-DOS下加載運(yùn)行的時候,程序會執(zhí)行這個區(qū)域的代碼(PE的代碼都是for windows的,不可能在DOS下實際執(zhí)行,因此,只能執(zhí)行這些stub程序),當(dāng)然運(yùn)行的結(jié)果僅僅是打印“This program cannot be run in DOS mode”。

另外一個區(qū)域就是實際的PE格式的文件了。主要包括PE header(綠色block)、各種Section header(藍(lán)色block,用于描述各個section)和各個section的實際的Data。各個域的具體含義我們會結(jié)合具體的代碼在下一章描述。

三、代碼分析:

1、MZ header。相關(guān)代碼如下所示:

#ifdef CONFIG_EFI?
efi_head:?
??? add??? x13, x18, #0x16 --------------------------(2)?
??? b??? stext?
#else?
??? b??? stext--------------------------------(1)?
??? .long??? 0??
#endif?
??? .quad??? _kernel_offset_le-------------------------(3)?
??? .quad??? _kernel_size_le??
??? .quad??? _kernel_flags_le?
??? .quad??? 0??????????????? // reserved?
??? .quad??? 0??????????????? // reserved?
??? .quad??? 0??????????????? // reserved?
??? .byte??? 0x41------------Magic number, "ARM\x64"?
??? .byte??? 0x52?
??? .byte??? 0x4d?
??? .byte??? 0x64

#ifdef CONFIG_EFI?
??? .long??? pe_header - efi_head-----------------------(4)?
#else?
??? .word??? 0??????????????? // reserved?
#endif

這里定義了64字節(jié)的kernel image header,應(yīng)對兩種場景:一種是從普通的linux bootloader加載內(nèi)核,另外一種是從UEFI firmware直接加載kernel(定義了CONFIG_EFI ),在這種場景下,這64B的內(nèi)容被解釋為MZ header。

(1)大部分的kernel image header都是相同的,除了第一個8-Byte和最后的4-Byte。沒有定義CONFIG_EFI 是大家都比較熟悉的場景,當(dāng)bootloader完成kernel image的從外設(shè)到RAM的搬移之后會執(zhí)行kernel image的第一條指令。因此,這里是一條跳轉(zhuǎn)到stext的指令。

(2)如果想把自己偽裝成一個UEFI image,kernel需要符合PE格式,下面是一個簡化版本的PE格式的示意圖(僅僅包括部分格式,主要用來說明兼容MS-DOS 相關(guān)部分的內(nèi)容):

上圖中的灰色區(qū)域就是64-Byte的MZ header(對應(yīng)kernel image header的內(nèi)容),當(dāng)然,對于linux kernel而言,它只是偽裝成PE格式而已,只要能夠提供足夠的信息給UEFI firmware的boot manager就OK了。PE格式的文件除了包括一個MZ header,還包括一段MS-DOS stub(上圖中的黃色區(qū)域),當(dāng)然,對于linux kernel image,我們沒有提供這部分的內(nèi)容。這里“add??? x13, x18, #0x16”這條指令沒有任何實際的意義,這條指令的opcode實際上就是MZ signature,用來標(biāo)識這是一個DOS MZ executable的image。

(3)對于UEFI firmware而言,MS-DOS header大部分的區(qū)域都是沒有什么用處的,因此正好可以用來提供信息,以便讓linux的bootloader可以知道如何加載kernel(非UEFI加載的情況)。_kernel_offset_le標(biāo)識加載kernel的位置,如果等于0,表示加載到RAM的0地址的位置上。_kernel_size_le表示需要加載的kernel image的長度,_kernel_flags_le是表示kernel的一些屬性,目前僅僅使用了bit 0,表示kernel的endianess。

(4)在UEFI firmware加載kernel的情況下,需要找到PE header以及各個section的定義了,以便boot manager完成加載kernel image的任務(wù)。在MS-DOS header中(offset是0x3c)有四個字節(jié)指向了PE header,通過它可以找到如何加載內(nèi)核的各種信息。這個過程是這樣的:UEFI firmware的boot manager如果發(fā)現(xiàn)了MZ header,那么就認(rèn)為這是一個符合標(biāo)準(zhǔn)的EFI image,并在0x3c處獲取PE header的位置,并繼續(xù)解析其內(nèi)容以便加載kernel image。

2、PE header相關(guān)代碼

PE header包括三部分的內(nèi)容:PE signature、COFF(Common Object File Format)file header和optional header。PE signature和COFF file header的代碼如下:

pe_header:?
??? .ascii??? "PE" ----------------PE header signanature?
??? .short???? 0?
coff_header:?
??? .short??? 0xaa64----------表示machine type是AArch64?
??? .short??? 2------------該P(yáng)E文件有多少個section?
??? .long??? 0------------該文件的創(chuàng)建時間?
??? .long??? 0------------符號表信息?
??? .long??? 1------------符號表中的符號的數(shù)目?
??? .short??? section_table - optional_header --------optional header的長度?
??? .short??? 0x206---------------Characteristics,具體的含義請查看PE規(guī)格書

上節(jié)我們說過,通過MZ header可以找到PE header,所謂PE header的開始位置實際上就是一個“PE\0\0”的signature,隨后緊接著就是COFF file header,COFF file header具體的定義如下(該表格來自PE specification):

Offset

Size

Field

Description

0

2

Machine

The number that identifies the type of target machine

2

2

NumberOfSections

The number of sections. This indicates the size of the section table, which immediately follows the headers.

4

4

TimeDateStamp

The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created.

8

4

PointerToSymbolTable

The file offset of the COFF symbol table, or zero if no COFF symbol table is present. This value should be zero for an image because COFF debugging information is deprecated.

12

4

NumberOfSymbols

The number of entries in the symbol table. This data can be used to locate the string table, which immediately follows the symbol table. This value should be zero for an image because COFF debugging information is deprecated.

16

2

SizeOfOptionalHeader

The size of the optional header, which is required for executable files but not for object files. This value should be zero for an object file. For a description of the header format, see section 3.4, “Optional Header (Image Only).”

18

2

Characteristics

The flags that indicate the attributes of the file

NumberOfSections定義了PE文件中的section的數(shù)目,對于linux kernel image的PE文件,包括了兩個section,一個是.reloc section(這是EFI application loader需要的,我們這里只是提供了一個dummy版本的.reloc section),另外一個是.text section(整個kernel image)。

通過COFF file header中的SizeOfOptionalHeader域,UEFI firmware可以知道optional header的size。之所以是“optional”主要是因為這些header內(nèi)容不一定會存在。例如:對于object文件,這些header不存在。當(dāng)然,我們是UEFI image file(可執(zhí)行文件),因此這些optional header是必須提供的。optional_header的最開始的域是optional header magic number,用來確定該P(yáng)E文件是PE32還是PE32+格式的。根據(jù)UEFI規(guī)范,UEFI application file應(yīng)該是PE32+格式的。PE32+格式的optional header格式如下:

Offset

Size

Header part

Description

0

28/24

Standard fields

Fields that are defined for all implementations of COFF, including UNIX.

28/24

68/88

Windows-specific fields

Additional fields to support specific features of Windows (for example, subsystems).

96/112

Variable

Data directories

Address/size pairs for special tables that are found in the image file and are used by the operating system (for example, the import table and the export table).

Standard fields包括了如何加載以及如何運(yùn)行的信息。相關(guān)的代碼如下:

optional_header:?
??? .short??? 0x20b??????????????? // PE32+ format?
??? .byte??? 0x02??????????????? // MajorLinkerVersion?
??? .byte??? 0x14??????????????? // MinorLinkerVersion?
??? .long??? _end - stext??????????? // SizeOfCode?
??? .long??? 0??????????????? // SizeOfInitializedData?
??? .long??? 0??????????????? // SizeOfUninitializedData?
??? .long??? efi_stub_entry - efi_head??? // AddressOfEntryPoint?
??? .long??? stext_offset??????????? // BaseOfCode

比較重要的信息包括:代碼段在image file中的偏移(BaseOfCode),正文段的大小(SizeOfCode),data段的大小(SizeOfInitializedData),bss段的大小(SizeOfUninitializedData),加載到memory后入口函數(shù)(AddressOfEntryPoint,對于linux kernel而言,入口函數(shù)是efi_stub_entry)。

Windows-specific fields和Data directories主要被Windows操作系統(tǒng)的linker和loader使用的,這里就不詳述了。

3、Section table和section Data

大家有興趣可以自己查閱PE規(guī)格,我這里就偷懶啦,^_^。

?

四、參考文獻(xiàn):

1、https://lwn.net/Articles/584123/

2、http://www.linaro.org/blog/when-will-uefi-and-acpi-be-ready-on-arm/

3、https://lwn.net/Articles/574439/

4、PE規(guī)格書

5、UEFI規(guī)格書

?

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的ARM64的启动过程之(五):UEFI的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。