这里作为《[uboot] (番外篇)uboot启动kernel篇(二)——bootm跳转到kernel的流程》延伸,介绍一下bootm过程中,怎么从uImage中获取kernel的信息的。
一、说明
从《[uboot] (番外篇)uboot启动kernel篇(二)——bootm跳转到kernel的流程》我们知道了bootm的过程中,从uImage解析出kernel信息主要是在bootm_find_os中实现的。
这里注意,这些信息主要是在mkimage工具生成uImage的时候附加上去的,并不是kernel原生镜像的内容。
因为uImage有两种类型,Legacy-uImage和FIT-uImage ,这两个类型的格式是不一样的,因此,uboot从这两种uImage解析出kernel信息的方式也是不一样的。
后面会分别介绍这两种类型的解析流程。
二、kernel信息的存放位置
1、存放位置
kernel信息主要包括两方面内容:
- kernel的镜像信息(包括其加载地址):放在bootm_headers_t images -> image_info_t os中
- kernel的入口地址:放在bootm_headers_t images -> ulong ep中
如下(过滤掉一些无关部分)
include/image.h
typedef struct bootm_headers {
image_info_t os; /* os image info */
ulong ep; /* entry point of OS */
}
因此,bootm_find_os的主要目的是实现bootm_headers_t images中的image_info_t os和ulong ep的成员。
2、image_info_t
image_info_t用来描述kernel的镜像信息。包括头部信息、加载地址、kernel镜像地址和长度等等。
其数据结构如下:
include/image.h
typedef struct image_info {
ulong start, end; /* start/end of blob */ // 包括附加节点信息之内的整个kernel节点的起始地址和结束地址
ulong image_start, image_len; /* start of image within blob, len of image */ // kernel镜像的起始地址,镜像长度
ulong load; /* load addr for the image */ // 镜像的加载地址
uint8_t comp, type, os; /* compression, type of image, os type */ // 镜像的压缩格式、镜像类型、操作系统类型
uint8_t arch; /* CPU architecture */ // CPU体系结构
} image_info_t;
type对应于“kennel”,os对应于“linux”。
综上,后续我们解析uImage的时候的主要目的是填充image_info_t os和ulong ep,这句话多强调几遍。
三、Legacy-uImage中kernel信息的解析
建议先参考《[uboot] (番外篇)uboot启动kernel篇(一)——Legacy-uImage & FIT-uImage》
Legacy-uImage中kernel信息的解析相对较为简单。
1、Legacy-uImage的生成
首先要知道Legacy-uImage是怎么生成的。
如下:
mkimage -A arm -O linux -C none -T kernel -a 0x20008000 -e 0x20008040 -n Linux_Image -d zImage uImage
Usage: mkimage -l image
-l ==> list image header information
mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch' // 体系
-O ==> set operating system to 'os' // 操作系统
-T ==> set image type to 'type' // 镜像类型
-C ==> set compression type 'comp' // 压缩类型
-a ==> set load address to 'addr' (hex) // 加载地址
-e ==> set entry point to 'ep' (hex) // 入口地址
-n ==> set image name to 'name' // 镜像名称,注意不能超过32B
-d ==> use image data from 'datafile' // 输入文件
-x ==> set XIP (execute in place)
通过上述,可以知道kernel的信息都是在这个时候定义的(而不是kernel原生镜像原来就有的)。
生成uImage会包含64Byte的格式头,如下:
hlos@node4:boot$ od -tx1 -tc -Ax -N64 uImage
000000 27 05 19 56 5a f3 f7 8e 58 45 0d 3d 00 17 cd f8
' 005 031 V Z 363 367 216 X E \r = \0 027 315 370
000010 20 00 80 00 20 00 80 40 e2 4b 43 b6 05 02 02 00
\0 200 \0 \0 200 @ 342 K C 266 005 002 002 \0
0