看了半天加抓了log,就以log为起点。
CPU: S3C6410@532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: MINI6410
DRAM: 128 MB
Flash: 0 kB
NAND: 256 MB
In: serial
Out: serial
Err: serial
MAC: 08:90:90:90:90:90
Hit any key to stop autoboot: 0
in_str data
peek: C7E1339C, get: C7E13380, __promptme: 1, promptmode: 1, p: nand read.i c00080
parse_stream, end_trigger=10
hush.c 3200
hush.c 3207
hush.c:run_list_real rmode=0 if_code=0 next_if_code=0 skip_more=11
hush.c run_pipe_real 1574
hush.c run_pipe_real 1711, run the command
NAND read: device 0 offset 0x80000, size 0x500000
我猜前面都是应该在分析命令,最后调用到了hush.c : run_pipe_real函数。在这个函数中才调用了命令对应的函数。
rcode = (cmdtp->cmd)
(cmdtp, flag,child->argc-i,&child->argv[i]);
感觉uboot用了类似任务的概念。
跟着看cmdtp怎么来的。
cmdtp = find_cmd(child->argv[i]))
好,是从这个函数找过来的。 这是从一个table中找,然后悲剧。这个table的起始位置叫__u_boot_cmd_start 。
搜了代码没找到。在一个叫u-boot.lds的文件中有这个东东。
现在我看过了,这是个高级的编译脚本。
根据这个找到的命令函数,使用下面的语句来执行这个命令。
rcode = (cmdtp->cmd) (cmdtp, flag,child->argc-i,&child->argv[i]);
Example: bootm
比如说bootm命令,经过搜索,这个命令对应着do_bootm函数。这个命令就是用来启动kernel的。
在我的板子上,运行的linux的zimage,就会运行下面这段。
#ifdef CONFIG_ZIMAGE_BOOT
#define LINUX_ZIMAGE_MAGIC 0x016f2818
if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
printf("Boot with zImage /n");
addr = virt_to_phys(addr);
hdr->ih_os = IH_OS_LINUX ;
hdr->ih_ep = ntohl(addr) ;
goto after_header_check;
}
#endif
上面这个标为蓝色的代码,就是赋值了跳转到kernel的第一个指令的地址。
接下来跳转到了after_header_check段,执行了下面的代码
case IH_OS_LINUX :
#ifdef CONFIG_SILENT_CONSOLE
fixup_silent_linux();
#endif
printf("do_bootm_linux linux boots at here %s/n", __FILE__);
do_bootm_linux (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
其实也就是调用了do_bootm_linux函数,这个函数在lib_arm/armlinux.c文件中(对于我的mini6440来说)。
里面有:
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
看到这个就是将刚才的值赋给了theKernel,以备之后跳转用到。
之后做了些设置,然后就跳转到theKernel了。
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
bd->bi_boot_params里面的值,就是前面设置的地方,具体用来干什么,还有待进一步分析。
那这个theKernel到底是什么地方呢? 通过debug,知道这个值是0x50008000. 我grep了一下kernel的目录,发现有这么一个命令。
arch/arm/boot/compressed/.vmlinux.cmd:cmd_arch/arm/boot/compressed/vmlinux := arm-linux-ld -EL --defsym zreladdr=0x50008000 --defsym params_phys=0x50000100 -p --no-undefined -X /home/wyang2/test/usr/local/arm/4.4.1/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.1/libgcc.a -T arch/arm/boot/compressed/vmlinux.lds arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/misc.o -o arch/arm/boot/compressed/vmlinux
这个是编译vmlinux的命令,那可以看出0x50008000这个地址对应的是zreladdr这个符号。 那就要去看看这个符号对应的是什么了。
这个符号在arch/arm/boot/compressed/head.S中,但是真的是跳转到这么?我不懂了。
有个帖子是说这个head.S的,
http://gicl.cs.drexel.edu/people/sevy/linux/ARM_Linux_boot_sequence.html