前言
很早就应该写关于安全启动和FIT镜像的文章了,但是很久没有写下来。
曾经有人问我,工作后最让你感触的是什么?我的回答是“学得快”。
就嵌入而言,大多数应届毕业生在校时可能没有做过完整的项目,仅靠在校所学的知识很难满足公司的要求。
就基础驱动来说,之前学过魏东山老师的s3c2440课程,但是到了公司才发现这些内容其实都是老的了。
但是,这并不意味着您不需要学习这些东西。我认为学习过程中最重要的是培养自己学习的能力。
许多初学者在刚开始学习时可能会在设置环境时失败。您是否在设置环境时遇到困难并且不知道该怎么办?
我们日常开发中遇到的问题90%网上都有人遇到过并且有相应的解决方案。学习如何使用Bing、Google 和stackoverflow 等搜索工具是一项非常重要的技能。
遇到网上查不到的问题怎么办? 对于软件问题,应该先了解原理,再检查代码逻辑。对于硬件问题,请参考官方手册。 Linux内核、ARM等都提供了完整的文档,大多数问题都在文档中进行了解释。
现在,这已经太过分了。现在,让我们回到主题。
本文主要介绍FIT Image的由来、如何创建、其语法结构以及如何使用bootm启动FIT Image。
本文将帮助您做好安全启动的准备,稍后将对此进行介绍。实现ARMv8 安全启动的一种方法是使用FIT 映像特性。
zImage,uImage, Legacy uImage 和 FIT uImage
编译内核时,它会生成一个名为vmlinux 的elf 可执行文件。这是未经任何处理的原始内核elf文件。然而,最终写入嵌入式设备的并不是这个文件。这是一种经过objcopy工具处理后专门用于写入的图像格式。
原则上,镜像可以直接写入Flash来启动和运行,但Linux内核开发人员认为镜像仍然太大,因此他们压缩了镜像,并为压缩后的镜像文件创建了一个前端,并添加了一些解压缩功能。此代码构建一个名为zImage 的压缩格式的图像文件。
解压时,zImage镜像头中的解压代码进行自解压并运行解压后的内核镜像。
为了成功启动Linux内核,Uboot需要了解有关内核的一些信息。例如镜像的类型(内核镜像、dtb、ramdisk镜像)、镜像在内存中的位置、镜像的链接地址、镜像文件是否被压缩等。
为了获取这些信息,Uboot发明了一种称为uImage(也称为legacy uImage)的内核格式。 uImage由zImage处理。 uboot 有一个名为mkimage 的工具,它会在zImage 中添加一个64 字节的标头,并在标头中存储引导内核所需的信息。一旦uboot启动,它就会从头中读取所需的信息,按照指令执行相应的操作。
有关标头格式,请参阅include/image.h。 mkimage的源代码位于tools/mkimage中
FIT image的来源
为什么在使用旧版uImage 后还要创建FIT uImage?
根据Linus Torvalds 的说法,Arch/arm/mach-xxx 内核中充满了大量的垃圾代码。这是因为内核不关心板上的平台设备、资源、i2c_board_info、spi_board_info等板级细节。如果您有兴趣,请查看s3c2410 板级目录。代码量有几万行。
这就是ARM 社区引入设备树的原因。设备树允许将许多硬件细节直接传输到Linux,而不需要在内核中进行大量冗余编码。
为了更好地支持单个固件的通用性,Uboot也应该支持这个uImage固件。 FIT uImage 中添加了多个dtb 文件和ramdisk 文件。当然,如果需要的话也支持多个内核文件。
内核中FDT的整个过程就是一个扁平化的设备树,FIT的正式名称是扁平化的镜像树。 FIT使用设备树源文件(DTS)语法,生成的图像文件类似于dtb文件(简称itb)。
这样做的目的是允许Uboot通过选择特定的kernel/dtb和ramdisk来启动同一个uImage,从而允许一个uImage用于多种板类型。
关于嵌入式物联网,有很多东西需要学习。如果你不学错路线或者内容,你的工资就会增加。
免费共享约150GB的数据包。学习内容、访谈、项目都比较新、广泛。据估计,在网上购买某些鱼至少要花费几十美元。
点此寻找助手,0元领取:嵌入式物联网学习资料(今日头条)
制作FIT Image
创建FIT 映像需要两个工具:mkimage 和dtc。 dtc 必须导入到环境变量$PATH 中,mkimage 将调用dtc。
mkimage 的输入是一个扩展名为.its 的图像源文件,它定义了启动过程中图像的各种属性。只要写出Image的属性就可以了。实际的Image数据在uImage内部,具体路径由它指定。
下面是内核文件。后面会介绍各个内容的含义。
/* * 包含单个内核的简单U-Boot uImage 源文件*//dts-v1/;/{description=’包含单个Linux 内核的简单映像’ #address-cells=1 {description=’Vanilla Linux kernel’; data=/incbin/(‘./vmlinux.bin.gz’); # 图像数据特定路径类型=’ppc’; os=’linux’; { default=’config@ 1 { description=’Boot Linux kernel’ } };}; mkimage 的输出是一个包含所有必要数据(内核、dtb、ramdisk)的二进制文件。 )。 itb文件创建后,可以直接加载到嵌入式设备上,并通过bootm命令启动。
收集创建FIT 图像所需的四个文件。
mkimage、dtcits(图像源文件(*.its)) 图像数据文件。
its语法结构
uImage Tree 的根节点结构
/o 图像树|- 描述=’图像描述’ |- #address-cells=1 | o 图像@1 | @2 {.} |- 默认=’ conf@1′ | o conf@1 {.} o conf@2 {.} .描述:描述uImage。句子。时间戳:更改镜像镜像的时间。由mkimage 工具自动生成。 Security Boot 还将不同的时间戳视为不同的映像。映像:子映像,例如内核映像、RAM 磁盘映像等。配置:配置项节点。您可以根据不同的场景,将不同类型的二进制文件组合起来形成配置项。 u-boot在启动时逐单元加载并执行配置项,可以方便地针对不同的场景选择不同的配置。
‘/images’ node
该节点包含镜像镜像所需的信息。
o image@1 |- description=’组件子图像描述’ |- data=/incbin/(‘path/to/data/file.bin’) |- type=’子图像类型名称’ |- Arch=’ARCH 名称’ |- os=’操作系统名称’ |- 压缩=’压缩名称’ |- 负载=00000000 |- 条目=00000000 | o hash@1 {.} o hash@2 {.} .description:子镜像的文本描述。你可以随心所欲地写。 type:子镜像的类型,例如standalone、kernel、ramdisk、firmware等。 data:包含节点二进制文件的路径。压缩:压缩方式(无、gzip、bzip2等)。 os:操作系统的名称(solaris、uboot、qnx 等)。 Arch:arm、mips、i386等平台架构。 Entry:二进制文件入口地址,或者链接地址。 load:二进制文件的加载位置。 hash@1:图像中使用的验证算法(sha256、crc32等)。
Hash nodes
o hash@1 |- algo=’哈希或校验和算法名称’ |- value=[哈希或校验和值] algo:算法名称,例如crc32、md5、sha256。 value:算法校验值,即算法计算出来的值。
‘/configurations’ node
o 配置|- default=’默认配置子节点单元名称’ | o config@1 {.} o config@2 {.} .default:默认子节点配置config@ 1: 这个配置我们使用内核映像、RAM 磁盘映像等。
Configuration nodes
o config@1 |- description=’配置描述’ |- kernel=’内核子节点单元名称’ |- ramdisk=’ramdisk 子节点单元名称’ |- fdt=’fdt 子节点单元名称’ [, ‘ fdt |overlay 子节点单元名称’,] |- fpga=’fpga 子节点单元名称’ |-loadables=’loadables 子节点单元名称’ 描述:配置名称。 kernel:镜像类型为kernel的单元名称。 ramdisk:镜像类型为ramdisk的单元名称。 fdt:图像类型为fdt的单元名称。 loadables:其他可加载二进制文件的列表。 U-Boot 在指定的起始地址加载每个二进制文件。
举例
下面是一个包含内核、RAM 磁盘和FDT BLOB 映像的多个配置的文件。它包括三种配置,每种配置都有不同的内核、ramdisk 和fdt。默认配置项由“default”指定。当然,你也可以在运行时指定。
/* * 包含多个内核、ramdisk 和FDT BLOB 的U-Boot uImage 源文件*//dts-v1/;/{ description=’各种内核、ramdisk 和FDT BLOB’ #address-cells=1 ;=’vanilla-2.6.23′; 数据=/incbin/(‘./vmlinux.bin.gz’); arch=’ppc’; 负载=00000000 { algo=’ 2.6.23′ ; 数据=/incbin/(‘./2.6.23-denx.bin.gz’); 操作系统=’gzip’; 哈希@1 { 算法=’sha1′ } ; 数据=/incbin/(‘./2.4.25-denx.bin.gz) ‘); 压缩=00000000; @1 { 描述=’eldk-4.2-ramdisk’; /(‘./eldk-4.2-ramdisk’); arch=’gzip’; 条目=00000000; hash @ 1 { algo=’eldk-3.1-ramdisk’ ; ppc’; 条目=’fdt@1 }; 数据=’flat_dt’; { 描述=’tqm5200s-fdt’; 压缩=’none’; 哈希@ 1 { 默认值=’config@1′;config’; 1′ }; 描述=’tqm5200s kernel@ 2′; fdt=’fdt@2′ }; 描述=’tqm5200s denx-2.4.25 配置’;
FIT Image的编译和启动
在服务器上,您可以使用mkimage 工具创建FIT 映像。
下面是kernel_fdt.its,它是用来创建下面的itb的。
/* * 包含单个内核和FDT blob 的简单U-Boot uImage 源文件*//dts-v1/;/{ description=’包含单个Linux 内核和FDT blob 的简单映像’ #address -cells=1; kernel@1 { 描述=’Vanilla Linux 内核’; data=/incbin/(‘./vmlinux.bin.gz’); arch=’ppc’;=’sha1′ };data=/incbin/(‘./target.dtb’); arch=’ppc’; 哈希@1 { 算法=’crc32′;=’sha1′ 配置{ 默认=’ conf@1′; Description=’FDT kernel=’fdt@1′;};};}; $ mkimage -f kernel_fdt.its kernel_fdt.itbdtc: DTS -DTB on File’ Kernel_fdt.its PTION3360 使用Linux 内核和FDT Blobcreated: 3 月11 日星期二16:29:22 2008 Image 0 (kernel@1)Description:Virginia
nilla Linux kernel Type: Kernel Image Compression: gzip compressed Data Size: 1092037 Bytes = 1066.44 kB = 1.04 MB Architecture: PowerPC OS: Linux Load Address: 0x00000000 Entry Point: 0x00000000 Hash algo: crc32 Hash value: 2c0cc807 Hash algo: sha1 Hash value: 264b59935470e42c418744f83935d44cdf59a3bb Image 1 (fdt@1) Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Size: 16384 Bytes = 16.00 kB = 0.02 MB Architecture: PowerPC Hash algo: crc32 Hash value: 0d655d71 Hash algo: sha1 Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def Default Configuration: ‘conf@1’ Configuration 0 (conf@1) Description: Boot Linux kernel with FDT blob Kernel: kernel@1 FDT: fdt@1在当前目录下就可以找到kernel_fdt.itb,itb文件就可以加载到设备上启动。
> tftp 900000 /path/to/tftp/location/kernel_fdt.itbUsing FEC deviceTFTP from server 192.168.1.1; our IP address is 192.168.160.5Filename ‘/path/to/tftp/location/kernel_fdt.itb’.Load address: 0x900000Loading: ################################################################# ###########doneBytes transferred = 1109776 (10ef10 hex)=> iminfo## Checking Image at 00900000 … FIT image found FIT description: Simple image with single Linux kernel and FDT blob Created: 2008-03-11 15:29:22 UTC Image 0 (kernel@1) Description: Vanilla Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x009000ec Data Size: 1092037 Bytes = 1 MB Architecture: PowerPC OS: Linux Load Address: 0x00000000 Entry Point: 0x00000000 Hash algo: crc32 Hash value: 2c0cc807 Hash algo: sha1 Hash value: 264b59935470e42c418744f83935d44cdf59a3bb Image 1 (fdt@1) Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x00a0abdc Data Size: 16384 Bytes = 16 kB Architecture: PowerPC Hash algo: crc32 Hash value: 0d655d71 Hash algo: sha1 Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def Default Configuration: ‘conf@1’ Configuration 0 (conf@1) Description: Boot Linux kernel with FDT blob Kernel: kernel@1 FDT: fdt@1=> bootm## Booting kernel from FIT Image at 00900000 … Using ‘conf@1’ configuration Trying ‘kernel@1’ kernel subimage Description: Vanilla Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x009000ec Data Size: 1092037 Bytes = 1 MB Architecture: PowerPC OS: Linux Load Address: 0x00000000 Entry Point: 0x00000000 Hash algo: crc32 Hash value: 2c0cc807 Hash algo: sha1 Hash value: 264b59935470e42c418744f83935d44cdf59a3bb Verifying Hash Integrity … crc32+ sha1+ OK Uncompressing Kernel Image … OK## Flattened Device Tree from FIT Image at 00900000 Using ‘conf@1’ configuration Trying ‘fdt@1’ FDT blob subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x00a0abdc Data Size: 16384 Bytes = 16 kB Architecture: PowerPC Hash algo: crc32 Hash value: 0d655d71 Hash algo: sha1 Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def Verifying Hash Integrity … crc32+ sha1+ OK Booting using the fdt blob at 0xa0abdc Loading 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@2bootm 200000:kernel@1 800000:ramdisk@1 800000:fdt@1bootm 200000:kernel@2 200000:ramdisk@2 600000bootm 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
来源:嵌入式与Linux那些事
本文转载自“嵌入式与Linux那些事”,如有侵权,请联系删除原文链接:secure boot (一)FIT Image
版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
原创文章,作者:小条,如若转载,请注明出处:https://www.sudun.com/ask/85182.html