0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FIT Image起源及制作方法

lhl545545 来源:嵌入式与Linux那些事 作者:嵌入式与Linux那些 2022-09-05 14:23 次阅读

secure boot 和FIT Image是前段时间接触到的,其实早就该总结下了,奈何懒癌犯了,拖了好久才写出来。

之前也有人问我,工作后最大的感受是什么?我的回答是:“快速学习”。

嵌入式来讲,大多数应届生在校期间可能都没做过完整的项目,仅凭在校期间学习的内容很难胜任公司的要求。

就底层驱动来讲,虽然我之前也学习过韦东山老师的上s3c2440的课程,但是到了公司才发现,这些内容其实都已经过时了。

但并不是说这些内容都没有必要去学习了。在学习的过程中,认为最重要的是培养我们的自学能力。

很多初学者在刚开始学习时,可能就败在了搭建环境上。搭建环境时遇到问题不知道怎么办?

我们日常开发中遇到的90%的问题,在网上都有人遇到过,也有相应的解决办法。学会利用bing,google,stackoverflow等搜索工具是一项很重要的技能。

如果遇到了网上没有的问题怎么办?软件问题要先搞清楚原理,再去看代码逻辑。硬件问题看官方手册。像Linux kernel,ARM等都提供了完善的手册,大部分问题在手册中都有相应说明。

好了,扯远了。下面回归正题。

本文主要介绍了FIT Image起源,制作方法,its的语法结构,bootm 启动FIT Image的方式。

本文这篇文章是对后面介绍的secure boot做铺垫。ARMv8 secure boot一种实现的方式就是利用了FIT Image的特性。

zImage,uImage, Legacy uImage 和 FIT uImage

内核经过编译后,会生成一个elf的可执行程序,叫vmlinux,这个就是原始的未经任何处理加工的原版内核elf文件。不过,最终烧写在嵌入式设备上的并不是这个文件。而是经过objcopy工具加工后的专门用于烧录的镜像格式Image。

原则上Image就可以直接被烧录到Flash上进行启动执行,但linux的内核开发者觉得Image还是太大了,因此对Image进行了压缩,并且在Image压缩后的文件的前端附加了一部分解压缩代码,构成了一个压缩格式的镜像文件就叫zImage

解压的时候,通过zImage镜像头部的解压缩代码进行自解压,然后执行解压出来的内核镜像。

Uboot要正确启动Linux内核,就需要知道内核的一些信息,比如镜像的类型(kernel image,dtb,ramdisk image),镜像在内存的位置,镜像的链接地址,镜像文件是否有压缩等等。

Uboot为了拿到这些信息,发明了一种内核格式叫uImage,也叫Legacy uImage。uImage是由zImage加工得到的,uboot中有一个工具mkimage,该工具会给zImage加一个64字节的header,将启动内核所需的信息存储在header中。uboot启动后,从header中读取所需的信息,按照指示,进行相应的动作即可。

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

FIT image的来源

有了Legacy uImage后,为什么又搞出来一个FIT uImage呢?

在Linus Torvalds 看来,内核中arch/arm/mach-xxx充斥着大量的垃圾代码。因为内核并不关心板级细节,比如板上的platform设备、resource、i2c_board_info、spi_board_info等等。大家有兴趣可以看下s3c2410的板级目录,代码量在数万行。

因此,ARM社区引入了Device Tree,使用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

为了更好的支持单个固件的通用性,Uboot也需要对这种uImage固件进行支持。FIT uImage中加入多个dtb文件 和ramdisk文件,当然如果需要的话,同样可以支持多个kernel文件。

内核中的FDT全程为flattened device tree,FIT全称叫flattened image tree。FIT利用了Device Tree Source files(DTS)的语法,生成的Image文件也和dtb文件类似(称作itb)。

这样的目的就是能够使同一个uImage能够在Uboot中选择特定的kernel/dtb和ramdisk进行启动了,达成一个uImage可以通用多个板型的目的。

制作FIT Image

制作FIT Image需要用到两个工具,mkimage和的dtc。dtc要导入到环境变量$PATH中,mkimage会调用dtc。

mkimage的输入为 image source file,它定义了启动过程中image的各种属性,扩展名为.its。its只是描述了Image的属性,实际的Image data 是在uImage中,具体路径由its指定。

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

如下是kernel 的its文件,后面会介绍各项内容的含义。

