0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FIT Image起源及制作方法

lhl545545 ? 來源:嵌入式與Linux那些事 ? 作者:嵌入式與Linux那些 ? 2022-09-05 14:23 ? 次閱讀

secure boot 和FIT Image是前段時間接觸到的,其實(shí)早就該總結(jié)下了,奈何懶癌犯了,拖了好久才寫出來。

之前也有人問我,工作后最大的感受是什么?我的回答是:“快速學(xué)習(xí)”。

嵌入式來講,大多數(shù)應(yīng)屆生在校期間可能都沒做過完整的項(xiàng)目,僅憑在校期間學(xué)習(xí)的內(nèi)容很難勝任公司的要求。

就底層驅(qū)動來講,雖然我之前也學(xué)習(xí)過韋東山老師的上s3c2440的課程,但是到了公司才發(fā)現(xiàn),這些內(nèi)容其實(shí)都已經(jīng)過時了。

但并不是說這些內(nèi)容都沒有必要去學(xué)習(xí)了。在學(xué)習(xí)的過程中,認(rèn)為最重要的是培養(yǎng)我們的自學(xué)能力。

很多初學(xué)者在剛開始學(xué)習(xí)時,可能就敗在了搭建環(huán)境上。搭建環(huán)境時遇到問題不知道怎么辦?

我們?nèi)粘i_發(fā)中遇到的90%的問題,在網(wǎng)上都有人遇到過,也有相應(yīng)的解決辦法。學(xué)會利用bing,google,stackoverflow等搜索工具是一項(xiàng)很重要的技能。

如果遇到了網(wǎng)上沒有的問題怎么辦?軟件問題要先搞清楚原理,再去看代碼邏輯。硬件問題看官方手冊。像Linux kernel,ARM等都提供了完善的手冊,大部分問題在手冊中都有相應(yīng)說明。

好了,扯遠(yuǎn)了。下面回歸正題。

本文主要介紹了FIT Image起源,制作方法,its的語法結(jié)構(gòu),bootm 啟動FIT Image的方式。

本文這篇文章是對后面介紹的secure boot做鋪墊。ARMv8 secure boot一種實(shí)現(xiàn)的方式就是利用了FIT Image的特性。

zImage,uImage, Legacy uImage 和 FIT uImage

內(nèi)核經(jīng)過編譯后,會生成一個elf的可執(zhí)行程序,叫vmlinux,這個就是原始的未經(jīng)任何處理加工的原版內(nèi)核elf文件。不過,最終燒寫在嵌入式設(shè)備上的并不是這個文件。而是經(jīng)過objcopy工具加工后的專門用于燒錄的鏡像格式Image。

原則上Image就可以直接被燒錄到Flash上進(jìn)行啟動執(zhí)行,但linux的內(nèi)核開發(fā)者覺得Image還是太大了,因此對Image進(jìn)行了壓縮,并且在Image壓縮后的文件的前端附加了一部分解壓縮代碼,構(gòu)成了一個壓縮格式的鏡像文件就叫zImage。

解壓的時候,通過zImage鏡像頭部的解壓縮代碼進(jìn)行自解壓,然后執(zhí)行解壓出來的內(nèi)核鏡像。

Uboot要正確啟動Linux內(nèi)核,就需要知道內(nèi)核的一些信息,比如鏡像的類型(kernel image,dtb,ramdisk image),鏡像在內(nèi)存的位置,鏡像的鏈接地址,鏡像文件是否有壓縮等等。

Uboot為了拿到這些信息,發(fā)明了一種內(nèi)核格式叫uImage,也叫Legacy uImage。uImage是由zImage加工得到的,uboot中有一個工具mkimage,該工具會給zImage加一個64字節(jié)的header,將啟動內(nèi)核所需的信息存儲在header中。uboot啟動后,從header中讀取所需的信息,按照指示,進(jìn)行相應(yīng)的動作即可。

header格式可以參考:include/image.h。mkimage源碼在tools/mkimage

FIT image的來源

有了Legacy uImage后,為什么又搞出來一個FIT uImage呢?

在Linus Torvalds 看來,內(nèi)核中arch/arm/mach-xxx充斥著大量的垃圾代碼。因?yàn)閮?nèi)核并不關(guān)心板級細(xì)節(jié),比如板上的platform設(shè)備、resource、i2c_board_info、spi_board_info等等。大家有興趣可以看下s3c2410的板級目錄,代碼量在數(shù)萬行。

