文章目录

  • 前言
  • zImage,uImage, Legacy uImage 和 FIT uImage
  • FIT image的来源
  • 制作FIT Image
  • its语法结构
    • uImage Tree 的根节点结构
    • '/images' node
    • Hash nodes
    • '/configurations' node
    • Configuration nodes
    • 举例
  • FIT Image的编译和启动
  • bootm启动不同的配置
  • 总结
  • 本文参考

前言

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指定。

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

/** Simple U-Boot uImage source file containing a single kernel*//dts-v1/;/ {description = "Simple image with single Linux kernel";#address-cells = <1>;images {kernel@1 {description = "Vanilla Linux kernel";data = /incbin/("./vmlinux.bin.gz"); # Image data 具体路径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 = "Boot Linux kernel";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 的根节点结构

/ o image-tree|- description = "image description"|- timestamp = <12399321>|- #address-cells = <1>|o images| || o image@1 {...}| o image@2 {...}| ...|o configurations|- default = "conf@1"|o conf@1 {...}o conf@2 {...}...
  • description:描述uImage的文本。

  • timestamp:修改Image镜像的时间,由mkimage工具自动生成。在security boot中,timestamp不同也会被认为是不同的Image。

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

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

‘/images’ node

该节点中描述了Image镜像必要的信息.

 o image@1|- description = "component sub-image description"|- data = /incbin/("path/to/data/file.bin")|- type = "sub-image type name"|- arch = "ARCH name"|- os = "OS name"|- compression = "compression name"|- load = <00000000>|- entry = <00000000>|o hash@1 {...}o hash@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

o hash@1|- algo = "hash or checksum algorithm name"|- value = [hash or checksum value]
  • algo:算法名称,如crc32,md5,sha256等。

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

‘/configurations’ node

o configurations|- default = "default configuration sub-node unit name"|o config@1 {...}o config@2 {...}...
  • default:默认的子节点的配置

  • config@1: 该配置具体使用那些kernel Image,ramdisk Image等。

Configuration nodes

o config@1|- description = "configuration description"|- kernel = "kernel sub-node unit name"|- ramdisk = "ramdisk sub-node unit name"|- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...]|- fpga = "fpga sub-node unit-name"|- loadables = "loadables sub-node unit-name"
  • description:该配置的名称。

  • kernel:镜像类型为kernel的单元的名称。

  • ramdisk:镜像类型为ramdisk的单元的名称。

  • fdt:镜像类型为fdt的单元的名称。

  • loadables:额外的可加载的二进制文件的列表,U-Boot将在给定的起始地址加载每个二进制文件。

举例

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

/** U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs*//dts-v1/;/ {description = "Various kernels, ramdisks and FDT blobs";#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 = "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";};};
};

FIT Image的编译和启动

在服务器上,可以使用mkimage工具制作 FIT Image。

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

/** Simple U-Boot uImage source file containing a single kernel and FDT blob*//dts-v1/;/ {description = "Simple image with single Linux kernel and FDT blob";#address-cells = <1>;images {kernel@1 {description = "Vanilla Linux kernel";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 = "Flattened Device Tree blob";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 = "Boot Linux kernel with FDT blob";kernel = "kernel@1";fdt = "fdt@1";};};
};
$ mkimage -f kernel_fdt.its kernel_fdt.itb
DTC: dts->dtb  on file "kernel_fdt.its"
$
$ mkimage -l kernel_fdt.itb
FIT description: Simple image with single Linux kernel and FDT blob
Created:     Tue Mar 11 16:29:22 2008Image 0 (kernel@1)Description:    Vanilla Linux kernelType:       Kernel ImageCompression:    gzip compressedData Size:   1092037 Bytes = 1066.44 kB = 1.04 MBArchitecture: PowerPCOS:      LinuxLoad Address: 0x00000000Entry Point:   0x00000000Hash algo:    crc32Hash value:    2c0cc807Hash algo:  sha1Hash value: 264b59935470e42c418744f83935d44cdf59a3bbImage 1 (fdt@1)Description:    Flattened Device Tree blobType:     Flat Device TreeCompression:    uncompressedData Size:  16384 Bytes = 16.00 kB = 0.02 MBArchitecture: PowerPCHash algo:   crc32Hash value:    0d655d71Hash algo:  sha1Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52defDefault Configuration: 'conf@1'Configuration 0 (conf@1)Description: Boot Linux kernel with FDT blobKernel:  kernel@1FDT:       fdt@1

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

