解决引导内核遇到undefined instruction的错误
其实在上一篇随笔之前,就是在启动linux 内核的时候,出了点问题
刚Starting kernel ...就出现了undefined instrction,这是什么问题呢?
在网上也搜了不少资料,有两篇很有启发
http://www.latelee.org/porting-uboot/u-boot-porting-booting-kernel.html
http://blog.csdn.net/liangkaiming/article/details/5986680
就是这两篇。
我们先来了解下mkimage这个命令,重要关注loadaddress和entry address
./mkimage -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'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
mkimage是将zImage之前加上64字节的镜像头
所以如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址是否相同。
(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之
(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部。
我们来看看这三个地址的不同情况:
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
这种情况 ,只能把 uImage download到 30008000的位置上,否则 从 30008040
是启动不了的。
原因:如果将uImage(加了头的镜像文件)下载到不同于指定加载地址的地方,则会进行上面的操作,将去掉头部的内核拷贝到指定的加载地址,此时加载地址和入口地址需要是相同的,因为已经没有镜像头了,所以此时入口地址也应该为30008000,而不应该再加上64个字节
所以在构建镜像头部中的加载地址和入口地址时千万要考虑下载的地址,否则将会启动不了。
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
这种情况download地址随便。 还是按上面说的,因为将加载地址和入口地址设置成同样的地址,在下载到任意地址时,将去掉头部的内核镜像拷贝到指定加载地址后,可以直接从加载地址开始启动。但是要是下载地址和指定加载地址相同呢?也就是下面的:
如果 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
下载地址一定要在指定的加载地址上。
所以,我在制作镜像头的时候没有自己动手制作,而是make uImage ARCH=arm CROSS_COMPILE=arm-linux-直接一步到位,所以启动的时候应该在0x30008040的位置启动!
看到这个图片还是很高兴的!!!