]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - common/cmd_bootm.c
[new uImage] Add memmove_wd() common routine
[karo-tx-uboot.git] / common / cmd_bootm.c
1 /*
2  * (C) Copyright 2000-2006
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #define DEBUG
25
26 /*
27  * Boot support
28  */
29 #include <common.h>
30 #include <watchdog.h>
31 #include <command.h>
32 #include <image.h>
33 #include <malloc.h>
34 #include <zlib.h>
35 #include <bzlib.h>
36 #include <environment.h>
37 #include <asm/byteorder.h>
38
39 #if defined(CONFIG_OF_LIBFDT)
40 #include <fdt.h>
41 #include <libfdt.h>
42 #include <fdt_support.h>
43 #elif defined(CONFIG_OF_FLAT_TREE)
44 #include <ft_build.h>
45 #endif
46
47 DECLARE_GLOBAL_DATA_PTR;
48
49 /*cmd_boot.c*/
50 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
51
52 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
53 #include <rtc.h>
54 #endif
55
56 #ifdef CFG_HUSH_PARSER
57 #include <hush.h>
58 #endif
59
60 #ifdef CONFIG_HAS_DATAFLASH
61 #include <dataflash.h>
62 #endif
63
64 int  gunzip (void *, int, unsigned char *, unsigned long *);
65
66 #ifdef CONFIG_BZIP2
67 extern void bz_internal_error(int);
68 #endif
69
70 #if defined(CONFIG_CMD_IMI)
71 static int image_info (unsigned long addr);
72 #endif
73
74 #if defined(CONFIG_CMD_IMLS)
75 #include <flash.h>
76 extern flash_info_t flash_info[]; /* info for FLASH chips */
77 static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
78 #endif
79
80 static void print_type (image_header_t *hdr);
81
82 /*
83  *  Continue booting an OS image; caller already has:
84  *  - copied image header to global variable `header'
85  *  - checked header magic number, checksums (both header & image),
86  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
87  *  - loaded (first part of) image to header load address,
88  *  - disabled interrupts.
89  */
90 typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
91                           int   argc, char *argv[],
92                           ulong addr,           /* of image to boot */
93                           ulong *len_ptr,       /* multi-file image length table */
94                           int   verify);        /* getenv("verify")[0] != 'n' */
95
96 extern boot_os_Fcn do_bootm_linux;
97
98 #ifdef CONFIG_SILENT_CONSOLE
99 static void fixup_silent_linux (void);
100 #endif
101 static boot_os_Fcn do_bootm_netbsd;
102 static boot_os_Fcn do_bootm_rtems;
103 #if defined(CONFIG_CMD_ELF)
104 static boot_os_Fcn do_bootm_vxworks;
105 static boot_os_Fcn do_bootm_qnxelf;
106 int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
107 int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
108 #endif
109 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
110 static boot_os_Fcn do_bootm_artos;
111 #endif
112 #ifdef CONFIG_LYNXKDI
113 static boot_os_Fcn do_bootm_lynxkdi;
114 extern void lynxkdi_boot( image_header_t * );
115 #endif
116
117 #ifndef CFG_BOOTM_LEN
118 #define CFG_BOOTM_LEN   0x800000        /* use 8MByte as default max gunzip size */
119 #endif
120
121 image_header_t header;
122
123 ulong load_addr = CFG_LOAD_ADDR;                /* Default Load Address */
124
125 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
126 {
127         ulong   iflag;
128         ulong   addr;
129         ulong   data, len;
130         ulong  *len_ptr;
131         uint    unc_len = CFG_BOOTM_LEN;
132         int     i, verify;
133         char    *name, *s;
134         int     (*appl)(int, char *[]);
135         image_header_t *hdr = &header;
136
137         verify = getenv_verify ();
138
139         if (argc < 2) {
140                 addr = load_addr;
141         } else {
142                 addr = simple_strtoul(argv[1], NULL, 16);
143         }
144
145         show_boot_progress (1);
146         printf ("## Booting image at %08lx ...\n", addr);
147
148         /* Copy header so we can blank CRC field for re-calculation */
149 #ifdef CONFIG_HAS_DATAFLASH
150         if (addr_dataflash(addr)){
151                 read_dataflash (addr, image_get_header_size (), (char *)&header);
152         } else
153 #endif
154         memmove (&header, (char *)addr, image_get_header_size ());
155
156         if (!image_check_magic(hdr)) {
157                 puts ("Bad Magic Number\n");
158                 show_boot_progress (-1);
159                 return 1;
160         }
161         show_boot_progress (2);
162
163         if (!image_check_hcrc (hdr)) {
164                 puts ("Bad Header Checksum\n");
165                 show_boot_progress (-2);
166                 return 1;
167         }
168         show_boot_progress (3);
169
170 #ifdef CONFIG_HAS_DATAFLASH
171         if (addr_dataflash(addr)){
172                 len  = image_get_image_size (hdr);
173                 read_dataflash(addr, len, (char *)CFG_LOAD_ADDR);
174                 addr = CFG_LOAD_ADDR;
175         }
176 #endif
177
178
179         /* for multi-file images we need the data part, too */
180         print_image_hdr ((image_header_t *)addr);
181
182         len = image_get_data_size (hdr);
183         data = addr + image_get_header_size ();
184         len_ptr = (ulong *)data;
185
186         if (verify) {
187                 puts ("   Verifying Checksum ... ");
188                 if (!image_check_dcrc ((image_header_t *)addr)) {
189                         printf ("Bad Data CRC\n");
190                         show_boot_progress (-3);
191                         return 1;
192                 }
193                 puts ("OK\n");
194         }
195         show_boot_progress (4);
196
197         if (!image_check_target_arch (hdr)) {
198                 printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr));
199                 show_boot_progress (-4);
200                 return 1;
201         }
202         show_boot_progress (5);
203
204         switch (image_get_type (hdr)) {
205         case IH_TYPE_STANDALONE:
206                 name = "Standalone Application";
207                 /* A second argument overwrites the load address */
208                 if (argc > 2) {
209                         image_set_load (hdr, simple_strtoul (argv[2], NULL, 16));
210                 }
211                 break;
212         case IH_TYPE_KERNEL:
213                 name = "Kernel Image";
214                 break;
215         case IH_TYPE_MULTI:
216                 name = "Multi-File Image";
217                 len  = image_to_cpu (len_ptr[0]);
218                 /* OS kernel is always the first image */
219                 data += 8; /* kernel_len + terminator */
220                 for (i=1; len_ptr[i]; ++i)
221                         data += 4;
222                 break;
223         default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
224                 show_boot_progress (-5);
225                 return 1;
226         }
227         show_boot_progress (6);
228
229         /*
230          * We have reached the point of no return: we are going to
231          * overwrite all exception vector code, so we cannot easily
232          * recover from any failures any more...
233          */
234
235         iflag = disable_interrupts();
236
237 #ifdef CONFIG_AMIGAONEG3SE
238         /*
239          * We've possible left the caches enabled during
240          * bios emulation, so turn them off again
241          */
242         icache_disable();
243         invalidate_l1_instruction_cache();
244         flush_data_cache();
245         dcache_disable();
246 #endif
247
248         switch (image_get_comp (hdr)) {
249         case IH_COMP_NONE:
250                 if (image_get_load (hdr) == addr) {
251                         printf ("   XIP %s ... ", name);
252                 } else {
253                         printf ("   Loading %s ... ", name);
254
255                         memmove_wd ((void *)image_get_load (hdr),
256                                    (void *)data, len, CHUNKSZ);
257
258                         puts("OK\n");
259                 }
260                 break;
261         case IH_COMP_GZIP:
262                 printf ("   Uncompressing %s ... ", name);
263                 if (gunzip ((void *)image_get_load (hdr), unc_len,
264                             (uchar *)data, &len) != 0) {
265                         puts ("GUNZIP ERROR - must RESET board to recover\n");
266                         show_boot_progress (-6);
267                         do_reset (cmdtp, flag, argc, argv);
268                 }
269                 break;
270 #ifdef CONFIG_BZIP2
271         case IH_COMP_BZIP2:
272                 printf ("   Uncompressing %s ... ", name);
273                 /*
274                  * If we've got less than 4 MB of malloc() space,
275                  * use slower decompression algorithm which requires
276                  * at most 2300 KB of memory.
277                  */
278                 i = BZ2_bzBuffToBuffDecompress ((char*)image_get_load (hdr),
279                                                 &unc_len, (char *)data, len,
280                                                 CFG_MALLOC_LEN < (4096 * 1024), 0);
281                 if (i != BZ_OK) {
282                         printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
283                         show_boot_progress (-6);
284                         do_reset (cmdtp, flag, argc, argv);
285                 }
286                 break;
287 #endif /* CONFIG_BZIP2 */
288         default:
289                 if (iflag)
290                         enable_interrupts();
291                 printf ("Unimplemented compression type %d\n", image_get_comp (hdr));
292                 show_boot_progress (-7);
293                 return 1;
294         }
295         puts ("OK\n");
296         show_boot_progress (7);
297
298         switch (image_get_type (hdr)) {
299         case IH_TYPE_STANDALONE:
300                 if (iflag)
301                         enable_interrupts();
302
303                 /* load (and uncompress), but don't start if "autostart"
304                  * is set to "no"
305                  */
306                 if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {
307                         char buf[32];
308                         sprintf(buf, "%lX", len);
309                         setenv("filesize", buf);
310                         return 0;
311                 }
312                 appl = (int (*)(int, char *[]))image_get_ep (hdr);
313                 (*appl)(argc-1, &argv[1]);
314                 return 0;
315         case IH_TYPE_KERNEL:
316         case IH_TYPE_MULTI:
317                 /* handled below */
318                 break;
319         default:
320                 if (iflag)
321                         enable_interrupts();
322                 printf ("Can't boot image type %d\n", image_get_type (hdr));
323                 show_boot_progress (-8);
324                 return 1;
325         }
326         show_boot_progress (8);
327
328         switch (image_get_os (hdr)) {
329         default:                        /* handled by (original) Linux case */
330         case IH_OS_LINUX:
331 #ifdef CONFIG_SILENT_CONSOLE
332             fixup_silent_linux();
333 #endif
334             do_bootm_linux  (cmdtp, flag, argc, argv,
335                              addr, len_ptr, verify);
336             break;
337         case IH_OS_NETBSD:
338             do_bootm_netbsd (cmdtp, flag, argc, argv,
339                              addr, len_ptr, verify);
340             break;
341
342 #ifdef CONFIG_LYNXKDI
343         case IH_OS_LYNXOS:
344             do_bootm_lynxkdi (cmdtp, flag, argc, argv,
345                              addr, len_ptr, verify);
346             break;
347 #endif
348
349         case IH_OS_RTEMS:
350             do_bootm_rtems (cmdtp, flag, argc, argv,
351                              addr, len_ptr, verify);
352             break;
353
354 #if defined(CONFIG_CMD_ELF)
355         case IH_OS_VXWORKS:
356             do_bootm_vxworks (cmdtp, flag, argc, argv,
357                               addr, len_ptr, verify);
358             break;
359         case IH_OS_QNX:
360             do_bootm_qnxelf (cmdtp, flag, argc, argv,
361                               addr, len_ptr, verify);
362             break;
363 #endif
364 #ifdef CONFIG_ARTOS
365         case IH_OS_ARTOS:
366             do_bootm_artos  (cmdtp, flag, argc, argv,
367                              addr, len_ptr, verify);
368             break;
369 #endif
370         }
371
372         show_boot_progress (-9);
373 #ifdef DEBUG
374         puts ("\n## Control returned to monitor - resetting...\n");
375         do_reset (cmdtp, flag, argc, argv);
376 #endif
377         return 1;
378 }
379
380 U_BOOT_CMD(
381         bootm,  CFG_MAXARGS,    1,      do_bootm,
382         "bootm   - boot application image from memory\n",
383         "[addr [arg ...]]\n    - boot application image stored in memory\n"
384         "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
385         "\t'arg' can be the address of an initrd image\n"
386 #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
387         "\tWhen booting a Linux kernel which requires a flat device-tree\n"
388         "\ta third argument is required which is the address of the\n"
389         "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
390         "\tuse a '-' for the second argument. If you do not pass a third\n"
391         "\ta bd_info struct will be passed instead\n"
392 #endif
393 );
394
395 #ifdef CONFIG_SILENT_CONSOLE
396 static void
397 fixup_silent_linux ()
398 {
399         char buf[256], *start, *end;
400         char *cmdline = getenv ("bootargs");
401
402         /* Only fix cmdline when requested */
403         if (!(gd->flags & GD_FLG_SILENT))
404                 return;
405
406         debug ("before silent fix-up: %s\n", cmdline);
407         if (cmdline) {
408                 if ((start = strstr (cmdline, "console=")) != NULL) {
409                         end = strchr (start, ' ');
410                         strncpy (buf, cmdline, (start - cmdline + 8));
411                         if (end)
412                                 strcpy (buf + (start - cmdline + 8), end);
413                         else
414                                 buf[start - cmdline + 8] = '\0';
415                 } else {
416                         strcpy (buf, cmdline);
417                         strcat (buf, " console=");
418                 }
419         } else {
420                 strcpy (buf, "console=");
421         }
422
423         setenv ("bootargs", buf);
424         debug ("after silent fix-up: %s\n", buf);
425 }
426 #endif /* CONFIG_SILENT_CONSOLE */
427
428 static void
429 do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
430                 int     argc, char *argv[],
431                 ulong   addr,
432                 ulong   *len_ptr,
433                 int     verify)
434 {
435         image_header_t *hdr = &header;
436
437         void    (*loader)(bd_t *, image_header_t *, char *, char *);
438         image_header_t *img_addr;
439         char     *consdev;
440         char     *cmdline;
441
442
443         /*
444          * Booting a (NetBSD) kernel image
445          *
446          * This process is pretty similar to a standalone application:
447          * The (first part of an multi-) image must be a stage-2 loader,
448          * which in turn is responsible for loading & invoking the actual
449          * kernel.  The only differences are the parameters being passed:
450          * besides the board info strucure, the loader expects a command
451          * line, the name of the console device, and (optionally) the
452          * address of the original image header.
453          */
454
455         img_addr = 0;
456         if ((image_check_type (hdr, IH_TYPE_MULTI)) && (len_ptr[1]))
457                 img_addr = (image_header_t *) addr;
458
459
460         consdev = "";
461 #if   defined (CONFIG_8xx_CONS_SMC1)
462         consdev = "smc1";
463 #elif defined (CONFIG_8xx_CONS_SMC2)
464         consdev = "smc2";
465 #elif defined (CONFIG_8xx_CONS_SCC2)
466         consdev = "scc2";
467 #elif defined (CONFIG_8xx_CONS_SCC3)
468         consdev = "scc3";
469 #endif
470
471         if (argc > 2) {
472                 ulong len;
473                 int   i;
474
475                 for (i=2, len=0 ; i<argc ; i+=1)
476                         len += strlen (argv[i]) + 1;
477                 cmdline = malloc (len);
478
479                 for (i=2, len=0 ; i<argc ; i+=1) {
480                         if (i > 2)
481                                 cmdline[len++] = ' ';
482                         strcpy (&cmdline[len], argv[i]);
483                         len += strlen (argv[i]);
484                 }
485         } else if ((cmdline = getenv("bootargs")) == NULL) {
486                 cmdline = "";
487         }
488
489         loader = (void (*)(bd_t *, image_header_t *, char *, char *))image_get_ep (hdr);
490
491         printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
492                 (ulong)loader);
493
494         show_boot_progress (15);
495
496         /*
497          * NetBSD Stage-2 Loader Parameters:
498          *   r3: ptr to board info data
499          *   r4: image address
500          *   r5: console device
501          *   r6: boot args string
502          */
503         (*loader) (gd->bd, img_addr, consdev, cmdline);
504 }
505
506 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
507
508 /* Function that returns a character from the environment */
509 extern uchar (*env_get_char)(int);
510
511 static void
512 do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
513                 int     argc, char *argv[],
514                 ulong   addr,
515                 ulong   *len_ptr,
516                 int     verify)
517 {
518         ulong top;
519         char *s, *cmdline;
520         char **fwenv, **ss;
521         int i, j, nxt, len, envno, envsz;
522         bd_t *kbd;
523         void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top);
524         image_header_t *hdr = &header;
525
526         /*
527          * Booting an ARTOS kernel image + application
528          */
529
530         /* this used to be the top of memory, but was wrong... */
531 #ifdef CONFIG_PPC
532         /* get stack pointer */
533         asm volatile ("mr %0,1" : "=r"(top) );
534 #endif
535         debug ("## Current stack ends at 0x%08lX ", top);
536
537         top -= 2048;            /* just to be sure */
538         if (top > CFG_BOOTMAPSZ)
539                 top = CFG_BOOTMAPSZ;
540         top &= ~0xF;
541
542         debug ("=> set upper limit to 0x%08lX\n", top);
543
544         /* first check the artos specific boot args, then the linux args*/
545         if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL)
546                 s = "";
547
548         /* get length of cmdline, and place it */
549         len = strlen(s);
550         top = (top - (len + 1)) & ~0xF;
551         cmdline = (char *)top;
552         debug ("## cmdline at 0x%08lX ", top);
553         strcpy(cmdline, s);
554
555         /* copy bdinfo */
556         top = (top - sizeof(bd_t)) & ~0xF;
557         debug ("## bd at 0x%08lX ", top);
558         kbd = (bd_t *)top;
559         memcpy(kbd, gd->bd, sizeof(bd_t));
560
561         /* first find number of env entries, and their size */
562         envno = 0;
563         envsz = 0;
564         for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
565                 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
566                         ;
567                 envno++;
568                 envsz += (nxt - i) + 1; /* plus trailing zero */
569         }
570         envno++;        /* plus the terminating zero */
571         debug ("## %u envvars total size %u ", envno, envsz);
572
573         top = (top - sizeof(char **)*envno) & ~0xF;
574         fwenv = (char **)top;
575         debug ("## fwenv at 0x%08lX ", top);
576
577         top = (top - envsz) & ~0xF;
578         s = (char *)top;
579         ss = fwenv;
580
581         /* now copy them */
582         for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
583                 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
584                         ;
585                 *ss++ = s;
586                 for (j = i; j < nxt; ++j)
587                         *s++ = env_get_char(j);
588                 *s++ = '\0';
589         }
590         *ss++ = NULL;   /* terminate */
591
592         entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr);
593         (*entry)(kbd, cmdline, fwenv, top);
594 }
595 #endif
596
597
598 #if defined(CONFIG_CMD_BOOTD)
599 int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
600 {
601         int rcode = 0;
602 #ifndef CFG_HUSH_PARSER
603         if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1;
604 #else
605         if (parse_string_outer(getenv("bootcmd"),
606                 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1;
607 #endif
608         return rcode;
609 }
610
611 U_BOOT_CMD(
612         boot,   1,      1,      do_bootd,
613         "boot    - boot default, i.e., run 'bootcmd'\n",
614         NULL
615 );
616
617 /* keep old command name "bootd" for backward compatibility */
618 U_BOOT_CMD(
619         bootd, 1,       1,      do_bootd,
620         "bootd   - boot default, i.e., run 'bootcmd'\n",
621         NULL
622 );
623
624 #endif
625
626 #if defined(CONFIG_CMD_IMI)
627 int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
628 {
629         int     arg;
630         ulong   addr;
631         int     rcode=0;
632
633         if (argc < 2) {
634                 return image_info (load_addr);
635         }
636
637         for (arg=1; arg <argc; ++arg) {
638                 addr = simple_strtoul(argv[arg], NULL, 16);
639                 if (image_info (addr) != 0) rcode = 1;
640         }
641         return rcode;
642 }
643
644 static int image_info (ulong addr)
645 {
646         image_header_t *hdr = (image_header_t *)addr;
647
648         printf ("\n## Checking Image at %08lx ...\n", addr);
649
650         if (!image_check_magic (hdr)) {
651                 puts ("   Bad Magic Number\n");
652                 return 1;
653         }
654
655         if (!image_check_hcrc (hdr)) {
656                 puts ("   Bad Header Checksum\n");
657                 return 1;
658         }
659
660         print_image_hdr (hdr);
661
662         puts ("   Verifying Checksum ... ");
663         if (!image_check_dcrc (hdr)) {
664                 puts ("   Bad Data CRC\n");
665                 return 1;
666         }
667         puts ("OK\n");
668         return 0;
669 }
670
671 U_BOOT_CMD(
672         iminfo, CFG_MAXARGS,    1,      do_iminfo,
673         "iminfo  - print header information for application image\n",
674         "addr [addr ...]\n"
675         "    - print header information for application image starting at\n"
676         "      address 'addr' in memory; this includes verification of the\n"
677         "      image contents (magic number, header and payload checksums)\n"
678 );
679
680 #endif
681
682 #if defined(CONFIG_CMD_IMLS)
683 /*-----------------------------------------------------------------------
684  * List all images found in flash.
685  */
686 int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
687 {
688         flash_info_t *info;
689         int i, j;
690         image_header_t *hdr;
691
692         for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
693                 if (info->flash_id == FLASH_UNKNOWN)
694                         goto next_bank;
695                 for (j=0; j<info->sector_count; ++j) {
696
697                         hdr = (image_header_t *)info->start[j];
698
699                         if (!hdr || !image_check_magic (hdr))
700                                 goto next_sector;
701
702                         if (!image_check_hcrc (hdr))
703                                 goto next_sector;
704
705                         printf ("Image at %08lX:\n", (ulong)hdr);
706                         print_image_hdr (hdr);
707
708                         puts ("   Verifying Checksum ... ");
709                         if (!image_check_dcrc (hdr)) {
710                                 puts ("Bad Data CRC\n");
711                         } else {
712                                 puts ("OK\n");
713                         }
714 next_sector:            ;
715                 }
716 next_bank:      ;
717         }
718
719         return (0);
720 }
721
722 U_BOOT_CMD(
723         imls,   1,              1,      do_imls,
724         "imls    - list all images found in flash\n",
725         "\n"
726         "    - Prints information about all images found at sector\n"
727         "      boundaries in flash.\n"
728 );
729 #endif
730
731 void
732 print_image_hdr (image_header_t *hdr)
733 {
734 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
735         time_t timestamp = (time_t)image_get_time (hdr);
736         struct rtc_time tm;
737 #endif
738
739         printf ("   Image Name:   %.*s\n", IH_NMLEN, image_get_name (hdr));
740 #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
741         to_tm (timestamp, &tm);
742         printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n",
743                 tm.tm_year, tm.tm_mon, tm.tm_mday,
744                 tm.tm_hour, tm.tm_min, tm.tm_sec);
745 #endif
746         puts ("   Image Type:   "); print_type(hdr);
747         printf ("\n   Data Size:    %d Bytes = ", image_get_data_size (hdr));
748         print_size (image_get_data_size (hdr), "\n");
749         printf ("   Load Address: %08x\n"
750                 "   Entry Point:  %08x\n",
751                  image_get_load (hdr), image_get_ep (hdr));
752
753         if (image_check_type (hdr, IH_TYPE_MULTI)) {
754                 int i;
755                 ulong len;
756                 ulong *len_ptr = (ulong *)((ulong)hdr + image_get_header_size ());
757
758                 puts ("   Contents:\n");
759                 for (i=0; (len = image_to_cpu (*len_ptr)); ++i, ++len_ptr) {
760                         printf ("   Image %d: %8ld Bytes = ", i, len);
761                         print_size (len, "\n");
762                 }
763         }
764 }
765
766
767 static void
768 print_type (image_header_t *hdr)
769 {
770         char *os, *arch, *type, *comp;
771
772         switch (image_get_os (hdr)) {
773         case IH_OS_INVALID:     os = "Invalid OS";              break;
774         case IH_OS_NETBSD:      os = "NetBSD";                  break;
775         case IH_OS_LINUX:       os = "Linux";                   break;
776         case IH_OS_VXWORKS:     os = "VxWorks";                 break;
777         case IH_OS_QNX:         os = "QNX";                     break;
778         case IH_OS_U_BOOT:      os = "U-Boot";                  break;
779         case IH_OS_RTEMS:       os = "RTEMS";                   break;
780 #ifdef CONFIG_ARTOS
781         case IH_OS_ARTOS:       os = "ARTOS";                   break;
782 #endif
783 #ifdef CONFIG_LYNXKDI
784         case IH_OS_LYNXOS:      os = "LynxOS";                  break;
785 #endif
786         default:                os = "Unknown OS";              break;
787         }
788
789         switch (image_get_arch (hdr)) {
790         case IH_ARCH_INVALID:   arch = "Invalid CPU";           break;
791         case IH_ARCH_ALPHA:     arch = "Alpha";                 break;
792         case IH_ARCH_ARM:       arch = "ARM";                   break;
793         case IH_ARCH_AVR32:     arch = "AVR32";                 break;
794         case IH_ARCH_BLACKFIN:  arch = "Blackfin";              break;
795         case IH_ARCH_I386:      arch = "Intel x86";             break;
796         case IH_ARCH_IA64:      arch = "IA64";                  break;
797         case IH_ARCH_M68K:      arch = "M68K";                  break;
798         case IH_ARCH_MICROBLAZE:arch = "Microblaze";            break;
799         case IH_ARCH_MIPS64:    arch = "MIPS 64 Bit";           break;
800         case IH_ARCH_MIPS:      arch = "MIPS";                  break;
801         case IH_ARCH_NIOS2:     arch = "Nios-II";               break;
802         case IH_ARCH_NIOS:      arch = "Nios";                  break;
803         case IH_ARCH_PPC:       arch = "PowerPC";               break;
804         case IH_ARCH_S390:      arch = "IBM S390";              break;
805         case IH_ARCH_SH:        arch = "SuperH";                break;
806         case IH_ARCH_SPARC64:   arch = "SPARC 64 Bit";          break;
807         case IH_ARCH_SPARC:     arch = "SPARC";                 break;
808         default:                arch = "Unknown Architecture";  break;
809         }
810
811         switch (image_get_type (hdr)) {
812         case IH_TYPE_INVALID:   type = "Invalid Image";         break;
813         case IH_TYPE_STANDALONE:type = "Standalone Program";    break;
814         case IH_TYPE_KERNEL:    type = "Kernel Image";          break;
815         case IH_TYPE_RAMDISK:   type = "RAMDisk Image";         break;
816         case IH_TYPE_MULTI:     type = "Multi-File Image";      break;
817         case IH_TYPE_FIRMWARE:  type = "Firmware";              break;
818         case IH_TYPE_SCRIPT:    type = "Script";                break;
819         case IH_TYPE_FLATDT:    type = "Flat Device Tree";      break;
820         default:                type = "Unknown Image";         break;
821         }
822
823         switch (image_get_comp (hdr)) {
824         case IH_COMP_NONE:      comp = "uncompressed";          break;
825         case IH_COMP_GZIP:      comp = "gzip compressed";       break;
826         case IH_COMP_BZIP2:     comp = "bzip2 compressed";      break;
827         default:                comp = "unknown compression";   break;
828         }
829
830         printf ("%s %s %s (%s)", arch, os, type, comp);
831 }
832
833 static void
834 do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
835                 ulong addr, ulong *len_ptr, int verify)
836 {
837         image_header_t *hdr = &header;
838         void    (*entry_point)(bd_t *);
839
840         entry_point = (void (*)(bd_t *))image_get_ep (hdr);
841
842         printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
843                 (ulong)entry_point);
844
845         show_boot_progress (15);
846
847         /*
848          * RTEMS Parameters:
849          *   r3: ptr to board info data
850          */
851
852         (*entry_point ) ( gd->bd );
853 }
854
855 #if defined(CONFIG_CMD_ELF)
856 static void
857 do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
858                   ulong addr, ulong *len_ptr, int verify)
859 {
860         image_header_t *hdr = &header;
861         char str[80];
862
863         sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
864         setenv("loadaddr", str);
865         do_bootvx(cmdtp, 0, 0, NULL);
866 }
867
868 static void
869 do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
870                  ulong addr, ulong *len_ptr, int verify)
871 {
872         image_header_t *hdr = &header;
873         char *local_args[2];
874         char str[16];
875
876         sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
877         local_args[0] = argv[0];
878         local_args[1] = str;    /* and provide it via the arguments */
879         do_bootelf(cmdtp, 0, 2, local_args);
880 }
881 #endif
882
883 #ifdef CONFIG_LYNXKDI
884 static void
885 do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
886                  int    argc, char *argv[],
887                  ulong  addr,
888                  ulong  *len_ptr,
889                  int    verify)
890 {
891         lynxkdi_boot( &header );
892 }
893
894 #endif /* CONFIG_LYNXKDI */