> tftp 900000 /path/to/tftp/location/kernel_fdt.itb
Using FEC device
TFTP from server 192.168.1.1; our IP address is 192.168.160.5
Filename '/path/to/tftp/location/kernel_fdt.itb'.
Load address: 0x900000
Loading: ############################################################################
done
Bytes transferred = 1109776 (10ef10 hex)
=> iminfo## Checking Image at 00900000 ...FIT image foundFIT description: Simple image with single Linux kernel and FDT blobCreated:        2008-03-11  15:29:22 UTCImage 0 (kernel@1)Description:  Vanilla Linux kernelType:     Kernel ImageCompression:  gzip compressedData Start:   0x009000ecData Size:    1092037 Bytes =  1 MBArchitecture: PowerPCOS:       LinuxLoad Address: 0x00000000Entry Point:  0x00000000Hash algo:    crc32Hash value:   2c0cc807Hash algo:    sha1Hash value:   264b59935470e42c418744f83935d44cdf59a3bbImage 1 (fdt@1)Description:  Flattened Device Tree blobType:     Flat Device TreeCompression:  uncompressedData Start:   0x00a0abdcData Size:    16384 Bytes = 16 kBArchitecture: PowerPCHash algo:    crc32Hash value:   0d655d71Hash algo:    sha1Hash value:   25ab4e15cd4b8a5144610394560d9c318ce52defDefault Configuration: 'conf@1'Configuration 0 (conf@1)Description:  Boot Linux kernel with FDT blobKernel:       kernel@1FDT:       fdt@1
=> bootm
## Booting kernel from FIT Image at 00900000 ...Using 'conf@1' configurationTrying 'kernel@1' kernel subimageDescription:  Vanilla Linux kernelType:     Kernel ImageCompression:  gzip compressedData Start:   0x009000ecData Size:    1092037 Bytes =  1 MBArchitecture: PowerPCOS:       LinuxLoad Address: 0x00000000Entry Point:  0x00000000Hash algo:    crc32Hash value:   2c0cc807Hash algo:    sha1Hash value:   264b59935470e42c418744f83935d44cdf59a3bbVerifying Hash Integrity ... crc32+ sha1+ OKUncompressing Kernel Image ... OK
## Flattened Device Tree from FIT Image at 00900000Using 'conf@1' configurationTrying 'fdt@1' FDT blob subimageDescription:  Flattened Device Tree blobType:     Flat Device TreeCompression:  uncompressedData Start:   0x00a0abdcData Size:    16384 Bytes = 16 kBArchitecture: PowerPCHash algo:    crc32Hash value:   0d655d71Hash algo:    sha1Hash value:   25ab4e15cd4b8a5144610394560d9c318ce52defVerifying Hash Integrity ... crc32+ sha1+ OKBooting using the fdt blob at 0xa0abdcLoading Device Tree to 007fc000, end 007fffff ... OK
[    0.000000] Using lite5200 machine description
[    0.000000] Linux version 2.6.24-rc6-gaebecdfc (m8@hekate) (gcc version 4.0.0 (DENX ELDK 4.1 4.0.0)) #1 Sat Jan 12 15:38:48 CET 2008

bootm启动不同的配置

对于FIT Image,bootm有多种启动方式。

1. bootm <addr1>
2. bootm [<addr1>]:<subimg1>
3. bootm [<addr1>]#<conf>[#<extra-conf[#...]]
4. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2>
5. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> [<addr3>]:<subimg3>
6. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> <addr3>
7. bootm [<addr1>]:<subimg1> -            [<addr3>]:<subimg3>
8. bootm [<addr1>]:<subimg1> -            <addr3>

对于有多种镜像,多套配置的itb,都是以configurations 中default 指定的配置启动。

bootm 200000

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

bootm 200000#cfg@1

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

bootm 200000:kernel@1 800000:ramdisk@2
bootm 200000:kernel@1 800000:ramdisk@1 800000:fdt@1
bootm 200000:kernel@2 200000:ramdisk@2 600000
bootm 200000:kernel@2 - 200000:fdt@1

如果bootm的时候不指定地址,则会使用CONFIG_SYS_LOAD_ADDR配置的地址。

总结

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

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

本文参考

https://www.elecfans.com/emb/20190402899374.html

http://www.wowotech.net/u-boot/fit_image_overview.html

howto.txt

command_syntax_extensions.txt

source_file_format.txt