因此,ARM社區(qū)引入了Device Tree,使用Device Tree后,許多硬件的細(xì)節(jié)可以直接透過它傳遞給Linux,而不再需要在kernel中進(jìn)行大量的冗余編碼。

為了更好的支持單個固件的通用性,Uboot也需要對這種uImage固件進(jìn)行支持。FIT uImage中加入多個dtb文件 和ramdisk文件,當(dāng)然如果需要的話,同樣可以支持多個kernel文件。

內(nèi)核中的FDT全程為flattened device tree,F(xiàn)IT全稱叫flattened image tree。FIT利用了Device Tree Source files(DTS)的語法,生成的Image文件也和dtb文件類似(稱作itb)。

這樣的目的就是能夠使同一個uImage能夠在Uboot中選擇特定的kernel/dtb和ramdisk進(jìn)行啟動了,達(dá)成一個uImage可以通用多個板型的目的。

制作FIT Image

制作FIT Image需要用到兩個工具,mkimage和的dtc。dtc要導(dǎo)入到環(huán)境變量$PATH中,mkimage會調(diào)用dtc。

mkimage的輸入為 image source file,它定義了啟動過程中image的各種屬性,擴(kuò)展名為.its。its只是描述了Image的屬性,實(shí)際的Image data 是在uImage中,具體路徑由its指定。

80707f44-2cd0-11ed-ba43-dac502259ad0.png

如下是kernel 的its文件,后面會介紹各項(xiàng)內(nèi)容的含義。

/*
*SimpleU-BootuImagesourcefilecontainingasinglekernel
*/

/dts-v1/;

/{
description="SimpleimagewithsingleLinuxkernel";
#address-cells=<1>;

images{
kernel@1{
description="VanillaLinuxkernel";
data=/incbin/("./vmlinux.bin.gz");#Imagedata具體路徑
type="kernel";
arch="ppc";
os="linux";
compression="gzip";
load=<00000000>;
entry=<00000000>;
hash@1{
algo="crc32";
};
hash@2{
algo="sha1";
};
};
};

configurations{
default="config@1";
config@1{
description="BootLinuxkernel";
kernel="kernel@1";
};
};
};

mkimage的輸出是一個后綴為.itb的二進(jìn)制文件,包含了所有需要的數(shù)據(jù)(kernel,dtb,ramdisk)。itb文件制作好之后,就可以直接加載到嵌入式設(shè)備上,通過bootm命令啟動。

總結(jié)下制作FIT Image的4個必要文件:

mkimage,

dtc

its(image source file (*.its))

image data file(s)。

its語法結(jié)構(gòu)

uImage Tree 的根節(jié)點(diǎn)結(jié)構(gòu)

/oimage-tree
|-description="imagedescription"
|-timestamp=<12399321>
|-#address-cells=<1>
|
oimages
||
|oimage@1{...}
|oimage@2{...}
|...
|
oconfigurations
|-default="conf@1"
|
oconf@1{...}
oconf@2{...}
...

description:描述uImage的文本。

timestamp:修改Image鏡像的時間,由mkimage工具自動生成。在security boot中,timestamp不同也會被認(rèn)為是不同的Image。

images:子鏡像,如kernel Image,ramdisk Image。

configurations:配置項(xiàng)節(jié)點(diǎn),可以將不同類型的二進(jìn)制文件,根據(jù)不同的場景,組合起來,形成一個個的配置項(xiàng)。u-boot在boot的時候,以配置項(xiàng)為單位加載、執(zhí)行,這樣就可以根據(jù)不同的場景,方便的選擇不同的配置。

'/images' node

該節(jié)點(diǎn)中描述了Image鏡像必要的信息.

oimage@1
|-description="componentsub-imagedescription"
|-data=/incbin/("path/to/data/file.bin")
|-type="sub-imagetypename"
|-arch="ARCHname"
|-os="OSname"
|-compression="compressionname"
|-load=<00000000>
|-entry=<00000000>
|
ohash@1{...}
ohash@2{...}
...

description:子鏡像的文本描述,可以隨便寫。

type:子鏡像的類型,比如standalone,kernel,ramdisk,firmware等等。

data:包含該節(jié)點(diǎn)二進(jìn)制文件的路徑。

compression:壓縮方式,比如none,gzip,bzip2。

os:操作系統(tǒng)的名稱,如solaris,uboot,qnx等。

arch:平臺架構(gòu),如arm,mips,i386等。

entry:二進(jìn)制文件入口地址,即鏈接地址。

load:二進(jìn)制文件的加載位置。

