问题1:编译内核时候提示 mkimage" command not found - U-Boot images will not be built "
解决:
1)将经过编译后的uboot目录中tools目录下的mkimage的路径导入到系统环境变量;
2)将uboot目录中tools目录下的mkimage拷贝到系统usr/bin目录;
分析:
mkimage随着uboot的编译而得到,uboot的tools目录下有mkimage的代码,查看tools下的Makefile文件,看到编译时候使用的CC=$(HOSTCC),又结合ubuntu下通过apt-get install u-boot-tools得到的mkimage,分别用file查看mkimage看到都是x64的,而且uboot的tools目录下的mkimage也可以在ubuntu下运行,所以推测两者是一致的,采用任何一种方法都可以得到,都可以用于后面转化得到uImage。
问题2:make uImage得到的uImage,看到Load Address和Entry Point都是0
联想:在uboot的顶层Makefile中,可以看到$(obj) u-boot.img : $(obj) u-boot.bin
./tools/mkimage -A ... -T... -C ... -a... -e... -n... -d...
这样入口地址将会被传入;
在编译内核时候,make uImage的过程如下:
生成uImage的工具mkimage由arch/arm/boot/Makefile中的MKIMAGE定义:
MKIMAGE := $(srctree)/scripts/mkuboot.sh
mkuboot.sh的作用是去找到是否存在"mkimage",此工具是用来生成最后的uImage。
mkuboot.sh 首先检查toolchain是否拥有mkimage (使用-z来判空),如果没有,再检查系统中是否拥有mkimage;如果没有则报错。
然后调用:$mkimage "$@"
在老版本的内核中,通过mkimage来生成uImage的位置为arch/arm/boot/Makefile中:
- quiet_cmd_uimage = UIMAGE $@
- cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel /
- -C none -a $(LOADADDR) -e $(STARTADDR) /
- -n 'Linux-$(KERNELRELEASE)' -d $< $@
其中-a 参数的传入通过该Makefile下面语句:
- ZERLADDR := $(zreladdr -y)
-
- ifeq ($(CONFIG_ZBOOT_ROM),y)
- $(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)
- else
- $(obj)/uImage: LOADADDR=$(ZRELADDR)
- endif
$(obj)/uImage: STARTADDR=$(LOADADDR)
从makefile.boot中传入生成uImage的相关参数(e.g: arm/arm/mach-omap2/Makefile.boot)
- ifneq ($(MACHINE),)
- include $(srctree)/$(MACHINE)/Makefile.boot
- endif
由zImage生成uImage通过该Makefile的下面语句:
- $(obj)/uImage: $(obj)/zImage FORCE
- $(call if_changed,uimage)
- @echo ' Image $@ is ready'
注:zImage的生成过程:http://blog.csdn.net/voice_shen/article/details/17713441
当然,也可以手动的通过 mkimage -A arm -O linux -T kernel -C none -a <load_addr> -e <entry_addr> -n <name> -d zImage uImage生成uImage。
关于uImage的启动,注意下面几种情况:
1> mkimage -A arm -O linux -T kernel -C none -a 30008000 -e
30008040 -n linux-2.6.18.8 -d zImage uImage2.6.18.8-8040
使用mkimage生成内核镜像文件,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx(download addr)是否与-a指定的加载地址(load adrr)是否相同。
(1)如果不同的话,会从地址xxxx(download addr)开始提取出uImage的64byte的头部,对其进行分析,分析出load addr,然后把去掉头部的内核复制到load addr中,此时因为入口地址(enter addr)不等于load addr,所以内核启动不起来。
(2)如果相同的话,uImage原封不动的放在那,此时因为-e指定的入口地址为推后64byte,跳过了这64byte的头部。
所以把 uImage download到 30008000的位置上可以启动,否则从 30008040 是启动不了的。 2> mkimage -A arm -O linux -T kernel -C none -a 30008000 -e
30008000 -n linux-2.6.18.8 -d zImage uImage2.6.18.8-8000
(1)这种情况download地址随便,因为将加载地址和入口地址设置成同样的地址,在下载到任意地址时,将去掉头部的内核镜像拷贝到指定加载地址后,其实就是从加载地址开始启动。
(2)下载地址和指定加载地址相同,如果 tftp 下载地址==0x30008000 , 此时因为下载地址和指定加载地址相同,所以就不会搬动,内核直接从指定加载地址自解压啦,但是因为指定的入口地址也是0x30008000,还是在镜像头处,可以看到上面的代码,如果相同没有做任何事,只是打印了提示信息,所以还得将入口地址往后推后64个字节还是从 0x30008040 启动就肯定OK 。
所以在制作镜像头以及下载地址就有两种情况:
1,mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage zImage.img
加载地址和入口地址相同
tftp 0x31000000 zImage.img
bootm 0x31000000
下载地址可以任意放。
2,mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage zImage.img
入口地址在加载地址后面64个字节
tftp 0x30008000 zImage.img
bootm 0x30008000
下载地址一定要在指定的加载地址上。