分类: 嵌入式
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
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]; i
1111 goto next_bank;
1112 for (j=0; 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 */