hash@1:鏡像使用的校驗(yàn)算法,如sha256,crc32等。

Hash nodes

ohash@1
|-algo="hashorchecksumalgorithmname"
|-value=[hashorchecksumvalue]

algo:算法名稱,如crc32,md5,sha256等。

value:算法校驗(yàn)值,即algo計算后的數(shù)值。

'/configurations' node

oconfigurations
|-default="defaultconfigurationsub-nodeunitname"
|
oconfig@1{...}
oconfig@2{...}
...

default:默認(rèn)的子節(jié)點(diǎn)的配置

config@1: 該配置具體使用那些kernel Image,ramdisk Image等。

Configuration nodes

oconfig@1
|-description="configurationdescription"
|-kernel="kernelsub-nodeunitname"
|-ramdisk="ramdisksub-nodeunitname"
|-fdt="fdtsub-nodeunit-name"[,"fdtoverlaysub-nodeunit-name",...]
|-fpga="fpgasub-nodeunit-name"
|-loadables="loadablessub-nodeunit-name"

description:該配置的名稱。

kernel:鏡像類型為kernel的單元的名稱。

ramdisk:鏡像類型為ramdisk的單元的名稱。

fdt:鏡像類型為fdt的單元的名稱。

loadables:額外的可加載的二進(jìn)制文件的列表,U-Boot將在給定的起始地址加載每個二進(jìn)制文件。

舉例

如下是一個有多種kernels, ramdisks and FDT blobs鏡像多套配置的its文件。它包含了3種配置,每種配置使用了不同的kernel、ramdisk和fdt,默認(rèn)配置項(xiàng)由“default”指定,當(dāng)然也可以在運(yùn)行時指定。

/*
*U-BootuImagesourcefilewithmultiplekernels,ramdisksandFDTblobs
*/

/dts-v1/;

/{
description="Variouskernels,ramdisksandFDTblobs";
#address-cells=<1>;

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

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";
};
};

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

ramdisk@1{
description="eldk-4.2-ramdisk";
data=/incbin/("./eldk-4.2-ramdisk");
type="ramdisk";
arch="ppc";
os="linux";
compression="gzip";
load=<00000000>;
entry=<00000000>;
hash@1{
algo="sha1";
};
};

ramdisk@2{
description="eldk-3.1-ramdisk";
data=/incbin/("./eldk-3.1-ramdisk");
type="ramdisk";
arch="ppc";
os="linux";
compression="gzip";
load=<00000000>;
entry=<00000000>;
hash@1{
algo="crc32";
};
};

fdt@1{
description="tqm5200-fdt";
data=/incbin/("./tqm5200.dtb");
type="flat_dt";
arch="ppc";
compression="none";
hash@1{
algo="crc32";
};
};

fdt@2{
description="tqm5200s-fdt";
data=/incbin/("./tqm5200s.dtb");
type="flat_dt";
arch="ppc";
compression="none";
load=<00700000>;
hash@1{
algo="sha1";
};
};

};

