Chinaunix首页 | 论坛 | 博客
  • 博客访问: 477834
  • 博文数量: 174
  • 博客积分: 2502
  • 博客等级: 少校
  • 技术积分: 1923
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-28 09:47
文章分类

全部博文(174)

文章存档

2011年(8)

2010年(16)

2009年(68)

2008年(82)

我的朋友

分类: 嵌入式

2009-09-03 21:09:11

   1 // MPC8360EAMDS ltib U-Boot-1.2.0 common/cmd_bootm.c  --- by starby
   2 //
   3 // bootm命令分析
   4 // 基于PowerPC CPU.  主要按bootm  kern_addr ramdisk_addr [fdt_addr]代码流程分析
   5 //
   6 // 重要参数CFG_BOOTMAPSZ界定了传给内核的启动参数,bd info 及 of 的地址上界
   7 //
   8 // bootm命令用于启动mkimage命令制作的镜像,mkimage会在Data数据前添加64字节的Header
   9 // 此Header结构的ih_load(Data Load Address)指定了搬运Dada数据的目的地址
  10 // 对于内核,此Header结构的ih_ep(Entry Point Address)指定了内核入口函数的地址
  11 // 除非特殊需要,ramdisk镜像的ih_load和ih_ep可以指定为0
  12 // fdt镜像Header结构ih_load需谨慎,防止搬运时覆盖
  13 //
  14 // 如果定义了CONFIG_OF_LIBFDT,会对fdt镜像的of_flat_tree添加一些节点,具体看下面定义
  15 // 若定义了CONFIG_OF_LIBFDT,并给出bootm命令参数fdt_addr,则会将fdt结构传给内核;否
  16 // 则仍然将bd info结构传给内核。它们以不同的形式使用内核入口函数(void *)kernel(...)
  17
  18 #include
  19 #include
  20 #include
  21 #include
  22 #include
  23 #include
  24 #include
  25 #include
  26 #include
  27 #if defined(CONFIG_OF_LIBFDT)
  28 #include
  29 #include
  30 #include
  31 #endif
  32 #if defined(CONFIG_OF_FLAT_TREE)
  33 #include
  34 #endif
  35 DECLARE_GLOBAL_DATA_PTR;
  36 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  37 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
  38 #include
  39 #endif
  40 #ifdef CFG_HUSH_PARSER
  41 #include
  42 #endif
  43 #ifdef CFG_INIT_RAM_LOCK
  44 #include
  45 #endif
  46 /*
  47  * Some systems (for example LWMON) have very short watchdog periods;
  48  * we must make sure to split long operations like memmove() or
  49  * crc32() into reasonable chunks.
  50  */
  51 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  52 # define CHUNKSZ (64 * 1024)
  53 #endif
  54 int  gunzip (void *, int, unsigned char *, unsigned long *);
  55 static void *zalloc(void *, unsigned, unsigned);
  56 static void zfree(void *, void *, unsigned);
  57
  58 #if defined(CONFIG_CMD_IMI)
  59 static int image_info (unsigned long addr);
  60 #endif
  61 #if defined(CONFIG_CMD_IMLS)
  62 #include
  63 extern flash_info_t flash_info[]; /* info for FLASH chips */
  64 static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  65 #endif
  66 static void print_type (image_header_t *hdr);
  67 #ifdef __I386__
  68 image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);
  69 #endif
  70 /*
  71  *  Continue booting an OS image; caller already has:
  72  *  - copied image header to global variable `header'
  73  *  - checked header magic number, checksums (both header & image),
  74  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
  75  *  - loaded (first part of) image to header load address,
  76  *  - disabled interrupts.
  77  */
  78 typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
  79               int    argc, char *argv[],
  80               ulong addr,       /* of image to boot */
  81               ulong *len_ptr,   /* multi-file image length table */
  82               int    verify);    /* getenv("verify")[0] != 'n' */
  83 #ifdef  DEBUG
  84 extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  85 #endif
  86 #ifdef CONFIG_PPC       // 定义在ppc_config.mk PLATFORM_CPPFLAGS += -DCONFIG_PPC
  87 static boot_os_Fcn do_bootm_linux;  // 使用本文件中的do_bootm_linux
  88 #else
  89 extern boot_os_Fcn do_bootm_linux;
  90 #endif
  91 #ifdef CONFIG_SILENT_CONSOLE
  92 static void fixup_silent_linux (void);
  93 #endif
  94 /* include/image.h */
  95 #define IH_MAGIC    0x27051956 /* Image Magic Number       */
  96 #define IH_NMLEN        32    /* Image Name Length       */
  97 typedef struct image_header {   // mkimage命令制作的镜像会按此结构在镜像文件头中添加64个字节的信息
  98     uint32_t   ih_magic;   /* Image Header Magic Number    */
  99     uint32_t   ih_hcrc;    /* Image Header CRC Checksum */
 100     uint32_t   ih_time;    /* Image Creation Timestamp  */
 101     uint32_t   ih_size;    /* Image Data Size       */
 102     uint32_t   ih_load;    /* Data   Load  Address      */
 103     uint32_t   ih_ep;      /* Entry Point Address        */
 104     uint32_t   ih_dcrc;    /* Image Data CRC Checksum   */
 105     uint8_t        ih_os;      /* Operating System       */
 106     uint8_t        ih_arch;    /* CPU architecture      */
 107     uint8_t        ih_type;    /* Image Type            */
 108     uint8_t        ih_comp;    /* Compression Type      */
 109     uint8_t        ih_name[IH_NMLEN];  /* Image Name */
 110 } image_header_t;                   // 64字节
 111
 112 image_header_t header;              // 全局数据header
 113
 114 U_BOOT_CMD(                         // bootm命令说明, 此命令将调用下面的do_bootm函数
 115     bootm,  CFG_MAXARGS,    1,    do_bootm,
 116     "bootm   - boot application image from memory\n",
 117     "[addr [arg ...]]\n    - boot application image stored in memory\n"
 118     "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
 119     "\t'arg' can be the address of an initrd image\n"
 120 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) // 请看下面源码
 121     "\tWhen booting a Linux kernel which requires a flat device-tree\n"
 122     "\ta third argument is required which is the address of the of the\n"
 123     "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
 124     "\tuse a '-' for the second argument. If you do not pass a third\n"
 125     "\ta bd_info struct will be passed instead\n"
 126 #endif
 127 );
 128 #ifndef CFG_BOOTM_LEN
 129 #define CFG_BOOTM_LEN   0x800000  /* use 8MByte as default max gunzip size */
 130 #endif
 131
 132 ulong load_addr = CFG_LOAD_ADDR;        /* Default Load Address */
 133
 134 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 135                         // argc 是bootm命令的参数个数
 136                         // argv 指向bootm命令的参数列表 bootm [xx] [xx] [xx]
 137 {
 138     ulong   iflag;
 139     ulong   addr;
 140     ulong   data, len, checksum;
 141     ulong  *len_ptr;
 142     uint    unc_len = CFG_BOOTM_LEN;
 143     int    i, verify;
 144     char   *name, *s;
 145     int    (*appl)(int, char *[]);        // 应用程序函数指针
 146     image_header_t *hdr = &header;  // pointer to header
 147
 148     s = getenv ("verify");
 149     verify = (s && (*s == 'n')) ? 0 : 1;   // 是否对镜像Data进行校验
 150
 151     if (argc < 2) {            
 152         addr = load_addr;           // bootm命令没参数时,使用默认地址
 153     } else {
 154         addr = simple_strtoul(argv[1], NULL, 16);  // bootm image_addr [...] 否则取出镜像地址
 155     }
 156
 157     show_boot_progress (1);
 158     printf ("## Booting image at %08lx ...\n", addr);  // 打印镜像地址
 159
 160     /* Copy header so we can blank CRC field for re-calculation */
 161 #ifdef CONFIG_HAS_DATAFLASH
 162     if (addr_dataflash(addr)){
 163         read_dataflash(addr, sizeof(image_header_t), (char *)&header);
 164     } else
 165 #endif
 166     memmove (&header, (char *)addr, sizeof(image_header_t)); // memmove(dst, src, count);
 167                             // 将镜像Header信息64字节复制到header中
 168
 169     if (ntohl(hdr->ih_magic) != IH_MAGIC) {    // 镜像Header信息魔数校验
 170 #ifdef __I386__ /* correct image format not implemented yet - fake it */
 171         if (fake_header(hdr, (void*)addr, -1) != NULL) {
 172             /* to compensate for the addition below */
 173             addr -= sizeof(image_header_t);
 174             /* turnof verify,
 175              * fake_header() does not fake the data crc
 176              */
 177             verify = 0;
 178         } else
 179 #endif  /* __I386__ */
 180         {
 181         puts ("Bad Magic Number\n");      // 错误,退出
 182         show_boot_progress (-1);
 183         return 1;
 184         }
 185     }
 186     show_boot_progress (2);
 187
 188     data = (ulong)&header;              // 全局数据header地址
 189     len  = sizeof(image_header_t);     // len = 64
 190
 191     checksum = ntohl(hdr->ih_hcrc);     // 镜像Header的原Header 64字节校验值
 192     hdr->ih_hcrc = 0;
 193
 194     if (crc32 (0, (uchar *)data, len) != checksum) {   // Header完整性校验
 195         puts ("Bad Header Checksum\n");
 196         show_boot_progress (-2);
 197         return 1;
 198     }
 199     show_boot_progress (3);
 200
 201 #ifdef CONFIG_HAS_DATAFLASH
 202     if (addr_dataflash(addr)){
 203         len  = ntohl(hdr->ih_size) + sizeof(image_header_t);
 204         read_dataflash(addr, len, (char *)CFG_LOAD_ADDR);
 205         addr = CFG_LOAD_ADDR;
 206     }
 207 #endif
 208
 209     /* for multi-file images we need the data part, too */
 210     print_image_hdr ((image_header_t *)addr);  // 根据镜像Header信息输出镜像信息
 211
 212     data = addr + sizeof(image_header_t);  // data值为镜像Header后镜像Data的起始地址
 213     len  = ntohl(hdr->ih_size);             // 镜像Data的大小(不包含镜像Header)
 214
 215     if (verify) {
 216         puts ("   Verifying Checksum ... ");
 217         if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { // 镜像Data完整性校验
 218             printf ("Bad Data CRC\n");
 219             show_boot_progress (-3);
 220             return 1;
 221         }
 222         puts ("OK\n");
 223     }
 224     show_boot_progress (4);
 225
 226     len_ptr = (ulong *)data;        // len_ptr指向镜像Data起始地址
 227
 228 #if defined(__ARM__)
 229     if (hdr->ih_arch != IH_CPU_ARM)
 230 #elif defined(__avr32__)
 231     if (hdr->ih_arch != IH_CPU_AVR32)
 232 #elif defined(__bfin__)
 233     if (hdr->ih_arch != IH_CPU_BLACKFIN)
 234 #elif defined(__I386__)
 235     if (hdr->ih_arch != IH_CPU_I386)
 236 #elif defined(__nios2__)
 237     if (hdr->ih_arch != IH_CPU_NIOS2)
 238 #elif defined(__PPC__)              // config.mk中根据ARCH为ppc来定义 __PPC__
 239     if (hdr->ih_arch != IH_CPU_PPC) // include/image.h中 #define CPU Architecture
 240 #else
 241 # error Unknown CPU type            // 未知CPU,退出
 242 #endif
 243     {
 244         printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);
 245         show_boot_progress (-4);
 246         return 1;
 247     }
 248     show_boot_progress (5);
 249
 250     switch (hdr->ih_type) {            // 镜像类型Type      
 251     case IH_TYPE_STANDALONE:       /* "Standalone Program" 应用程序 */
 252         name = "Standalone Application";
 253         /* A second argument overwrites the load address */
 254         if (argc > 2) {
 255             hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); // 镜像Data Load 地址
 256         }
 257         break;
 258     case IH_TYPE_KERNEL:           /* OS Kernel Image */
 259         name = "Kernel Image";
 260         break;
 261     case IH_TYPE_MULTI:                /* Multi-File Image */
 262         name = "Multi-File Image";
 263         len  = ntohl(len_ptr[0]);
 264         /* OS kernel is always the first image */
 265         data += 8; /* kernel_len + terminator */
 266         for (i=1; len_ptr[i]; ++i)
 267             data += 4;
 268         break;
 269     default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
 270         show_boot_progress (-5);
 271         return 1;
 272     }
 273     show_boot_progress (6);
 274
 275     /*
 276      * We have reached the point of no return: we are going to
 277      * overwrite all exception vector code, so we cannot easily
 278      * recover from any failures any more...
 279      */
 280     iflag = disable_interrupts();       // lib_ppc/interrupts.c 禁止中断,保存原寄存器标志
 281
 282 #ifdef CONFIG_AMIGAONEG3SE
 283     /*
 284      * We've possible left the caches enabled during
 285      * bios emulation, so turn them off again
 286      */
 287     icache_disable();
 288     invalidate_l1_instruction_cache();
 289     flush_data_cache();
 290     dcache_disable();
 291 #endif
 292
 293     switch (hdr->ih_comp) {            // 镜像压缩格式Compression Type
 294     case IH_COMP_NONE:             /* No Compression Used */
 295         if(ntohl(hdr->ih_load) == addr) {
 296             printf ("   XIP %s ... ", name);
 297         } else {
 298 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 299             size_t l = len;
 300             void *to = (void *)ntohl(hdr->ih_load);
 301             void *from = (void *)data;
 302
 303             printf ("   Loading %s ... ", name);
 304
 305             while (l > 0) {
 306                 size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
 307                 WATCHDOG_RESET();
 308                 memmove (to, from, tail);
 309                 to += tail;
 310                 from += tail;
 311                 l -= tail;
 312             }
 313 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
 314             memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
 315                         // 直接将镜像Data复制到 Load 地址
 316 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
 317         }
 318         break;
 319     case IH_COMP_GZIP:                 /* gzip Compression Used */
 320         printf ("   Uncompressing %s ... ", name);
 321         if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, // gunzip(dst, dstlen, src, lenp)解压
 322                 (uchar *)data, &len) != 0) {             // 将镜像Data解压缩到镜像 Load 地址
 323             puts ("GUNZIP ERROR - must RESET board to recover\n");
 324             show_boot_progress (-6);
 325             do_reset (cmdtp, flag, argc, argv);
 326         }
 327         break;
 328 #ifdef CONFIG_BZIP2         /* BZIP2 Support */
 329     case IH_COMP_BZIP2:                                /* bzip2 Compression Used */
 330         printf ("   Uncompressing %s ... ", name);
 331         /*
 332          * If we've got less than 4 MB of malloc() space,
 333          * use slower decompression algorithm which requires
 334          * at most 2300 KB of memory.
 335          */
 336         i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),   // bzip2解压
 337                         &unc_len, (char *)data, len,          // 将镜像Data解压缩到镜像 Load 地址
 338                         CFG_MALLOC_LEN < (4096 * 1024), 0);
 339         if (i != BZ_OK) {
 340             printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
 341             show_boot_progress (-6);
 342             do_reset (cmdtp, flag, argc, argv);
 343         }
 344         break;
 345 #endif /* CONFIG_BZIP2 */
 346     default:                           /* Unimplemented Compression Type */
 347         if (iflag)
 348             enable_interrupts();        
 349         printf ("Unimplemented compression type %d\n", hdr->ih_comp);
 350         show_boot_progress (-7);
 351         return 1;
 352     }
 353     puts ("OK\n");
 354     show_boot_progress (7);
 355
 356     switch (hdr->ih_type) {                // 镜像 Type  
 357     case IH_TYPE_STANDALONE:           /* Standalone Program */
 358         if (iflag)
 359             enable_interrupts();
 360
 361         /* load (and uncompress), but don't start if "autostart"
 362          * is set to "no"
 363          */
 364         if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {
 365             char buf[32];
 366             sprintf(buf, "%lX", len);
 367             setenv("filesize", buf);
 368             return 0;
 369         }
 370         appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);     // 程序入口
 371         (*appl)(argc-1, &argv[1]);                            // 执行程序
 372         return 0;
 373     case IH_TYPE_KERNEL:       /* OS Kernel Image */    // 内核,以后处理
 374     case IH_TYPE_MULTI:            /* Multi-File Image */
 375         /* handled below */
 376         break;
 377     default:
 378         if (iflag)
 379             enable_interrupts();
 380         printf ("Can't boot image type %d\n", hdr->ih_type);
 381         show_boot_progress (-8);
 382         return 1;
 383     }
 384     show_boot_progress (8);
 385
 386     switch (hdr->ih_os) {                          // 镜像 Operating System    
 387     default:           /* handled by (original) Linux case */
 388     case IH_OS_LINUX:                              // Linux OS 内核
 389 #ifdef CONFIG_SILENT_CONSOLE
 390         fixup_silent_linux();       /* Silent CONSOLE setup */
 391 #endif
 392         do_bootm_linux  (cmdtp, flag, argc, argv,
 393                  addr, len_ptr, verify);            // 调用函数do_bootm_linux
 394                  // cmdtp, flag, argc, argv为 do_bootm()参数,addr为bootm命令参数地址或默认启动地址
 395                  // argc 为bootm命令参数个数,argv指向bootm命令参数列表
 396                  // len_ptr指向镜像Data起始地址(addr+64), verify是否校验标志
 397         break;
 398     case IH_OS_NETBSD:         /* NetBSD */
 399         do_bootm_netbsd (cmdtp, flag, argc, argv,
 400                  addr, len_ptr, verify);
 401         break;
 402
 403 #ifdef CONFIG_LYNXKDI
 404     case IH_OS_LYNXOS:         /* LynxOS */
 405         do_bootm_lynxkdi (cmdtp, flag, argc, argv,
 406                  addr, len_ptr, verify);
 407         break;
 408 #endif
 409
 410     case IH_OS_RTEMS:          /* RTEMS */
 411         do_bootm_rtems (cmdtp, flag, argc, argv,
 412                  addr, len_ptr, verify);
 413         break;
 414
 415 #if defined(CONFIG_CMD_ELF)
 416     case IH_OS_VXWORKS:            /* VxWorks */
 417         do_bootm_vxworks (cmdtp, flag, argc, argv,
 418                   addr, len_ptr, verify);
 419         break;
 420     case IH_OS_QNX:
 421         do_bootm_qnxelf (cmdtp, flag, argc, argv,
 422                   addr, len_ptr, verify);
 423         break;
 424 #endif
 425 #ifdef CONFIG_ARTOS
 426     case IH_OS_ARTOS:          /* ARTOS */
 427         do_bootm_artos  (cmdtp, flag, argc, argv,
 428                  addr, len_ptr, verify);
 429         break;
 430 #endif
 431     }
 432
 433     show_boot_progress (-9);
 434 #ifdef DEBUG
 435     puts ("\n## Control returned to monitor - resetting...\n");
 436     do_reset (cmdtp, flag, argc, argv);     /* cpu/mpc83xx/cpu.c */
 437 #endif
 438     return 1;
 439 }
 440
 441
 442 #ifdef CONFIG_SILENT_CONSOLE
 443 static void
 444 fixup_silent_linux ()
 445 {
 446     char buf[256], *start, *end;
 447     char *cmdline = getenv ("bootargs");
 448
 449     /* Only fix cmdline when requested */
 450     if (!(gd->flags & GD_FLG_SILENT))      // Silent mode
 451         return;
 452
 453     debug ("before silent fix-up: %s\n", cmdline);
 454     if (cmdline) {
 455         if ((start = strstr (cmdline, "console=")) != NULL) {
 456             end = strchr (start, ' ');
 457             strncpy (buf, cmdline, (start - cmdline + 8));
 458             if (end)
 459                 strcpy (buf + (start - cmdline + 8), end);
 460             else
 461                 buf[start - cmdline + 8] = '\0';
 462         } else {
 463             strcpy (buf, cmdline);
 464             strcat (buf, " console=");
 465         }
 466     } else {
 467         strcpy (buf, "console=");
 468     }
 469
 470     setenv ("bootargs", buf);
 471     debug ("after silent fix-up: %s\n", buf);
 472 }
 473 #endif /* CONFIG_SILENT_CONSOLE */
 474
 475 #ifdef CONFIG_PPC                   // 定义在ppc_config.mk PLATFORM_CPPFLAGS += -DCONFIG_PPC
 476 static void  __attribute__((noinline))      // do_bootm_linux不能作为inline函数被gcc优化
 477 do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
 478         int   argc, char *argv[],
 479         ulong   addr,
 480         ulong   *len_ptr,
 481         int   verify)
 482 {
 483     ulong   sp;
 484     ulong   len, checksum;
 485     ulong   initrd_start, initrd_end;
 486     ulong   cmd_start, cmd_end;
 487     ulong   initrd_high;
 488     ulong   data;
 489     int    initrd_copy_to_ram = 1;
 490     char    *cmdline;
 491     char   *s;
 492     bd_t    *kbd;
 493     void   (*kernel)(bd_t *, ulong, ulong, ulong, ulong); // 内核入口函数指针
 494     image_header_t *hdr = &header;      // hdr 指向全局数据header
 495 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 496     char   *of_flat_tree = NULL;
 497     ulong   of_data = 0;
 498 #endif
 499
 500     if ((s = getenv ("initrd_high")) != NULL) {
 501         /* a value of "no" or a similar string will act like 0,
 502          * turning the "load high" feature off. This is intentional.
 503          */
 504         initrd_high = simple_strtoul(s, NULL, 16);
 505         if (initrd_high == ~0)
 506             initrd_copy_to_ram = 0;
 507     } else {   /* not set, no restrictions to load high */
 508         initrd_high = ~0;     // initrd_high = 0xFFFF_FFFF
 509     }
 510
 511 #ifdef CONFIG_LOGBUFFER
 512     kbd=gd->bd;
 513     /* Prevent initrd from overwriting logbuffer */
 514     if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD))
 515         initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD;
 516     debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN);
 517 #endif
 518
 519     /*
 520      * Booting a (Linux) kernel image
 521      *
 522      * Allocate space for command line and board info - the
 523      * address should be as high as possible within the reach of
 524      * the kernel (see CFG_BOOTMAPSZ settings), but in unused
 525      * memory, which means far enough below the current stack
 526      * pointer.
 527      */
 528
 529     asm( "mr %0,1": "=r"(sp) : );      // 栈指针r1 赋给sp
 530
 531     debug ("## Current stack ends at 0x%08lX ", sp);
 532
 533     sp -= 2048;        /* just to be sure . For Safety*/
 534     if (sp > CFG_BOOTMAPSZ)
 535         sp = CFG_BOOTMAPSZ;
 536     sp &= ~0xF;            /* 16Bytes alignment */
 537             /* 
 538              * CFG_BOOTMAPSZ: Linux 内核启动代码的最大内存映射大小。all data that
 539              *      must be processed by the Linux kernel (bd_info, boot arguments,
 540              *      eventually initrd image) must be put below this limit.
 541              */
 542
 543     debug ("=> set upper limit to 0x%08lX\n", sp);     // 显示上界
 544
 545     cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);    
 546     kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
 547                     // cmdline 指向预留启动参数Buffer地址
 548                     // kbd 指向预留板子信息结构体bd_t地址
 549
 550     if ((s = getenv("bootargs")) == NULL)
 551         s = "";
 552
 553     strcpy (cmdline, s);        // 将启动参数Boot Arguments复制到预留空间
 554
 555     cmd_start    = (ulong)&cmdline[0];         // cmd_start 启动参数空间起始地址值
 556     cmd_end      = cmd_start + strlen(cmdline); // cmd_end 启动参数结束地址值
 557
 558     *kbd = *(gd->bd);       // 将bd info bd_t复制到预留空间
 559
 560 #ifdef  DEBUG
 561     printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
 562
 563     do_bdinfo (NULL, 0, 0, NULL);  // 显示bd info
 564 #endif
 565
 566     if ((s = getenv ("clocks_in_mhz")) != NULL) {
 567         /* convert all clock information to MHz */
 568         kbd->bi_intfreq /= 1000000L;
 569         kbd->bi_busfreq /= 1000000L;
 570 #if defined(CONFIG_MPC8220)
 571         kbd->bi_inpfreq /= 1000000L;
 572         kbd->bi_pcifreq /= 1000000L;
 573         kbd->bi_pevfreq /= 1000000L;
 574 #endif
 575     }
 576
 577     kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong)) ntohl(hdr->ih_ep);
 578                 // kernel指向镜像Entry Point地址,强制转化为内核入口函数指针。
 579                 // 此地址和mkimage命令有关
 580
 581     /*
 582      * Check if there is an initrd image
 583      */
 584
 585 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)       // #if defined
 586     /* Look for a '-' which indicates to ignore the ramdisk argument */
 587     if (argc >= 3 && strcmp(argv[2], "-") ==  0) { // U-Boot命令: bootm kern_addr - [fdt_addr]
 588         debug ("Skipping initrd\n");
 589         len = data = 0;
 590     }
 591     else
 592 #endif
 593     if (argc >= 3) {                    // U-Boot命令: bootm kern_addr ramdisk_addr [fdt_addr]
 594         debug ("Not skipping initrd\n");
 595         show_boot_progress (9);
 596
 597         addr = simple_strtoul(argv[2], NULL, 16); // ramdisk addr
 598
 599         printf ("## Loading RAMDisk Image at %08lx ...\n", addr);
 600
 601         /* Copy header so we can blank CRC field for re-calculation */
 602         memmove (&header, (char *)addr, sizeof(image_header_t));  // 将ramdisk镜像Header复制到header
 603
 604         if (ntohl(hdr->ih_magic)  != IH_MAGIC) {          // 镜像Header的魔数校验
 605             puts ("Bad Magic Number\n");
 606             show_boot_progress (-10);
 607             do_reset (cmdtp, flag, argc, argv);
 608         }
 609
 610         data = (ulong)&header;
 611         len  = sizeof(image_header_t);
 612
 613         checksum = ntohl(hdr->ih_hcrc);
 614         hdr->ih_hcrc = 0;
 615
 616         if (crc32 (0, (uchar *)data, len) != checksum) {  // ramdisk镜像Header完整性校验
 617             puts ("Bad Header Checksum\n");
 618             show_boot_progress (-11);
 619             do_reset (cmdtp, flag, argc, argv);
 620         }
 621
 622         show_boot_progress (10);
 623
 624         print_image_hdr (hdr);                      // 根据Header打印ramdisk镜像信息
 625
 626         data = addr + sizeof(image_header_t);     // data值为ramdisk镜像Data 起始地址
 627         len  = ntohl(hdr->ih_size);                 // ramdisk镜像Data长度
 628
 629         if (verify) {                 // 是否需要进行ramdisk镜像Data数据完整性校验
 630             ulong csum = 0;
 631 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 632             ulong cdata = data, edata = cdata + len;
 633 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
 634
 635             puts ("   Verifying Checksum ... ");
 636
 637 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 638
 639             while (cdata < edata) {
 640                 ulong chunk = edata - cdata;
 641
 642                 if (chunk > CHUNKSZ)
 643                     chunk = CHUNKSZ;
 644                 csum = crc32 (csum, (uchar *)cdata, chunk);
 645                 cdata += chunk;
 646
 647                 WATCHDOG_RESET();
 648             }
 649 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
 650             csum = crc32 (0, (uchar *)data, len);
 651 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
 652
 653             if (csum != ntohl(hdr->ih_dcrc)) {       // ramdisk镜像Data数据完整性校验
 654                 puts ("Bad Data CRC\n");
 655                 show_boot_progress (-12);
 656                 do_reset (cmdtp, flag, argc, argv);
 657             }
 658             puts ("OK\n");
 659         }
 660
 661         show_boot_progress (11);
 662
 663         if ((hdr->ih_os   != IH_OS_LINUX) ||      // 根据Header检验是否为Linux PPC Ramdisk镜像  
 664             (hdr->ih_arch != IH_CPU_PPC)    ||
 665             (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
 666             puts ("No Linux PPC Ramdisk Image\n");
 667             show_boot_progress (-13);
 668             do_reset (cmdtp, flag, argc, argv);     // 否则重启 (cpu/mpc83xx/cpu.c)
 669         }
 670         /*
 671          * Now check if we have a multifile image
 672          */
 673     } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
 674                             // <==> if (argc < 3) && multifile 镜像 && len_ptr[1]
 675                             // U-Boot命令: bootm  multifile_image_addr
 676         u_long tail    = ntohl(len_ptr[0]) % 4;
 677         int i;
 678
 679         show_boot_progress (13);
 680
 681         /* skip kernel length and terminator */
 682         data = (ulong)(&len_ptr[2]);
 683         /* skip any additional image length fields */
 684         for (i=1; len_ptr[i]; ++i)
 685             data += 4;
 686         /* add kernel length, and align */
 687         data += ntohl(len_ptr[0]);
 688         if (tail) {
 689             data += 4 - tail;
 690         }
 691
 692         len   = ntohl(len_ptr[1]);
 693
 694     } else {       // U-Boot命令: bootm [image_addr]
 695         /*
 696          * no initrd image
 697          */
 698         show_boot_progress (14);
 699
 700         len = data = 0;
 701     }
 702
 703 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 704     if(argc > 3) {                             // U-Boot命令: bootm kern_addr (ramdisk_addr/-) fdt_addr
 705         of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); // of_flat_tree 值为 fdt_addr
 706         hdr = (image_header_t *)of_flat_tree;   // hdr指向fdt_addr 强制转为image_header_t指针
 707 #if defined(CONFIG_OF_FLAT_TREE)                // 去掉镜像Header,校验marker
 708         if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {    
 709 #else
 710         if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { // libfdt/fdt.c
 711 #endif
 712 #ifndef CFG_NO_FLASH                            // not defined
 713             if (addr2info((ulong)of_flat_tree) != NULL)
 714                 of_data = (ulong)of_flat_tree;  // fdt_addr值
 715 #endif
 716         } else if (ntohl(hdr->ih_magic) == IH_MAGIC) {        // 校验fdt镜像Header魔数
 717             printf("## Flat Device Tree at %08lX\n", hdr);      
 718             print_image_hdr(hdr);                           // 根据fdt镜像Header打印信息
 719
 720             if ((ntohl(hdr->ih_load) <  ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) &&
 721                     ((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) {
 722                 // ((hdr->ih_load < (fdt_addr + hdr->ih_size + 64))  && \
 723                 // ((hdr->ih_load + hdr->ih_size) > fdt_addr))      防止搬运时覆盖
 724                 puts ("ERROR: fdt overwritten - "
 725                         "must RESET the board to recover.\n");
 726                 do_reset (cmdtp, flag, argc, argv);
 727             }
 728
 729             puts ("   Verifying Checksum ... ");
 730             memmove (&header, (char *)hdr, sizeof(image_header_t)); // 将fdt镜像Header复制到header
 731             checksum = ntohl(header.ih_hcrc);
 732             header.ih_hcrc = 0;
 733
 734             if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) {
 735                 puts ("ERROR: fdt header checksum invalid - "       // fdt镜像Header完整性校验
 736                         "must RESET the board to recover.\n");
 737                 do_reset (cmdtp, flag, argc, argv);
 738             }
 739
 740             checksum = ntohl(hdr->ih_dcrc);
 741             addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t));// addr指向fdt镜像Data起始地址
 742
 743             if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) {
 744                 puts ("ERROR: fdt checksum invalid - "              // fdt镜像Data完整性校验
 745                         "must RESET the board to recover.\n");
 746                 do_reset (cmdtp, flag, argc, argv);
 747             }
 748             puts ("OK\n");
 749
 750             if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) { // 校验fdt镜像Type为 Binary Flat Device Tree Blob
 751                 puts ("ERROR: uImage is not a fdt - "
 752                         "must RESET the board to recover.\n");
 753                 do_reset (cmdtp, flag, argc, argv);
 754             }
 755             if (ntohl(hdr->ih_comp) != IH_COMP_NONE) {   // fdt镜像Data不能压缩
 756                 puts ("ERROR: uImage is compressed - "
 757                         "must RESET the board to recover.\n");
 758                 do_reset (cmdtp, flag, argc, argv);
 759             }
 760 #if defined(CONFIG_OF_FLAT_TREE)
 761             if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
 762 #else
 763             if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { // fdt镜像Data检查
 764 #endif
 765                 puts ("ERROR: uImage data is not a fdt - "
 766                         "must RESET the board to recover.\n");
 767                 do_reset (cmdtp, flag, argc, argv);
 768             }
 769
 770             memmove((void *)ntohl(hdr->ih_load),     // 将fdt镜像Data搬运到 Load地址
 771                     (void *)(of_flat_tree + sizeof(image_header_t)),
 772                     ntohl(hdr->ih_size));
 773             of_flat_tree = (char *)ntohl(hdr->ih_load);  // of_flat_tree值为fdt镜像 Load地址
 774         } else {              // (ntohl(hdr->ih_magic) != IH_MAGIC
 775             puts ("Did not find a flat Flat Device Tree.\n"
 776                     "Must RESET the board to recover.\n");
 777             do_reset (cmdtp, flag, argc, argv);
 778         }
 779         printf ("   Booting using the fdt at 0x%x\n", // 显示fdt镜像Load地址
 780                 of_flat_tree);
 781     } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) {
 782                 // if (argc <= 3) && IH_TYPE_MULTI && len_ptr[1] && len_ptr[2]
 783                 // U-Boot命令: bootm [kern_addr] [multifile_image_addr]
 784         u_long tail    = ntohl(len_ptr[0]) % 4;
 785         int i;
 786
 787         /* skip kernel length, initrd length, and terminator */
 788         of_flat_tree = (char *)(&len_ptr[3]);
 789         /* skip any additional image length fields */
 790         for (i=2; len_ptr[i]; ++i)
 791             of_flat_tree += 4;
 792         /* add kernel length, and align */
 793         of_flat_tree += ntohl(len_ptr[0]);
 794         if (tail) {
 795             of_flat_tree += 4 - tail;
 796         }
 797
 798         /* add initrd length, and align */
 799         tail = ntohl(len_ptr[1]) % 4;
 800         of_flat_tree += ntohl(len_ptr[1]);
 801         if (tail) {
 802             of_flat_tree += 4 - tail;
 803         }
 804
 805 #ifndef CFG_NO_FLASH
 806         /* move the blob if it is in flash (set of_data to !null) */
 807         if (addr2info ((ulong)of_flat_tree) != NULL)
 808             of_data = (ulong)of_flat_tree;
 809 #endif
 810
 811
 812 #if defined(CONFIG_OF_FLAT_TREE)
 813         if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) {
 814 #else
 815         if (fdt_check_header (of_flat_tree) != 0) {
 816 #endif
 817             puts ("ERROR: image is not a fdt - "
 818                 "must RESET the board to recover.\n");
 819             do_reset (cmdtp, flag, argc, argv);
 820         }
 821
 822 #if defined(CONFIG_OF_FLAT_TREE)
 823         if (((struct boot_param_header *)of_flat_tree)->totalsize !=
 824             ntohl (len_ptr[2])) {
 825 #else
 826         if (be32_to_cpu (fdt_totalsize (of_flat_tree)) !=
 827             ntohl(len_ptr[2])) {
 828 #endif
 829             puts ("ERROR: fdt size != image size - "
 830                 "must RESET the board to recover.\n");
 831             do_reset (cmdtp, flag, argc, argv);
 832         }
 833     }
 834 #endif
 835     // 当bootm kern_addr ramdisk_addr [fdt_addr]时 data为ramdisk镜像Data起始地址值
 836     // 当bootm kern_addr - [fdt_addr]时,data为0
 837     if (!data) {      
 838         debug ("No initrd\n");        // data值为0
 839     }
 840
 841     if (data) {                        // data非0
 842         if (!initrd_copy_to_ram) {    /* zero-copy ramdisk support */
 843             initrd_start = data;
 844             initrd_end = initrd_start + len;
 845         } else {
 846             initrd_start  = (ulong)kbd - len;   // 在bd info下为ramdisk镜像Data预留空间
 847             initrd_start &= ~(4096 - 1); /* align on page */
 848
 849             if (initrd_high) {       // 一般为0xFFFF_FFFF
 850                 ulong nsp;
 851
 852             /*
 853              * initrd ramdisk不必在CFG_BOOTMAPSZ界限里
 854              *
 855              * the inital ramdisk does not need to be within
 856              * CFG_BOOTMAPSZ as it is not accessed until after
 857              * the mm system is initialised.
 858              *
 859              * do the stack bottom calculation again and see if
 860              * the initrd will fit just below the monitor stack
 861              * bottom without overwriting the area allocated
 862              * above for command line args and board info.
 863              */
 864                 asm( "mr %0,1": "=r"(nsp) : );  // nsp <= r1
 865                 nsp -= 2048;            /* just to be sure */
 866                 nsp &= ~0xF;
 867                 if (nsp > initrd_high)  /* limit as specified */
 868                     nsp = initrd_high;
 869                 nsp -= len;                     // 在U-Boot的用户栈空间顶部为ramdisk预留空间
 870                 nsp &= ~(4096 - 1); /* align on page */
 871                 if (nsp >= sp)
 872                     initrd_start = nsp;         // 为ramdisk镜像Data预留的起始地址
 873             }
 874
 875             show_boot_progress (12);
 876
 877             debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
 878                     data, + len - 1, len, len);
 879
 880             initrd_end    = initrd_start + len; // 预留空间的ramdisk镜像Data结束地址
 881             printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
 882                     initrd_start, initrd_end);
 883 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
 884             {
 885                 size_t l = len;
 886                 void *to = (void *)initrd_start;
 887                 void *from = (void *)data;
 888
 889                 while (l > 0) {
 890                     size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
 891                     WATCHDOG_RESET();
 892                     memmove (to, from, tail);
 893                     to += tail;
 894                     from += tail;
 895                     l -= tail;
 896                 }
 897             }
 898 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
 899             memmove ((void *)initrd_start, (void *)data, len); // 搬运ramdisk镜像Data到预留空间
 900 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
 901             puts ("OK\n");
 902         }
 903     } else {
 904         initrd_start = 0;
 905         initrd_end = 0;
 906     }
 907
 908 #if defined(CONFIG_OF_LIBFDT)   // U-Boot板子头文件中定义了CONFIG_OF_LIBFDT
 909
 910 #ifdef CFG_BOOTMAPSZ
 911     /*
 912      * The blob must be within CFG_BOOTMAPSZ,
 913      * so we flag it to be copied if it is not.
 914      */
 915     if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) // of_flat_tree为fdt镜像Load地址
 916         of_data = (ulong)of_flat_tree;  
 917 #endif
 918
 919     /* move of_flat_tree if needed */
 920     if (of_data) {
 921         int err;
 922         ulong of_start, of_len;
 923
 924         of_len = be32_to_cpu(fdt_totalsize(of_data));   // 获取fdt of_data长度
 925
 926         /* position on a 4K boundary before the kbd */
 927         of_start  = (ulong)kbd - of_len;        // 在bd info结构下预留空间
 928         of_start &= ~(4096 - 1);  /* align on page */
 929         debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
 930                 of_data, of_data + of_len - 1, of_len, of_len);
 931
 932         of_flat_tree = (char *)of_start;      // of_flat_tree指向预留of空间起始地址
 933         printf ("   Loading Device Tree to %08lx, end %08lx ... ",
 934                 of_start, of_start + of_len - 1);
 935         err = fdt_open_into((void *)of_data, (void *)of_start, of_len);
 936                                 // 将fdt Data copy到预留空间
 937         if (err != 0) {
 938             puts ("ERROR: fdt move failed - "
 939                 "must RESET the board to recover.\n");
 940             do_reset (cmdtp, flag, argc, argv);
 941         }
 942         puts ("OK\n");
 943     }
 944     /*
 945      * Add the chosen node if it doesn't exist, add the env and bd_t
 946      * if the user wants it (the logic is in the subroutines).
 947      */
 948     if (of_flat_tree) {            // 添加fdt /chosen节点
 949         if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
 950             puts ("ERROR: /chosen node create failed - "
 951                 "must RESET the board to recover.\n");
 952             do_reset (cmdtp, flag, argc, argv);
 953         }
 954 #ifdef CONFIG_OF_HAS_UBOOT_ENV
 955         if (fdt_env(of_flat_tree) < 0) {  // 添加fdt /u-boot-env节点
 956             puts ("ERROR: /u-boot-env node create failed - "
 957                 "must RESET the board to recover.\n");
 958             do_reset (cmdtp, flag, argc, argv);
 959         }
 960 #endif
 961 #ifdef CONFIG_OF_HAS_BD_T
 962         if (fdt_bd_t(of_flat_tree) < 0) { // 添加fdt /bd_t节点
 963             puts ("ERROR: /bd_t node create failed - "
 964                 "must RESET the board to recover.\n");
 965             do_reset (cmdtp, flag, argc, argv);
 966         }
 967 #endif
 968 #ifdef CONFIG_OF_BOARD_SETUP                // 添加板子相关的节点
 969         /* Call the board-specific fixup routine */
 970         ft_board_setup(of_flat_tree, gd->bd);
 971 #endif
 972     }
 973 #endif /* CONFIG_OF_LIBFDT */
 974 #if defined(CONFIG_OF_FLAT_TREE)            // U-Boot板子头文件中 #undef CONFIG_OF_FLAT_TREE
 975 #ifdef CFG_BOOTMAPSZ
 976     /*
 977      * The blob must be within CFG_BOOTMAPSZ,
 978      * so we flag it to be copied if it is not.
 979      */
 980     if (of_flat_tree >= (char *)CFG_BOOTMAPSZ)
 981         of_data = (ulong)of_flat_tree;
 982 #endif
 983
 984     /* move of_flat_tree if needed */
 985     if (of_data) {
 986         ulong of_start, of_len;
 987         of_len = ((struct boot_param_header *)of_data)->totalsize;
 988
 989         /* provide extra 8k pad */
 990         of_start  = (ulong)kbd - of_len - 8192;
 991         of_start &= ~(4096 - 1);  /* align on page */
 992         debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
 993                 of_data, of_data + of_len - 1, of_len, of_len);
 994
 995         of_flat_tree = (char *)of_start;
 996         printf ("   Loading Device Tree to %08lx, end %08lx ... ",
 997                 of_start, of_start + of_len - 1);
 998         memmove ((void *)of_start, (void *)of_data, of_len);
 999         puts ("OK\n");
