前言
本次实验环境
linux- 4.0 . tar. xz
u- boot- 2017.05 . tar. bz2
问题描述
在系统移植的第一步, 一般是 直接 找个 相似的 config , 然后配置一下, 然后编译一下. 直接tftp 然后bootm
如果 没有看到 Uncompressing Linux. . . done, booting the kernel
一般是因为 地址 的问题
这里面涉及到 四个地址
tftp 地址 / bootm 地址 / Load Address / Entry Point
总结
从实验来看
可见, 内核( zImage, uImage去掉uImage头就是zImage) 最终在内核的地址 还是内核做主.
Load Address 表示 内核镜像( zImage) 想要 住宿 的 内存地址
Entry Point 表示 当 内核镜像已经 住宿 到内存中去, uboot 要 将控制权 转移到 Entry Point , 也就是 uboot 的 最后一句 kernel_entry ( 0 , machid, r2) ; 这个函数的 地址 就是 Entry Point. 这个 Entry Point 就是 解压代码的第一条指令.
-- -
Load Address 是 zImage 的住宿地址
Entry Point 是 zImage 的控制地址, ( 从这个地址接收控制权)
可以看出来 uboot 就像 奴仆 一样 侍奉 kernel
tftp 0x60003000 uImage;
bootm 0x60003000 ;
uboot 一般通过 这两条 command line 来达到目的
tftp 0x60003000 uImage; bootm 0x60003000 ;
tftp A_addr uImage; bootm B_addr ;
tftp 0x60003000 uImage 只是将 uImage 下载到一个 临时地址. 下一句才是 安排住宿 和 控制交接的 流程
bootm 0x60003000 ;
1.
uImage ( uImage头+ zImage) 已经在 0x60003000 , 从 0x60003000 ( uImage头的位置, 存储zImage 要求 1. 住宿地址 2. 控制地址) 解析 住宿地址 和 控制地址.
2.
如果 0x60003040 ( 0x60003000 + 0x40 ) 已经是 zImage 想要的 住宿地址( 0x60003040 == Load Address) , 就不用 重新安排住宿.
如果 0x60003040 不是 zImage 想要的 住宿地址( 0x60003040 != Load Address) , 就将 zImage 搬到 zImage要求的地址( Load Address) .
3.
目前 zImage 已经到了想要的住宿环境 , uboot 就将 控制权( pc) 转移到 Entry Point.
下面注意关注 LOADADDR
ifneq ( $( LOADADDR) , )
UIMAGE_LOADADDR= $( LOADADDR)
else
ifeq ( $( CONFIG_ZBOOT_ROM) , y)
UIMAGE_LOADADDR= $( CONFIG_ZBOOT_ROM_TEXT)
else
UIMAGE_LOADADDR= $( ZRELADDR)
endif
endif
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 手动分隔
下面注意关注 UIMAGE_LOADADDR
$( obj) / uImage: $( obj) / zImage FORCE
@$( check_for_multiple_loadaddr)
$( call if_changed, uimage)
@$( kecho) ' Image $@ is ready'
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 手动分隔
下面注意关注 cmd_uimage 中 的 UIMAGE_LOADADDR 和 UIMAGE_ENTRYADDR
# U-Boot mkimage
# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
MKIMAGE : = $( srctree) / scripts/ mkuboot. sh
# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces
# the number of overrides in arch makefiles
UIMAGE_ARCH ? = $( SRCARCH)
UIMAGE_COMPRESSION ? = $( if $( 2 ) , $( 2 ) , none)
UIMAGE_OPTS- y ? =
UIMAGE_TYPE ? = kernel
UIMAGE_LOADADDR ? = arch_must_set_this
UIMAGE_ENTRYADDR ? = $( UIMAGE_LOADADDR)
UIMAGE_NAME ? = 'Linux-$(KERNELRELEASE)'
UIMAGE_IN ? = $<
UIMAGE_OUT ? = $@
quiet_cmd_uimage = UIMAGE $( UIMAGE_OUT)
cmd_uimage = $( CONFIG_SHELL) $( MKIMAGE) - A $( UIMAGE_ARCH) - O linux \
- C $( UIMAGE_COMPRESSION) $( UIMAGE_OPTS- y) \
- T $( UIMAGE_TYPE) \
- a $( UIMAGE_LOADADDR) - e $( UIMAGE_ENTRYADDR) \
- n $( UIMAGE_NAME) - d $( UIMAGE_IN) $( UIMAGE_OUT)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 手动分隔
cmd_uimage 最后的体现是
$cat arch/ arm/ boot/ . uImage. cmd
cmd_arch/ arm/ boot/ uImage : = / bin/ bash . / scripts/ mkuboot. sh - A arm - O linux - C none - T kernel - a 0x60004000 - e 0x60004000 - n 'Linux-4.0.0' - d arch/ arm/ boot/ zImage arch/ arm/ boot/ uImage
实验流程
$ export ARCH= arm CROSS_COMPILE= arm- linux- gnueabi- ; make vexpress_defconfig; make LOADADDR= 0x60004000 uImage - j8
. . .
LD vmlinux
SORTEX vmlinux
SYSMAP System. map
OBJCOPY arch/ arm/ boot/ Image
Kernel: arch/ arm/ boot/ Image is ready
LDS arch/ arm/ boot/ compressed/ vmlinux. lds
AS arch/ arm/ boot/ compressed/ head. o
GZIP arch/ arm/ boot/ compressed/ piggy. gzip
CC arch/ arm/ boot/ compressed/ misc. o
CC arch/ arm/ boot/ compressed/ decompress. o
CC arch/ arm/ boot/ compressed/ string. o
SHIPPED arch/ arm/ boot/ compressed/ hyp- stub. S
SHIPPED arch/ arm/ boot/ compressed/ lib1funcs. S
SHIPPED arch/ arm/ boot/ compressed/ ashldi3. S
SHIPPED arch/ arm/ boot/ compressed/ bswapsdi2. S
AS arch/ arm/ boot/ compressed/ hyp- stub. o
AS arch/ arm/ boot/ compressed/ lib1funcs. o
AS arch/ arm/ boot/ compressed/ ashldi3. o
AS arch/ arm/ boot/ compressed/ bswapsdi2. o
AS arch/ arm/ boot/ compressed/ piggy. gzip. o
LD arch/ arm/ boot/ compressed/ vmlinux
OBJCOPY arch/ arm/ boot/ zImage
Kernel: arch/ arm/ boot/ zImage is ready
UIMAGE arch/ arm/ boot/ uImage
Image Name: Linux- 4.0 .0 +
Created: Tue Oct 9 18 : 14 : 46 2018
Image Type: ARM Linux Kernel Image ( uncompressed)
Data Size: 6317536 Bytes = 6169.47 kB = 6.02 MB
Load Address: 60004000
Entry Point: 60004000
Image arch/ arm/ boot/ uImage is ready
可以看到,
1 /
首先生成了 vmlinux , 然后vmlinux 被 OBJCOPY 成了 Image
2 /
一些解压代码 和 压缩过后的 Image 链接成了 zImage
3 /
通过 UIMAGE 将 zImage 做成了 uImage
4 /
打印了 uImage的信息
-- --
此时的关注点在
1 /
UIMAGE 是什么
2 /
uImage 打印信息中 的 Load Address 和 Entry Point 是什么
Load Address: 60004000
Entry Point: 60004000
tftp 0x60003000 uImage; bootm 0x60003000
正常启动.
## Booting kernel from Legacy Image at 60003000 . . .
Image Name: Linux- 4.0 .0
Image Type: ARM Linux Kernel Image ( uncompressed)
Data Size: 3409856 Bytes = 3.3 MiB
Load Address: 60004000
Entry Point: 60004000
Verifying Checksum . . . OK
## Flattened Device Tree blob at 60500000
Booting using the fdt blob at 0x60500000
Loading Kernel Image . . . OK
Loading Device Tree to 7f ed4000, end 7f eda6df . . . OK
Starting kernel . . .
kernel_entry addr : 60004000
Booting Linux on physical CPU 0x0
Initializing cgroup subsys cpuset
Linux version 4.0 .0 ( pop@ubuntu) ( gcc version 5.4 .0 20160609 ( Ubuntu/ Linaro 5.4 .0 - 6u buntu1~ 16.04 .9 ) ) #2 SMP Mon Oct 8 00 : 43 : 35 PDT 2018
-- -- -- -- -- --
追踪uboot 代码流程发现
Starting kernel . . . 之前, 有搬移内核, 并从60004000 启动
从 from: 60003040 搬移 到 to: 60004000
-- -- -- -- -- -- -- -
bootm 流程
do_bootm
do_bootm_states
bootm_load_os
bootm_decomp_image
do_bootm_linux
boot_prep_linux
boot_selected_os
do_bootm_linux
boot_jump_linux ( images, flag) ;
announce_and_cleanup
kernel_entry ( 0 , machid, r2) ;
Load Address: 60004000
Entry Point: 60004000
tftp 0x60004000 bootm 0x60004000
也进行了搬移
to: 60004000 , from: 60004040
Load Address: 60004040
Entry Point: 60004040
tftp 0x60004000 bootm 0x60004000
不搬移, 且打印 XIP Kernel Image . . .
-- -
Load Address: 60004040 Entry Point: 60004040 这样子的内核 是 我们 手动做出来的, 当然也可以 通过 make 生成.
/ bin/ bash . / scripts/ mkuboot. sh - A arm - O linux - C none - T kernel - a 0x60004040 - e 0x60004040 - n 'Linux-4.0.0' - d arch/ arm/ boot/ zImage arch/ arm/ boot/ uImage
Image Name: Linux- 4.0 .0
Created: Tue Oct 9 20 : 07 : 23 2018
Image Type: ARM Linux Kernel Image ( uncompressed)
Data Size: 3409856 Bytes = 3329.94 kB = 3.25 MB
Load Address: 60004040
Entry Point: 60004040
其他
if_changed_rule
# Usage: $(call if_changed_rule,foo)
# Will check if $(cmd_foo) or any of the prerequisites changed,
# and if so will execute $(rule_foo).
if_changed_rule = $( if $( strip $( any- prereq) $( arg- check) ) , \
@set - e; \
$( rule_$( 1 ) ) )
uboot 引导 zImage
uboot可以引导 zImage? 不可以
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 手动分隔
测试
Load Address: 60004040
Entry Point: 60004040
tftp 0x60004000 bootm 0x60004000
Wrong Image Format for bootm command
ERROR: can't get kernel image!
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 手动分隔
uboot 怎么引导zImage
可以修改uboot 来直接引导 zImage, 跳过 对 uImage头的解析