bootm命令只能用来引导经过mkimage构建了镜像头的内核镜像文件以及根文件镜像,对于没有用mkimage对内核进行处理的话,那直接把内核下载到连接脚本中指定的加载地址0x30008000再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。
通过mkimage可以给内核镜像或根文件系统镜像加入一个用来记录镜像的各种信息的头。同样通过mkimage也可以将内核镜像进行一次压缩(指定-C none/gzip/bzip2),所以这里也就引申出了两个阶段的解压缩过程:第一个阶段是u-boot里面的解压缩,也就是将由mkimage压缩的镜像解压缩得到原始的没加镜像头的内核镜像。第二个阶段是内核镜像的自解压, u-boot 里面的解压实际上是bootm 实现的 , 把 mkimage -C bzip2或者gzip 生成的 uImage进行解压 ; 而kernel的自解压是对zImage进行解压,发生在bootm解压之后。
下面通过cmd_bootm.c文件中对bootm命令进行解析以及执行的过程来分析,这三种不同地址的区别:
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ...... if (argc < 2) {
......
// switch (hdr->ih_comp) { //开始判断利用mkimage命令后是否对内核镜像进行了压缩 memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); } case IH_COMP_GZIP://如果利用mkimage时对内核镜像进行了压缩,则需要在u-boot内进行第一阶段的解压缩,将解压后的内核镜像存放到指定的加载地址ih_load,然后内核镜像自解压启动
}
所以如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址是否相同。
我们来看看这三个地址的不同情况: 1> mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 原因:如果将uImage(加了头的镜像文件)下载到不同于指定加载地址的地方,则会进行上面的操作,将去掉头部的内核拷贝到指定的加载地址,此时加载地址和入口地址需要是相同的,因为已经没有镜像头了,所以此时入口地址也应该为30008000,而不应该再加上64个字节 所以在构建镜像头部中的加载地址和入口地址时千万要考虑下载的地址,否则将会启动不了。
所以在制作镜像头以及下载地址就有两种情况: 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 下载地址一定要在指定的加载地址上。 |
|
来自: chengong510 > 《嵌入式》