我之前发在 linuxforum上面, 不过讨论的人比较少 , 就贴在这里了。
具体可见:

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=embedded&Number=651003&page=0&view=collapsed&sb=5&o=0&fpart=1#Post651082

再读bootm源码,现象正常!

呵呵 , 原来 tftp download到是否是 hdr->ih_load(0x30008000) 确实是有说道的。
原来对bootm源码有个地方理解错了, bootm 会根据 hdr->ih_comp 判断是否需要解压, 对于
mkimage -C none 的是不需要解压的。

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
是启动不了的。
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 , 就从 0x30008040 启动就肯定OK 。
详细的请看代码。
研究了一下 u-boot-1.2.0 里面的 bootm的实现代码: do_bootm_linux() 函数 ,
原来由于我用mkimage的的时候的选项是 -C none , 所以下面的判断中 hdr->ih_comp =
IH_COMP_NONE
通过再读一遍代码, 也弄明白了上次问的问题, 就是 u-boot里面的解压和
内核自解压的区别: u-boot 里面的解压实际上是bootm 实现的 , 把 mkimage -C bzip2
或者gzip 生成的 uImage进行解压 ; 而kernel的自解压是对zImage进行解压,
发生在bootm解压之后。

呵呵 , 原来 tftp download到是否是 hdr->ih_load(0x30008000) 确实是有说道的。
原来对bootm源码有个地方理解错了, bootm 会根据 hdr->ih_comp 判断是否需要解压, 对于
mkimage -C none 的是不需要解压的。

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
是启动不了的。
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 , 就从 0x30008040 启动就肯定OK 。
详细的请看代码。
研究了一下 u-boot-1.2.0 里面的 bootm的实现代码: do_bootm_linux() 函数 ,
原来由于我用mkimage的的时候的选项是 -C none , 所以下面的判断中 hdr->ih_comp =
IH_COMP_NONE
通过再读一遍代码, 也弄明白了上次问的问题, 就是 u-boot里面的解压和
内核自解压的区别: u-boot 里面的解压实际上是bootm 实现的 , 把 mkimage -C bzip2
或者gzip 生成的 uImage进行解压 ; 而kernel的自解压是对zImage进行解压,
发生在bootm解压之后。

switch (hdr->ih_comp) {
case IH_COMP_NONE:
if(ntohl(hdr->ih_load) == addr) { //如果你是tftp 到 0x30008000那么这里就命中了。
printf (" XIP %s ... ", name); //tftp download 这里, 确实打印出来了。
} else { //否则随便download到一个地址, 流程就进入这里了。
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) //这个条件编译不成立
size_t l = len;
void *to = (void *)ntohl(hdr->ih_load);
void *from = (void *)data;
printf (" Loading %s ... ", name);
while (l > 0) {
size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
WATCHDOG_RESET();
memmove (to, from, tail);
to += tail;
from += tail;
l -= tail;
}
#else/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
------------------------实际执行的是这里---------------------------------
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
//从这里就可以看出一旦 tftpdownload到一个任意地址, bootm 都会把
//它(去掉header后的kernel搬运到0x30008000 的位置上,因此entry
//point 肯定要是 0x30008000 ,但是对于tftp 恰好download到
//0x30008000 的位置上的时候, 你会发现上面的代码中,就donothing
//了,因此就必须从 0x30008040

#endif/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
}
break;
case IH_COMP_GZIP:
printf (" Uncompressing %s ... ", name);
if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, // 把它解压到ih_load的位置上去
(uchar *)data, &len) != 0) {
puts ("GUNZIP ERROR - must RESET board to recover\n");
SHOW_BOOT_PROGRESS (-6);
do_reset (cmdtp, flag, argc, argv);
}
break;
.....
省略了 gzip和 bzip2的处理 , // 这里也说明 和 zImage的自解压是不一样的。
gzip : mkimage -C gzip ;
bzip2 mkimage -C bzip2 .
他是只uImage 本身被压缩了
default:
if (iflag)
enable_interrupts();
printf ("Unimplemented compression type %d\n", hdr->ih_comp);
SHOW_BOOT_PROGRESS (-7);
return 1;
}
//解压完毕,对于我得板子来说,是解压到 0x8000的位置上去了,这是个物理地址
puts ("OK\n");
SHOW_BOOT_PROGRESS (7);