/*
*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的二进制文件,包含了所有需要的数据(kernel,dtb,ramdisk)。itb文件制作好之后,就可以直接加载到嵌入式设备上,通过bootm命令启动。

总结下制作FIT Image的4个必要文件:

mkimage,

dtc

its(image source file (*.its))

image data file(s)。

its语法结构

uImage Tree 的根节点结构

/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不同也会被认为是不同的Image。

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

configurations:配置项节点,可以将不同类型的二进制文件,根据不同的场景,组合起来,形成一个个的配置项。u-boot在boot的时候,以配置项为单位加载、执行,这样就可以根据不同的场景,方便的选择不同的配置。

'/images' node

该节点中描述了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:包含该节点二进制文件的路径。

compression:压缩方式,比如none,gzip,bzip2。

os:操作系统的名称,如solaris,uboot,qnx等。

arch:平台架构,如arm,mips,i386等。

entry:二进制文件入口地址,即链接地址。

load:二进制文件的加载位置。

hash@1:镜像使用的校验算法,如sha256,crc32等。

Hash nodes

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

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

value:算法校验值,即algo计算后的数值。

'/configurations' node

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

default:默认的子节点的配置

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:额外的可加载的二进制文件的列表,U-Boot将在给定的起始地址加载每个二进制文件。

举例

如下是一个有多种kernels, ramdisks and FDT blobs镜像多套配置的its文件。它包含了3种配置,每种配置使用了不同的kernel、ramdisk和fdt,默认配置项由“default”指定,当然也可以在运行时指定。

/*
*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的编译和启动

在服务器上,可以使用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

在当前目录下就可以找到kernel_fdt.itb,itb文件就可以加载到设备上启动。

>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

也可以手动搭配不同的镜像节点启动

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配置的地址。

总结

本文对FIT Image作了简单的介绍,更详细的内容可以参考官方文档。后面有时间会动手制作一个FIT Image在板子上跑下。

FIT Image可以兼容于多种板子,而无需重新进行编译烧写。对于有多个kernel节点或者fdt节点等等,兼容性更强。同时,可以有多种configurations,来对kernel、fdt、ramdisk来进行组合。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10991

    浏览量

    206735
  • 软件
    +关注

    关注

    67

    文章

    4348

    浏览量

    85622
  • 代码
    +关注

    关注

    30

    文章

    4555

    浏览量

    66771

原文标题:secure boot (一)FIT Image

文章出处:【微信号:嵌入式与Linux那些事,微信公众号:嵌入式与Linux那些事】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    发烧音箱制作方法诀要

    发烧音箱制作方法诀要
    发表于 08-20 20:46

    加湿器制作方法

    本帖最后由 eehome 于 2013-1-5 10:03 编辑 麻烦各位前辈,有没有知道家用加湿器的制作方法的,我想学习一下,谢谢!
    发表于 11-19 21:38

    网线水晶头制作方法

    水晶头制作方法     双绞线制作工具 &
    发表于 09-03 23:04 4789次阅读

    LED频闪灯的制作方法

    LED频闪灯的制作方法 复杂的大厦也源于简单结构,现在我们就来试试从简单的闪灯
    发表于 04-20 11:12 6038次阅读
    LED频闪灯的<b class='flag-5'>制作方法</b>

    框行天线的制作方法

    框行天线的制作方法 如附图所示,这款天线的参数都标在图上。制作的材料可用7股的电力线。考虑到天线的稳定性和强度,应把天线固定在与其大
    发表于 01-04 10:09 1201次阅读
    框行天线的<b class='flag-5'>制作方法</b>

    矿机毫伏表的制作方法

    矿机毫伏表的制作方法 本表调零后,温飘很小,每次使用前应调零,用一个开关,把第2个9018的基极对地短路,然后调零即可。
    发表于 05-23 10:18 3157次阅读
    矿机毫伏表的<b class='flag-5'>制作方法</b>

    光立方制作方法

    光立方制作方法详情
    发表于 12-09 16:25 16次下载

    LED显示屏制作方法

    LED显示屏制作方法
    发表于 02-08 02:17 29次下载

    LED光立方焊接制作方法

    制作方法
    发表于 09-04 09:20 0次下载

    倒车雷达的制作方法

    本文图文介绍了倒车雷达的制作方法
    发表于 11-15 15:39 12次下载

    简易声控延时灯制作方法

    简易声控延时灯制作方法
    的头像 发表于 08-15 18:16 1.5w次阅读

    遥控光盘鼠标台灯制作方法

    遥控光盘鼠标台灯制作方法
    的头像 发表于 09-18 09:35 3281次阅读

    s5编程电缆制作方法

    s5编程电缆制作方法说明。
    发表于 05-09 11:27 8次下载

    无铅高温锡膏的制作方法及注意事项

    无铅锡膏使用时的工艺控制和制作方法,现如今电子产品的焊接是其重要的生产环节,目前使用无铅锡膏产品,有低、高温两种产品,还有称有铅和无铅,每一种的都是不同的制作方法和控制,下面由小编锡膏厂家先为大家介绍高温锡膏的制作方法
    发表于 10-14 14:34 4009次阅读

    Insun英尚SPI程序制作方法

    Insun英尚SPI程序制作方法
    的头像 发表于 07-06 10:25 425次阅读
    Insun英尚SPI程序<b class='flag-5'>制作方法</b>