secure boot (一)fit image相关推荐

  1. UEFI、BIOS、Secure Boot的关系和知识介绍

    从Windows 8操作系统时代开始,安装操作系统的方法也有了很大的改变,Windows 8采用了Secure Boot引导启动的方式,而不是过去Win XP和Win 7的Legacy启动方式,从而导 ...

  2. 反Secure Boot垄断:兼谈如何在Windows 8电脑上安装Linux

    一.自由软件基金会的呼吁 上周,2012年将近结束的时候,自由软件基金会(FSF)发出呼吁,要求人们继续支持反Secure Boot垄断,希望签名者能达到5万人(目前是4万). 我觉得,这个呼吁很重要 ...

  3. linux+显卡+停止运行,Linux secure boot(安全启动)时添加Nvidia显卡驱动

    原文链接: http://www.bubuko.com/infodetail-809913.html 开启Secure boot情况下,在Fedora 21下安装Nvidia 显卡驱动的方法. Nvi ...

  4. 华硕笔记本之secure boot

    在ubuntu下安装cuda的时候,一直装不好,cuda-7.5.run已经装好了,但是编译cuda的例程时失败,提示cuda的库链接不上. 初步判断是secure boot的问题,因为在开启X的情况 ...

  5. 惠普关闭 secure boot

    一般新买的win10电脑,是无法安装ubuntu的,需要关闭 secure boot 开机f1进bios,改成英文 advanced-secure boot configuration config ...

  6. Trusted Boot和Secure Boot的区别

    https://www.ibm.com/developerworks/library/l-trusted-boot-openPOWER-trs/index.html Trusted Boot依赖于Se ...

  7. 华硕主板关闭Secure Boot步骤 :(支持b460/b560/b660主板)

    Secure BOOT作用:Secure BOOT设计之初作用是防止恶意软件侵入.事实上它能够做到的仅仅是,当电脑引导器被病毒修改之后,它会给出提醒并拒绝启动,避免可能带来的进一步损失. 1.重启华硕 ...

  8. 宏碁笔记本关闭安全启动Secure Boot,就是改为Disabled

    1.开机按ESC或者F12进入BiOS界面 2.进入Boot 3.发现Secure Boot 为灰色不可点的状态. 4.Secure Boot 为灰色不可点的状态,则要切换到Security页面,选择 ...

  9. 解决win10 安装dnw驱动,每次重启都得禁用数字签名。解决命令行操作,设置元素数据时出错。电脑关闭Secure Boot

    解决win10 安装驱动,每次重启都得禁用数字签名 第一步.将电脑关闭Secure Boot 以我的华硕笔记本电脑为例: 1.重启电脑,按住 F2 进入 bios 模式.(其他电脑自行百度) 2.按 ...

最新文章

  1. 想去苹果做AI?看看你够不够格
  2. 乐观锁、悲观锁简单分析,回忆旧(新)知识...
  3. 现代密码学4.2--消息验证码/MAC
  4. ThreadLocal的使用
  5. TCP 端口监听队列原理
  6. hash redis springboot_Redis常见的工作场景使用实战,Redisson分布式锁的实现
  7. 2015c语言9月答案,2015年9月计算机二级C语言预测题答案
  8. SecureCRT如何导出导入配置文件
  9. 以后外卖还可以买手机了!饿了么与上海迪信通达成合作
  10. 将一幅图像转换为灰度图
  11. 【电子技术实验】NE555中文数据手册
  12. android使用谷歌插件下载图片,Image Downloader:批量图片下载
  13. Gradient Descent for one-hidden-layer-function(单隐藏层神经网络的梯度下降)
  14. intellij idea 工具栏的隐藏和显示
  15. ITK4.12+VS2015配置详解
  16. 基于python和md5的相同图片查重
  17. 非常道 2010-4-5日
  18. 开源的杀毒软件--ClamWin
  19. 如何向虚拟服务器传送文件,如何往虚拟机内传文件的3种方法
  20. 钉钉开发系列(十一)钉钉网页扫码登录

热门文章

  1. 2021-06-04 记一次好玩的通信原理实验
  2. Spark SQL操作之-函数汇总篇-下
  3. LWIP应用开发|LWIP协议栈
  4. Tacotron2--语音合成
  5. 青花瓷(java版)
  6. 内部用户触达方式主要有哪些?
  7. Win32 API实现CDC类的FillSolidRect接口
  8. Web3j通过合约地址监听transfer事件获取以太坊交易数据
  9. FontFamily 看这里就够了
  10. wordpress 常见代码文章外链加上nofollow移除多余加载JS和CSS代码等