1000     }
1001     /*
1002      * Create the /chosen node and modify the blob with board specific
1003      * values as needed.
1004      */
1005     ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
1006     /* ft_dump_blob(of_flat_tree); */
1007 #endif
1008     debug ("## Transferring control to Linux (at address %08lx) ...\n",
1009             (ulong)kernel);
1010
1011     show_boot_progress (15);
1012
1013 #if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
1014     unlock_ram_in_cache();          // cpu/83xx/start.S
1015 #endif
1016
1017 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
1018     if (of_flat_tree) {    /* device tree; boot new style */
1019         /*
1020          * Linux Kernel Parameters (passing device tree):
1021          *   r3: pointer to the fdt, followed by the board info data
1022          *   r4: physical pointer to the kernel itself
1023          *   r5: NULL
1024          *   r6: NULL
1025          *   r7: NULL
1026          */
1027         // 若定义了CONFIG_OF_LIBFDT 且给出了bootm命令的fdt_addr参数 则以下面的形式来使用kernel函数指针
1028         (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
1029         /* does not return */
1030     }
1031 #endif
1032     /*
1033      * Linux Kernel Parameters (passing board info data):
1034      *   r3: ptr to board info data
1035      *   r4: initrd_start or 0 if no initrd
1036      *   r5: initrd_end - unused if r4 is 0
1037      *   r6: Start of command line string
1038      *   r7: End   of command line string
1039      */
1040     // 若没定义CONFIG_OF_LIBFDT或者是bootm kern_addr [-/ramdisk_addr] 则以下面的形式来使用kernel函数指针
1041     (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
1042     /* does not return */
1043 }
1044 #endif /* CONFIG_PPC */
1045
1046     // 中间删除了其他do_boom_xxOS
1047
1048 #if defined(CONFIG_CMD_IMI)
1049 int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1050 {
1051     int    arg;
1052     ulong   addr;
1053     int     rcode=0;
1054     if (argc < 2) {
1055         return image_info (load_addr);
1056     }
1057     for (arg=1; arg 1058         addr = simple_strtoul(argv[arg], NULL, 16);
1059         if (image_info (addr) != 0) rcode = 1;
1060     }
1061     return rcode;
1062 }
1063 static int image_info (ulong addr)          // 显示镜像Header信息
1064 {
1065     ulong   data, len, checksum;
1066     image_header_t *hdr = &header;
1067     printf ("\n## Checking Image at %08lx ...\n", addr);
1068     /* Copy header so we can blank CRC field for re-calculation */
1069     memmove (&header, (char *)addr, sizeof(image_header_t));
1070     if (ntohl(hdr->ih_magic) != IH_MAGIC) {
1071         puts ("   Bad Magic Number\n");
1072         return 1;
1073     }
1074     data = (ulong)&header;
1075     len  = sizeof(image_header_t);
1076     checksum = ntohl(hdr->ih_hcrc);
1077     hdr->ih_hcrc = 0;
1078     if (crc32 (0, (uchar *)data, len) != checksum) {
1079         puts ("   Bad Header Checksum\n");
1080         return 1;
1081     }
1082     /* for multi-file images we need the data part, too */
1083     print_image_hdr ((image_header_t *)addr);
1084     data = addr + sizeof(image_header_t);
1085     len  = ntohl(hdr->ih_size);
1086     puts ("   Verifying Checksum ... ");
1087     if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
1088         puts ("   Bad Data CRC\n");
1089         return 1;
1090     }
1091     puts ("OK\n");
1092     return 0;
1093 }
1094
1095 U_BOOT_CMD(
1096     iminfo, CFG_MAXARGS,    1,    do_iminfo,
1097     "iminfo  - print header information for application image\n",
1098 );
1099 #endif
1100
1101 #if defined(CONFIG_CMD_IMLS)        // 列示Flash中的所有镜像文件
1102 int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1103 {
1104     flash_info_t *info;
1105     int i, j;
1106     image_header_t *hdr;
1107     ulong data, len, checksum;
1108
1109     for (i=0, info=&flash_info[0]; i1110         if (info->flash_id == FLASH_UNKNOWN)
1111             goto next_bank;
1112         for (j=0; jsector_count; ++j) {
1113             if (!(hdr=(image_header_t *)info->start[j]) ||
1114                 (ntohl(hdr->ih_magic) != IH_MAGIC))
1115                 goto next_sector;
1116             // 由上面if语句说明,在烧写时最好按Flash sector的起始地址来烧写镜像
1117
1118             /* Copy header so we can blank CRC field for re-calculation */
1119             memmove (&header, (char *)hdr, sizeof(image_header_t));
1120             checksum = ntohl(header.ih_hcrc);
1121             header.ih_hcrc = 0;
1122
1123             if (crc32 (0, (uchar *)&header, sizeof(image_header_t))
1124                 != checksum)
1125                 goto next_sector;
1126
1127             printf ("Image at %08lX:\n", (ulong)hdr);
1128             print_image_hdr( hdr );
1129
1130             data = (ulong)hdr + sizeof(image_header_t);
1131             len  = ntohl(hdr->ih_size);
1132
1133             puts ("   Verifying Checksum ... ");
1134             if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
1135                 puts ("   Bad Data CRC\n");
1136             }
1137             puts ("OK\n");
1138 next_sector:        ;
1139         }
1140 next_bank:  ;
1141     }
1142     return (0);
1143 }
1144
1145 U_BOOT_CMD(
1146     imls,   1,       1,   do_imls,    // U-Boot命令imls调用上面的do_imls函数
1147     "imls    - list all images found in flash\n",
1148 );
1149 #endif
1150
1151 void print_image_hdr (image_header_t *hdr)  // 根据image_header_t结构显示镜像信息
1152 {
1153 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
1154     time_t timestamp = (time_t)ntohl(hdr->ih_time);
1155     struct rtc_time tm;
1156 #endif
1157
1158     printf ("   Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name);
1159 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
1160     to_tm (timestamp, &tm);
1161     printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n",
1162         tm.tm_year, tm.tm_mon, tm.tm_mday,
1163         tm.tm_hour, tm.tm_min, tm.tm_sec);
1164 #endif
1165     puts ("   Image Type:   "); print_type(hdr);
1166     printf ("\n   Data Size:    %d Bytes = ", ntohl(hdr->ih_size));
1167     print_size (ntohl(hdr->ih_size), "\n");
1168     printf ("   Load Address: %08x\n"
1169         "   Entry Point:  %08x\n",
1170          ntohl(hdr->ih_load), ntohl(hdr->ih_ep));
1171
1172     if (hdr->ih_type == IH_TYPE_MULTI) {
1173         int i;
1174         ulong len;
1175         ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
1176
1177         puts ("   Contents:\n");
1178         for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) {
1179             printf ("   Image %d: %8ld Bytes = ", i, len);
1180             print_size (len, "\n");
1181         }
1182     }
1183 }
1184
1185 static void print_type (image_header_t *hdr)
1186 {
1187     char *os, *arch, *type, *comp;
1188     switch (hdr->ih_os) {
1189     case IH_OS_INVALID:    os = "Invalid OS";     break;
1190     case IH_OS_NETBSD: os = "NetBSD";          break;
1191     case IH_OS_LINUX:  os = "Linux";            break;
1192     case IH_OS_VXWORKS:    os = "VxWorks";            break;
1193     case IH_OS_U_BOOT: os = "U-Boot";          break;
1194     default:       os = "Unknown OS";       break;
1195     }
1196     switch (hdr->ih_arch) {
1197     case IH_CPU_INVALID:   arch = "Invalid CPU";     break;
1198     case IH_CPU_ARM:   arch = "ARM";         break;
1199     case IH_CPU_PPC:   arch = "PowerPC";     break;
1200     default:       arch = "Unknown Architecture";   break;
1201     }
1202     switch (hdr->ih_type) {
1203     case IH_TYPE_INVALID:  type = "Invalid Image";      break;
1204     case IH_TYPE_STANDALONE:type = "Standalone Program";   break;
1205     case IH_TYPE_KERNEL:   type = "Kernel Image";        break;
1206     case IH_TYPE_RAMDISK:  type = "RAMDisk Image";      break;
1207     case IH_TYPE_MULTI:    type = "Multi-File Image"; break;
1208     case IH_TYPE_FIRMWARE: type = "Firmware";      break;
1209     case IH_TYPE_SCRIPT:   type = "Script";      break;
1210     case IH_TYPE_FLATDT:   type = "Flat Device Tree";    break;
1211     default:       type = "Unknown Image";      break;
1212     }
1213     switch (hdr->ih_comp) {
1214     case IH_COMP_NONE: comp = "uncompressed";      break;
1215     case IH_COMP_GZIP: comp = "gzip compressed";   break;
1216     case IH_COMP_BZIP2:    comp = "bzip2 compressed"; break;
1217     default:       comp = "unknown compression";    break;
1218     }
1219     printf ("%s %s %s (%s)", arch, os, type, comp);
1220 }
1221 #define ZALLOC_ALIGNMENT    16
1222 static void *zalloc(void *x, unsigned items, unsigned size) {
1223     void *p;
1224     size *= items;
1225     size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
1226     p = malloc (size);
1227     return (p);
1228 }
1229 static void zfree(void *x, void *addr, unsigned nb) {
1230     free (addr);
1231 }
1232 #define HEAD_CRC    2
1233 #define EXTRA_FIELD 4
1234 #define ORIG_NAME   8
1235 #define COMMENT     0x10
1236 #define RESERVED    0xe0
1237 #define DEFLATED    8
1238 int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) // gunzip解压缩函数
1239 {
1240     z_stream s;
1241     int r, i, flags;
1242     /* skip header */
1243     i = 10;
1244     flags = src[3];
1245     if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
1246         puts ("Error: Bad gzipped data\n");
1247         return (-1);
1248     }
1249     if ((flags & EXTRA_FIELD) != 0)
1250         i = 12 + src[10] + (src[11] << 8);
1251     if ((flags & ORIG_NAME) != 0)
1252         while (src[i++] != 0)
1253             ;
1254     if ((flags & COMMENT) != 0)
1255         while (src[i++] != 0)
1256             ;
1257     if ((flags & HEAD_CRC) != 0)
1258         i += 2;
1259     if (i >= *lenp) {
1260         puts ("Error: gunzip out of data in header\n");
1261         return (-1);
1262     }
1263     s.zalloc = zalloc;
1264     s.zfree = zfree;
1265 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1266     s.outcb = (cb_func)WATCHDOG_RESET;
1267 #else
1268     s.outcb = Z_NULL;
1269 #endif  /* CONFIG_HW_WATCHDOG */
1270     r = inflateInit2(&s, -MAX_WBITS);
1271     if (r != Z_OK) {
1272         printf ("Error: inflateInit2() returned %d\n", r);
1273         return (-1);
1274     }
1275     s.next_in = src + i;
1276     s.avail_in = *lenp - i;
1277     s.next_out = dst;
1278     s.avail_out = dstlen;
1279     r = inflate(&s, Z_FINISH);
1280     if (r != Z_OK && r != Z_STREAM_END) {
1281         printf ("Error: inflate() returned %d\n", r);
1282         return (-1);
1283     }
1284     *lenp = s.next_out - (unsigned char *) dst;
1285     inflateEnd(&s);
1286     return (0);
1287 }
1288 #ifdef CONFIG_BZIP2
1289 void bz_internal_error(int errcode)
1290 {
1291     printf ("BZIP2 internal error %d\n", errcode);
1292 }
1293 #endif /* CONFIG_BZIP2 */

阅读(4404) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~