U-boot中启动内核的代码阅读

看了半天加抓了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

你可能感兴趣的:(linux,Stream,cmd,OS,header,table)