configurations{
default="config@1";

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

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

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

FIT Image的編譯和啟動

在服務(wù)器上,可以使用mkimage工具制作 FIT Image。

如下是kernel_fdt.its,下面將使用該文件制作itb。

/*
*SimpleU-BootuImagesourcefilecontainingasinglekernelandFDTblob
*/

/dts-v1/;

/{
description="SimpleimagewithsingleLinuxkernelandFDTblob";
#address-cells=<1>;

images{
kernel@1{
description="VanillaLinuxkernel";
data=/incbin/("./vmlinux.bin.gz");
type="kernel";
arch="ppc";
os="linux";
compression="gzip";
load=<00000000>;
entry=<00000000>;
hash@1{
algo="crc32";
};
hash@2{
algo="sha1";
};
};
fdt@1{
description="FlattenedDeviceTreeblob";
data=/incbin/("./target.dtb");
type="flat_dt";
arch="ppc";
compression="none";
hash@1{
algo="crc32";
};
hash@2{
algo="sha1";
};
};
};

configurations{
default="conf@1";
conf@1{
description="BootLinuxkernelwithFDTblob";
kernel="kernel@1";
fdt="fdt@1";
};
};
};

$mkimage-fkernel_fdt.itskernel_fdt.itb
DTC:dts->dtbonfile"kernel_fdt.its"
$
$mkimage-lkernel_fdt.itb
FITdescription:SimpleimagewithsingleLinuxkernelandFDTblob
Created:TueMar1116222008
Image0(kernel@1)
Description:VanillaLinuxkernel
Type:KernelImage
Compression:gzipcompressed
DataSize:1092037Bytes=1066.44kB=1.04MB
Architecture:PowerPC
OS:Linux
LoadAddress:0x00000000
EntryPoint:0x00000000
Hashalgo:crc32
Hashvalue:2c0cc807
Hashalgo:sha1
Hashvalue:264b59935470e42c418744f83935d44cdf59a3bb
Image1(fdt@1)
Description:FlattenedDeviceTreeblob
Type:FlatDeviceTree
Compression:uncompressed
DataSize:16384Bytes=16.00kB=0.02MB
Architecture:PowerPC
Hashalgo:crc32
Hashvalue:0d655d71
Hashalgo:sha1
Hashvalue:25ab4e15cd4b8a5144610394560d9c318ce52def
DefaultConfiguration:'conf@1'
Configuration0(conf@1)
Description:BootLinuxkernelwithFDTblob
Kernel:kernel@1
FDT:fdt@1

在當(dāng)前目錄下就可以找到kernel_fdt.itb,itb文件就可以加載到設(shè)備上啟動。

>tftp900000/path/to/tftp/location/kernel_fdt.itb
UsingFECdevice
TFTPfromserver192.168.1.1;ourIPaddressis192.168.160.5
Filename'/path/to/tftp/location/kernel_fdt.itb'.
Loadaddress:0x900000
Loading:#################################################################
###########
done
Bytestransferred=1109776(10ef10hex)
=>iminfo

##CheckingImageat00900000...
FITimagefound
FITdescription:SimpleimagewithsingleLinuxkernelandFDTblob
Created:2008-03-111522UTC
Image0(kernel@1)
Description:VanillaLinuxkernel
Type:KernelImage
Compression:gzipcompressed
DataStart:0x009000ec
DataSize:1092037Bytes=1MB
Architecture:PowerPC
OS:Linux
LoadAddress:0x00000000
EntryPoint:0x00000000
Hashalgo:crc32
Hashvalue:2c0cc807
Hashalgo:sha1
Hashvalue:264b59935470e42c418744f83935d44cdf59a3bb
Image1(fdt@1)
Description:FlattenedDeviceTreeblob
Type:FlatDeviceTree
Compression:uncompressed
DataStart:0x00a0abdc
DataSize:16384Bytes=16kB
Architecture:PowerPC
Hashalgo:crc32
Hashvalue:0d655d71
Hashalgo:sha1
Hashvalue:25ab4e15cd4b8a5144610394560d9c318ce52def
DefaultConfiguration:'conf@1'
Configuration0(conf@1)
Description:BootLinuxkernelwithFDTblob
Kernel:kernel@1
FDT:fdt@1
=>bootm
##BootingkernelfromFITImageat00900000...
Using'conf@1'configuration
Trying'kernel@1'kernelsubimage
Description:VanillaLinuxkernel
Type:KernelImage
Compression:gzipcompressed
DataStart:0x009000ec
DataSize:1092037Bytes=1MB
Architecture:PowerPC
OS:Linux
LoadAddress:0x00000000
EntryPoint:0x00000000
Hashalgo:crc32
Hashvalue:2c0cc807
Hashalgo:sha1
Hashvalue:264b59935470e42c418744f83935d44cdf59a3bb
VerifyingHashIntegrity...crc32+sha1+OK
UncompressingKernelImage...OK
##FlattenedDeviceTreefromFITImageat00900000
Using'conf@1'configuration
Trying'fdt@1'FDTblobsubimage
Description:FlattenedDeviceTreeblob
Type:FlatDeviceTree
Compression:uncompressed
DataStart:0x00a0abdc
DataSize:16384Bytes=16kB
Architecture:PowerPC
Hashalgo:crc32
Hashvalue:0d655d71
Hashalgo:sha1
Hashvalue:25ab4e15cd4b8a5144610394560d9c318ce52def
VerifyingHashIntegrity...crc32+sha1+OK
Bootingusingthefdtblobat0xa0abdc
LoadingDeviceTreeto007fc000,end007fffff...OK
[0.000000]Usinglite5200machinedescription
[0.000000]Linuxversion2.6.24-rc6-gaebecdfc(m8@hekate)(gccversion4.0.0(DENXELDK4.14.0.0))#1SatJan121548CET2008

bootm啟動不同的配置

對于FIT Image,bootm有多種啟動方式。

1.bootm
2.bootm[]:
3.bootm[]#[#]:[]:
5.bootm[]:[]:[]:
6.bootm[]:[]:
7.bootm[]:-[]:
8.bootm[]:-

對于有多種鏡像,多套配置的itb,都是以configurations 中default 指定的配置啟動。

bootm200000

也可以手動指定使用那套配置

bootm200000#cfg@1

也可以手動搭配不同的鏡像節(jié)點(diǎn)啟動

bootm200000:kernel@1800000:ramdisk@2
bootm200000:kernel@1800000:ramdisk@1800000:fdt@1
bootm200000:kernel@2200000:ramdisk@2600000
bootm200000:kernel@2-200000:fdt@1

如果bootm的時候不指定地址,則會使用CONFIG_SYS_LOAD_ADDR配置的地址。

總結(jié)

本文對FIT Image作了簡單的介紹,更詳細(xì)的內(nèi)容可以參考官方文檔。后面有時間會動手制作一個FIT Image在板子上跑下。

FIT Image可以兼容于多種板子,而無需重新進(jìn)行編譯燒寫。對于有多個kernel節(jié)點(diǎn)或者fdt節(jié)點(diǎn)等等,兼容性更強(qiáng)。同時,可以有多種configurations,來對kernel、fdt、ramdisk來進(jìn)行組合。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207914
  • 軟件
    +關(guān)注

    關(guān)注

    69

    文章

    4570

    瀏覽量

    86699
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4671

    瀏覽量

    67767

原文標(biāo)題:secure boot (一)FIT Image

文章出處:【微信號:嵌入式與Linux那些事,微信公眾號:嵌入式與Linux那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    發(fā)燒音箱制作方法訣要

    發(fā)燒音箱制作方法訣要
    發(fā)表于 08-20 20:46

    加濕器制作方法

    本帖最后由 eehome 于 2013-1-5 10:03 編輯 麻煩各位前輩,有沒有知道家用加濕器的制作方法的,我想學(xué)習(xí)一下,謝謝!
    發(fā)表于 11-19 21:38

    LED顯示屏制作方法教程

             LED顯示屏制作方法
    發(fā)表于 02-15 11:35 ?0次下載

    網(wǎng)線水晶頭制作方法

    水晶頭制作方法???? 雙絞線制作工具?&
    發(fā)表于 09-03 23:04 ?4919次閱讀

    雙絞線的制作方法過程

    雙絞線的制作方法過程 【實(shí)訓(xùn)目的】(1)掌握雙絞線和RJ-45接頭的排列,做交叉線和直連線。(2)學(xué)會雙絞線制作方法。(3)
    發(fā)表于 12-07 13:43 ?9913次閱讀

    方波逆變器的制作方法

    本文依據(jù)逆變電源的基本原理,利用對現(xiàn)有資料的分析推導(dǎo),提出了一種方波逆變器的制作方法并加以調(diào)試。
    發(fā)表于 04-21 10:58 ?1.3w次閱讀
    方波逆變器的<b class='flag-5'>制作方法</b>

    光立方制作方法

    光立方制作方法詳情
    發(fā)表于 12-09 16:25 ?16次下載

    LED顯示屏制作方法

    LED顯示屏制作方法
    發(fā)表于 02-08 02:17 ?29次下載

    LED光立方焊接制作方法

    制作方法
    發(fā)表于 09-04 09:20 ?0次下載

    倒車?yán)走_(dá)的制作方法

    本文圖文介紹了倒車?yán)走_(dá)的制作方法。
    發(fā)表于 11-15 15:39 ?13次下載

    天線結(jié)構(gòu)及天線的制作方法的詳解

    本文詳解了天線結(jié)構(gòu)及天線的制作方法。
    發(fā)表于 11-15 15:50 ?44次下載

    簡易聲控延時燈制作方法

    簡易聲控延時燈制作方法
    的頭像 發(fā)表于 08-15 18:16 ?1.5w次閱讀

    遙控光盤鼠標(biāo)臺燈制作方法

    遙控光盤鼠標(biāo)臺燈制作方法
    的頭像 發(fā)表于 09-18 09:35 ?3415次閱讀

    純直流混血功放制作方法

    純直流混血功放的制作方法說明。
    發(fā)表于 04-08 14:50 ?10次下載

    電子叮咚門鈴的制作方法

    電子發(fā)燒友網(wǎng)站提供《電子叮咚門鈴的制作方法.zip》資料免費(fèi)下載
    發(fā)表于 08-11 09:31 ?6次下載
    電子叮咚門鈴的<b class='flag-5'>制作方法</b>