FIT image介紹


作者:wowo 發佈於:2016-9-2 21:49 分類:u-boot分析

1. 前言

Linux kernel在ARM架構中引入device tree(全稱是flattened device tree,後續將會以FDT代稱)的時候[1],其實懷揣了一個Unify Kernel的夢想----同一個Image,可以支持多個不同的平臺。隨着新的ARM64架構將FDT列爲必選項,並將和體系結構有關的代碼剝離之後,這個夢想已經接近實現:

在編譯linux kernel的時候,不必特意的指定具體的架構和SOC,只需要告訴kernel本次編譯需要支持哪些板級的platform即可,最終將會生成一個Kernel image,以及多個和具體的板子(哪個架構、哪個SOC、哪個版型)有關的FDT image(dtb文件)。

bootloader在啓動的時候,根據硬件環境,加載不同的dtb文件,即可使linux kernel運行在不同的硬件平臺上,從而達到unify kernel的目標。

本文將基於嵌入式產品中普遍使用的u-boot,以其新的uImage格式(FIT image,Flattened uImage Tree)爲例,介紹達到此目標的步驟,以及背後的思考和意義。

2. Legacy uImage

從u-boot的角度看,它要boot一個二進制文件(例如kernel Image),需要了解該文件的一些信息,例如:

該文件的類型,如kernel image、dtb文件、ramdisk image等等?

該文件需要放在memory的哪個位置(加載地址)?

該文件需要從memory哪個位置開始執行(執行地址)?

該文件是否有壓縮?

該文件是否有一些完整性校驗的信息(如CRC)?

等等

結合“X-010-UBOOT-使用booti命令啓動kernel(Bubblegum-96平臺)”中有關booti的例子,上面信息被隱含在我們的命令行中了,例如:

通過DFU工具,將指定的image文件下載到指定的memory地址,間接的指定了二進制文件加載地址;

booti命令本身,說明加載的文件類型是ARM64平臺的Image文件;

通過booti的參數,可以指定Kernel Image、ramdisk、DTB文件的執行位置;

等等。

不過,這種做法缺點很明顯(總結來說,就是太囉嗦了):

需要往memory中搬不同的二進制文件(Kernel、DTB、ramdisk等);

boot指令(booti等)有比較複雜的參數;

無法靈活地處理二進制文件的校驗、解壓縮等操作;

等等。

爲了解決上述缺點,u-boot自定義了一種Image格式----uImage。最初的時候,uImage的格式比較簡單,就是爲二進制文件加上一個header(具體可參考“include/image.h”中的定義),標示該文件的特性。然後在boot該類型的Image時,從header中讀取所需的信息,按照指示,進行相應的動作即可。這種原始的Image格式,稱作Legacy uImage,其特徵可總結爲:

1)使用mkimage工具(位於u-boot source code的tools/mkimage中)生成。

2)支持OS Kernel Images、RAMDisk Images等多種類型的Image。

3)支持gzip、bzip2等壓縮算法。

4)支持CRC32 checksums。

5)等等。

最後,之所以稱作Legacy,說明又有新花樣了,這種舊的方式,我們就不再過多關注了,擁抱新事物去吧。

3. FIT uImage

3.1 簡介

device tree在ARM架構中普及之後,u-boot也馬上跟進、大力支持,畢竟,美好的Unify kernel的理想,需要bootloader的成全。爲了支持基於device tree的unify kernel,u-boot需要一種新的Image格式,這種格式需要具備如下能力:

1)Image中需要包含多個dtb文件。

2)可以方便的選擇使用哪個dtb文件boot kernel。

綜合上面的需求,u-boot推出了全新的image格式----FIT uImage,其中FIT是flattened image tree的簡稱。是不是覺得FIT和FDT(flattened device tree)有點像?沒錯,它利用了Device Tree Source files(DTS)的語法,生成的image文件也和dtb文件類似(稱作itb),下面我們會詳細描述。

3.2 思路

爲了簡單,我們可以直接把FIT uImage類比爲device tree的dtb文件,其生成和使用過程爲[2]

image source file        mkimage + dtc                           transfer to target 
           +                -----------------------------> image file -----------------------------------> bootm 
image data file(s)

其中image source file(.its)和device tree source file(.dts)類似,負責描述要生成的image file的信息(上面第2章描述的信息)。mkimage和dtc工具,可以將.its文件以及對應的image data file,打包成一個image file。我們將這個文件下載到麼memory中,使用bootm命令就可以執行了。

3.3 image source file的語法

