do_bootm 函数分析

 

u-boot检测到bootm命令后,它将调用do_bootm这个函数进行内核引导:

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{

     ulong    iflag;

     ulong    addr;

     ulong    data, len, checksum;

     ulong  *len_ptr;

     uint unc_len = CFG_BOOTM_LEN;

     int  i, verify;

     char *name, *s;

     int  (*appl)(int, char *[]);

     image_header_t *hdr = &header;

 

/*

1、提取命令行中的地址参数。

*/

     s = getenv ("verify");

     verify = (s && (*s == 'n')) ? 0 : 1;

 

     if (argc < 2) {

         addr = load_addr;

     } else {

         addr = simple_strtoul(argv[1], NULL, 16);

     }

 

     SHOW_BOOT_PROGRESS (1);

     printf ("## Booting image at %08lx .../n", addr);

 

     /* Copy header so we can blank CRC field for re-calculation */

     memmove (&header, (char *)addr, sizeof(image_header_t));

 

/*

2、检测内核文件头的签名是否有效。

*/

     if (ntohl(hdr->ih_magic) != IH_MAGIC) {

         {

         puts ("Bad Magic Number/n");

         SHOW_BOOT_PROGRESS (-1);

         return 1;

         }

     }

     SHOW_BOOT_PROGRESS (2);

 

/*

3、通过CRC校验确定文件是否损坏。

*/

     data = (ulong)&header;

     len  = sizeof(image_header_t);

 

     checksum = ntohl(hdr->ih_hcrc);

     hdr->ih_hcrc = 0;

 

     if (crc32 (0, (uchar *)data, len) != checksum) {

         puts ("Bad Header Checksum/n");

         SHOW_BOOT_PROGRESS (-2);

         return 1;

     }

     SHOW_BOOT_PROGRESS (3);

 

/*

4、输出内核文件头的信息。

*/

     /* for multi-file images we need the data part, too */

     print_image_hdr ((image_header_t *)addr);

 

     data = addr + sizeof(image_header_t);

     len  = ntohl(hdr->ih_size);

 

     if (verify) {

         puts ("   Verifying Checksum ... ");

         if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {

              printf ("Bad Data CRC/n");

              SHOW_BOOT_PROGRESS (-3);

              return 1;

         }

         puts ("OK/n");

     }

     SHOW_BOOT_PROGRESS (4);

 

/*

5、检验内核是否为此ARCH编译的。

*/

     len_ptr = (ulong *)data;

 

     if (hdr->ih_arch != IH_CPU_BLACKFIN)

     {

         printf ("Unsupported Architecture 0x%x/n", hdr->ih_arch);

         SHOW_BOOT_PROGRESS (-4);

         return 1;

     }

     SHOW_BOOT_PROGRESS (5);

 

/*

6、判断文件类型,对于uclinux内核,其值为IH_TYPE_KERNEL

*/

     switch (hdr->ih_type) {

     case IH_TYPE_STANDALONE:

         name = "Standalone Application";

         /* A second argument overwrites the load address */

         if (argc > 2) {

              hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16));

         }

         break;

     case IH_TYPE_KERNEL:

         name = "Kernel Image";

         break;

     case IH_TYPE_MULTI:

         name = "Multi-File Image";

         len  = ntohl(len_ptr[0]);

         /* OS kernel is always the first image */

         data += 8; /* kernel_len + terminator */

         for (i=1; len_ptr[i]; ++i)

              data += 4;

         break;

     default: printf ("Wrong Image Type for %s command/n", cmdtp->name);

         SHOW_BOOT_PROGRESS (-5);

         return 1;

     }

     SHOW_BOOT_PROGRESS (6);

 

     /*

      * We have reached the point of no return: we are going to

      * overwrite all exception vector code, so we cannot easily

      * recover from any failures any more...

      */

/*

7、将内核解压缩到文件头中指定的Load Address,从这里也可以知道,下载地址和文件头中的LoadAddress之间应该有足够的空间,否则将造成解压缩的失败。

*/

 

     iflag = disable_interrupts();

 

     switch (hdr->ih_comp) {

     case IH_COMP_NONE:

         if(ntohl(hdr->ih_load) == addr) {

              printf ("   XIP %s ... ", name);

         } else {

              memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);

         }

         break;

     case IH_COMP_GZIP:

         printf ("   Uncompressing %s ... ", name);

         if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,

                  (uchar *)data, &len) != 0) {

              puts ("GUNZIP ERROR - must RESET board to recover/n");

              SHOW_BOOT_PROGRESS (-6);

              do_reset (cmdtp, flag, argc, argv);

         }

         break;

     default:

         if (iflag)

              enable_interrupts();

         printf ("Unimplemented compression type %d/n", hdr->ih_comp);

         SHOW_BOOT_PROGRESS (-7);

         return 1;

     }

     puts ("OK/n");

     SHOW_BOOT_PROGRESS (7);

 

/*

8、由于引导的是内核,跳过本段代码。

*/

     switch (hdr->ih_type) {

     case IH_TYPE_STANDALONE:

         if (iflag)

              enable_interrupts();

 

         /* load (and uncompress), but don't start if "autostart"

          * is set to "no"

          */

         if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {

              char buf[32];

              sprintf(buf, "%lX", len);

              setenv("filesize", buf);

              return 0;

         }

         appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);

         (*appl)(argc-1, &argv[1]);

         return 0;

     case IH_TYPE_KERNEL:

     case IH_TYPE_MULTI:

         /* handled below */

         break;

     default:

         if (iflag)

              enable_interrupts();

         printf ("Can't boot image type %d/n", hdr->ih_type);

         SHOW_BOOT_PROGRESS (-8);

         return 1;

     }

     SHOW_BOOT_PROGRESS (8);

 

/*

9、调用相应的函数进行内核引导。

*/

     switch (hdr->ih_os) {

     default:           /* handled by (original) Linux case */

     case IH_OS_LINUX:

         do_bootm_linux  (cmdtp, flag, argc, argv,

                   addr, len_ptr, verify);

         break;

     case IH_OS_NETBSD:

         do_bootm_netbsd (cmdtp, flag, argc, argv,

                   addr, len_ptr, verify);

         break;

 

     case IH_OS_RTEMS:

         do_bootm_rtems (cmdtp, flag, argc, argv,

                   addr, len_ptr, verify);

         break;

 

     }

 

     SHOW_BOOT_PROGRESS (-9);

     return 1;

}

这个函数看着挺长的,其实无非就是将内核解压缩,然后调用do_bootm_linux引导内核。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值