image source file的語法和device tree source file完全一樣(可參考[3][4][5]中的例子),只不過自定義了一些特有的節點,包括images、configurations等。說明如下:

1)images節點

指定所要包含的二進制文件,可以指定多種類型的多個文件,例如multi.its[5]中的包含了3個kernel image、2個ramdisk image、2個fdt image。每個文件都是images下的一個子node,例如:

kernel@2 { 
    description = "2.6.23-denx"; 
    data = /incbin/("./2.6.23-denx.bin.gz"); 
    type = "kernel"; 
    arch = "ppc"; 
    os = "linux"; 
    compression = "gzip"; 
    load = <00000000>; 
    entry = <00000000>; 
    hash@1 { 
        algo = "sha1"; 
    }; 
};

可以包括如下的關鍵字:

description,描述,可以隨便寫;

data,二進制文件的路徑,格式爲----/incbin/("path/to/data/file.bin");

type,二進制文件的類型,"kernel", "ramdisk", "flat_dt"等,具體可參考中[6]的介紹;

arch,平臺類型,“arm”, “i386”等,具體可參考中[6]的介紹;

os,操作系統類型,linux、vxworks等,具體可參考中[6]的介紹;

compression,二進制文件的壓縮格式,u-boot會按照執行的格式解壓;

load,二進制文件的加載位置,u-boot會把它copy對應的地址上;

entry,二進制文件入口地址,一般kernel Image需要提供,u-boot會跳轉到該地址上執行;

hash,使用的數據校驗算法。

2)configurations

可以將不同類型的二進制文件,根據不同的場景,組合起來,形成一個個的配置項,u-boot在boot的時候,以配置項爲單位加載、執行,這樣就可以根據不同的場景,方便的選擇不同的配置,實現unify kernel目標。還以multi.its[5]爲例,

configurations { 
    default = "config@1"; 

     config@1 { 
         description = "tqm5200 vanilla-2.6.23 configuration"; 
         kernel = "kernel@1"; 
         ramdisk = "ramdisk@1"; 
        fdt = "fdt@1"; 
     }; 

     config@2 { 
         description = "tqm5200s denx-2.6.23 configuration"; 
         kernel = "kernel@2"; 
         ramdisk = "ramdisk@1"; 
         fdt = "fdt@2"; 
    }; 

     config@3 { 
         description = "tqm5200s denx-2.4.25 configuration"; 
        kernel = "kernel@3"; 
         ramdisk = "ramdisk@2"; 
     }; 
};

它包含了3種配置,每種配置使用了不同的kernel、ramdisk和fdt,默認配置項由“default”指定,當然也可以在運行時指定。

3.4 Image的編譯和使用

FIT uImage的編譯過程很簡單,根據實際情況,編寫image source file之後(假設名稱爲kernel_fdt.its),在命令行使用mkimage工具編譯即可:

$ mkimage -f kernel_fdt.its kernel_fdt.itb

其中-f指定需要編譯的source文件,並在後面指定需要生成的image文件(一般以.itb爲後綴,例如kernel_fdt.itb)。

Image文件生成後,也可以使用mkimage命令查看它的信息:

$ mkimage -l kernel.itb

最後,我們可以使用dfu工具將生成的.idb文件,下載的memory的某個地址(沒有特殊要求,例如0x100000),然後使用bootm命令即可啓動,步驟包括:

1)使用iminfo命令,查看memory中存在的images和configurations。

2)使用bootm命令,執行默認配置,或者指定配置。

使用默認配置啓動的話,可以直接使用bootm:

bootm 0x100000

選擇其它配置的話,可以指定配置名:

bootm 0x100000#config@2

以上可參考“doc/uImage.FIT/howto.txt[2]”,具體細節我們會在後續的文章中結合實例說明。

4. 總結

本文簡單的介紹了u-boot爲了實現Unify kernel所做的努力,但有一個問題,大家可以思考一下:bootloader的unify怎麼保證呢?

SOC廠家提供(固化、提供二進制文件等)?

格式統一,UEFI?

後面有時間的話,可以追着這個疑問研究研究。

5. 參考文檔

[1] Device Tree(一):背景介紹

[2] doc/uImage.FIT/howto.txt

[3] doc/uImage.FIT/kernel.its

[4] doc/uImage.FIT/kernel_fdt.its

[5] doc/uImage.FIT/multi.its

[6] doc/uImage.FIT/source_file_format.txt

 

原創文章,轉發請註明出處。蝸窩科技,www.wowotech.net




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章