]> git.sur5r.net Git - u-boot/blob - common/cmd_bootm.c
Update make target for ARM supported boards.
[u-boot] / common / cmd_bootm.c
1 /*
2  * (C) Copyright 2000-2002
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 /*
25  * Boot support
26  */
27 #include <common.h>
28 #include <watchdog.h>
29 #include <command.h>
30 #include <image.h>
31 #include <malloc.h>
32 #include <zlib.h>
33 #include <bzlib.h>
34 #include <environment.h>
35 #include <asm/byteorder.h>
36
37  /*cmd_boot.c*/
38  extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
39
40 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
41 #include <rtc.h>
42 #endif
43
44 #ifdef CFG_HUSH_PARSER
45 #include <hush.h>
46 #endif
47
48 #ifdef CONFIG_SHOW_BOOT_PROGRESS
49 # include <status_led.h>
50 # define SHOW_BOOT_PROGRESS(arg)        show_boot_progress(arg)
51 #else
52 # define SHOW_BOOT_PROGRESS(arg)
53 #endif
54
55 #ifdef CFG_INIT_RAM_LOCK
56 #include <asm/cache.h>
57 #endif
58
59 #ifdef CONFIG_LOGBUFFER
60 #include <logbuff.h>
61 #endif
62
63 #ifdef CONFIG_HAS_DATAFLASH
64 #include <dataflash.h>
65 #endif
66
67 /*
68  * Some systems (for example LWMON) have very short watchdog periods;
69  * we must make sure to split long operations like memmove() or
70  * crc32() into reasonable chunks.
71  */
72 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
73 # define CHUNKSZ (64 * 1024)
74 #endif
75
76 int  gunzip (void *, int, unsigned char *, unsigned long *);
77
78 static void *zalloc(void *, unsigned, unsigned);
79 static void zfree(void *, void *, unsigned);
80
81 #if (CONFIG_COMMANDS & CFG_CMD_IMI)
82 static int image_info (unsigned long addr);
83 #endif
84
85 #if (CONFIG_COMMANDS & CFG_CMD_IMLS)
86 #include <flash.h>
87 extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
88 static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
89 #endif
90
91 static void print_type (image_header_t *hdr);
92
93 #ifdef __I386__
94 image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);
95 #endif
96
97 /*
98  *  Continue booting an OS image; caller already has:
99  *  - copied image header to global variable `header'
100  *  - checked header magic number, checksums (both header & image),
101  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
102  *  - loaded (first part of) image to header load address,
103  *  - disabled interrupts.
104  */
105 typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,
106                           int   argc, char *argv[],
107                           ulong addr,           /* of image to boot */
108                           ulong *len_ptr,       /* multi-file image length table */
109                           int   verify);        /* getenv("verify")[0] != 'n' */
110
111 #ifdef  DEBUG
112 extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
113 #endif
114
115 #ifdef CONFIG_PPC
116 static boot_os_Fcn do_bootm_linux;
117 #else
118 extern boot_os_Fcn do_bootm_linux;
119 #endif
120 #ifdef CONFIG_SILENT_CONSOLE
121 static void fixup_silent_linux (void);
122 #endif
123 static boot_os_Fcn do_bootm_netbsd;
124 static boot_os_Fcn do_bootm_rtems;
125 #if (CONFIG_COMMANDS & CFG_CMD_ELF)
126 static boot_os_Fcn do_bootm_vxworks;
127 static boot_os_Fcn do_bootm_qnxelf;
128 int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
129 int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
130 #endif /* CFG_CMD_ELF */
131 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
132 static boot_os_Fcn do_bootm_artos;
133 #endif
134 #ifdef CONFIG_LYNXKDI
135 static boot_os_Fcn do_bootm_lynxkdi;
136 extern void lynxkdi_boot( image_header_t * );
137 #endif
138
139 image_header_t header;
140
141 ulong load_addr = CFG_LOAD_ADDR;                /* Default Load Address */
142
143 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
144 {
145         ulong   iflag;
146         ulong   addr;
147         ulong   data, len, checksum;
148         ulong  *len_ptr;
149         uint    unc_len = 0x400000;
150         int     i, verify;
151         char    *name, *s;
152         int     (*appl)(int, char *[]);
153         image_header_t *hdr = &header;
154
155         s = getenv ("verify");
156         verify = (s && (*s == 'n')) ? 0 : 1;
157
158         if (argc < 2) {
159                 addr = load_addr;
160         } else {
161                 addr = simple_strtoul(argv[1], NULL, 16);
162         }
163
164         SHOW_BOOT_PROGRESS (1);
165         printf ("## Booting image at %08lx ...\n", addr);
166
167         /* Copy header so we can blank CRC field for re-calculation */
168 #ifdef CONFIG_HAS_DATAFLASH
169         if (addr_dataflash(addr)){
170                 read_dataflash(addr, sizeof(image_header_t), (char *)&header);
171         } else
172 #endif
173         memmove (&header, (char *)addr, sizeof(image_header_t));
174
175         if (ntohl(hdr->ih_magic) != IH_MAGIC) {
176 #ifdef __I386__ /* correct image format not implemented yet - fake it */
177                 if (fake_header(hdr, (void*)addr, -1) != NULL) {
178                         /* to compensate for the addition below */
179                         addr -= sizeof(image_header_t);
180                         /* turnof verify,
181                          * fake_header() does not fake the data crc
182                          */
183                         verify = 0;
184                 } else
185 #endif  /* __I386__ */
186             {
187                 puts ("Bad Magic Number\n");
188                 SHOW_BOOT_PROGRESS (-1);
189                 return 1;
190             }
191         }
192         SHOW_BOOT_PROGRESS (2);
193
194         data = (ulong)&header;
195         len  = sizeof(image_header_t);
196
197         checksum = ntohl(hdr->ih_hcrc);
198         hdr->ih_hcrc = 0;
199
200         if (crc32 (0, (char *)data, len) != checksum) {
201                 puts ("Bad Header Checksum\n");
202                 SHOW_BOOT_PROGRESS (-2);
203                 return 1;
204         }
205         SHOW_BOOT_PROGRESS (3);
206
207 #ifdef CONFIG_HAS_DATAFLASH
208         if (addr_dataflash(addr)){
209                 len  = ntohl(hdr->ih_size) + sizeof(image_header_t);
210                 read_dataflash(addr, len, (char *)CFG_LOAD_ADDR);
211                 addr = CFG_LOAD_ADDR;
212         }
213 #endif
214
215
216         /* for multi-file images we need the data part, too */
217         print_image_hdr ((image_header_t *)addr);
218
219         data = addr + sizeof(image_header_t);
220         len  = ntohl(hdr->ih_size);
221
222         if (verify) {
223                 puts ("   Verifying Checksum ... ");
224                 if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
225                         printf ("Bad Data CRC\n");
226                         SHOW_BOOT_PROGRESS (-3);
227                         return 1;
228                 }
229                 puts ("OK\n");
230         }
231         SHOW_BOOT_PROGRESS (4);
232
233         len_ptr = (ulong *)data;
234
235 #if defined(__PPC__)
236         if (hdr->ih_arch != IH_CPU_PPC)
237 #elif defined(__ARM__)
238         if (hdr->ih_arch != IH_CPU_ARM)
239 #elif defined(__I386__)
240         if (hdr->ih_arch != IH_CPU_I386)
241 #elif defined(__mips__)
242         if (hdr->ih_arch != IH_CPU_MIPS)
243 #elif defined(__nios__)
244         if (hdr->ih_arch != IH_CPU_NIOS)
245 #elif defined(__M68K__)
246         if (hdr->ih_arch != IH_CPU_M68K)
247 #elif defined(__microblaze__)
248         if (hdr->ih_arch != IH_CPU_MICROBLAZE)
249 #elif defined(__nios2__)
250         if (hdr->ih_arch != IH_CPU_NIOS2)
251 #else
252 # error Unknown CPU type
253 #endif
254         {
255                 printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);
256                 SHOW_BOOT_PROGRESS (-4);
257                 return 1;
258         }
259         SHOW_BOOT_PROGRESS (5);
260
261         switch (hdr->ih_type) {
262         case IH_TYPE_STANDALONE:
263                 name = "Standalone Application";
264                 /* A second argument overwrites the load address */
265                 if (argc > 2) {
266                         hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16));
267                 }
268                 break;
269         case IH_TYPE_KERNEL:
270                 name = "Kernel Image";
271                 break;
272         case IH_TYPE_MULTI:
273                 name = "Multi-File Image";
274                 len  = ntohl(len_ptr[0]);
275                 /* OS kernel is always the first image */
276                 data += 8; /* kernel_len + terminator */
277                 for (i=1; len_ptr[i]; ++i)
278                         data += 4;
279                 break;
280         default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
281                 SHOW_BOOT_PROGRESS (-5);
282                 return 1;
283         }
284         SHOW_BOOT_PROGRESS (6);
285
286         /*
287          * We have reached the point of no return: we are going to
288          * overwrite all exception vector code, so we cannot easily
289          * recover from any failures any more...
290          */
291
292         iflag = disable_interrupts();
293
294 #ifdef CONFIG_AMIGAONEG3SE
295         /*
296          * We've possible left the caches enabled during
297          * bios emulation, so turn them off again
298          */
299         icache_disable();
300         invalidate_l1_instruction_cache();
301         flush_data_cache();
302         dcache_disable();
303 #endif
304
305         switch (hdr->ih_comp) {
306         case IH_COMP_NONE:
307                 if(ntohl(hdr->ih_load) == addr) {
308                         printf ("   XIP %s ... ", name);
309                 } else {
310 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
311                         size_t l = len;
312                         void *to = (void *)ntohl(hdr->ih_load);
313                         void *from = (void *)data;
314
315                         printf ("   Loading %s ... ", name);
316
317                         while (l > 0) {
318                                 size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
319                                 WATCHDOG_RESET();
320                                 memmove (to, from, tail);
321                                 to += tail;
322                                 from += tail;
323                                 l -= tail;
324                         }
325 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
326                         memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
327 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
328                 }
329                 break;
330         case IH_COMP_GZIP:
331                 printf ("   Uncompressing %s ... ", name);
332                 if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,
333                             (uchar *)data, &len) != 0) {
334                         puts ("GUNZIP ERROR - must RESET board to recover\n");
335                         SHOW_BOOT_PROGRESS (-6);
336                         do_reset (cmdtp, flag, argc, argv);
337                 }
338                 break;
339 #ifdef CONFIG_BZIP2
340         case IH_COMP_BZIP2:
341                 printf ("   Uncompressing %s ... ", name);
342                 /*
343                  * If we've got less than 4 MB of malloc() space,
344                  * use slower decompression algorithm which requires
345                  * at most 2300 KB of memory.
346                  */
347                 i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),
348                                                 &unc_len, (char *)data, len,
349                                                 CFG_MALLOC_LEN < (4096 * 1024), 0);
350                 if (i != BZ_OK) {
351                         printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
352                         SHOW_BOOT_PROGRESS (-6);
353                         udelay(100000);
354                         do_reset (cmdtp, flag, argc, argv);
355                 }
356                 break;
357 #endif /* CONFIG_BZIP2 */
358         default:
359                 if (iflag)
360                         enable_interrupts();
361                 printf ("Unimplemented compression type %d\n", hdr->ih_comp);
362                 SHOW_BOOT_PROGRESS (-7);
363                 return 1;
364         }
365         puts ("OK\n");
366         SHOW_BOOT_PROGRESS (7);
367
368         switch (hdr->ih_type) {
369         case IH_TYPE_STANDALONE:
370                 if (iflag)
371                         enable_interrupts();
372
373                 /* load (and uncompress), but don't start if "autostart"
374                  * is set to "no"
375                  */
376                 if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {
377                         char buf[32];
378                         sprintf(buf, "%lX", len);
379                         setenv("filesize", buf);
380                         return 0;
381                 }
382                 appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);
383                 (*appl)(argc-1, &argv[1]);
384                 return 0;
385         case IH_TYPE_KERNEL:
386         case IH_TYPE_MULTI:
387                 /* handled below */
388                 break;
389         default:
390                 if (iflag)
391                         enable_interrupts();
392                 printf ("Can't boot image type %d\n", hdr->ih_type);
393                 SHOW_BOOT_PROGRESS (-8);
394                 return 1;
395         }
396         SHOW_BOOT_PROGRESS (8);
397
398         switch (hdr->ih_os) {
399         default:                        /* handled by (original) Linux case */
400         case IH_OS_LINUX:
401 #ifdef CONFIG_SILENT_CONSOLE
402             fixup_silent_linux();
403 #endif
404             do_bootm_linux  (cmdtp, flag, argc, argv,
405                              addr, len_ptr, verify);
406             break;
407         case IH_OS_NETBSD:
408             do_bootm_netbsd (cmdtp, flag, argc, argv,
409                              addr, len_ptr, verify);
410             break;
411
412 #ifdef CONFIG_LYNXKDI
413         case IH_OS_LYNXOS:
414             do_bootm_lynxkdi (cmdtp, flag, argc, argv,
415                              addr, len_ptr, verify);
416             break;
417 #endif
418
419         case IH_OS_RTEMS:
420             do_bootm_rtems (cmdtp, flag, argc, argv,
421                              addr, len_ptr, verify);
422             break;
423
424 #if (CONFIG_COMMANDS & CFG_CMD_ELF)
425         case IH_OS_VXWORKS:
426             do_bootm_vxworks (cmdtp, flag, argc, argv,
427                               addr, len_ptr, verify);
428             break;
429         case IH_OS_QNX:
430             do_bootm_qnxelf (cmdtp, flag, argc, argv,
431                               addr, len_ptr, verify);
432             break;
433 #endif /* CFG_CMD_ELF */
434 #ifdef CONFIG_ARTOS
435         case IH_OS_ARTOS:
436             do_bootm_artos  (cmdtp, flag, argc, argv,
437                              addr, len_ptr, verify);
438             break;
439 #endif
440         }
441
442         SHOW_BOOT_PROGRESS (-9);
443 #ifdef DEBUG
444         puts ("\n## Control returned to monitor - resetting...\n");
445         do_reset (cmdtp, flag, argc, argv);
446 #endif
447         return 1;
448 }
449
450 U_BOOT_CMD(
451         bootm,  CFG_MAXARGS,    1,      do_bootm,
452         "bootm   - boot application image from memory\n",
453         "[addr [arg ...]]\n    - boot application image stored in memory\n"
454         "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
455         "\t'arg' can be the address of an initrd image\n"
456 );
457
458 #ifdef CONFIG_SILENT_CONSOLE
459 static void
460 fixup_silent_linux ()
461 {
462         DECLARE_GLOBAL_DATA_PTR;
463         char buf[256], *start, *end;
464         char *cmdline = getenv ("bootargs");
465
466         /* Only fix cmdline when requested */
467         if (!(gd->flags & GD_FLG_SILENT))
468                 return;
469
470         debug ("before silent fix-up: %s\n", cmdline);
471         if (cmdline) {
472                 if ((start = strstr (cmdline, "console=")) != NULL) {
473                         end = strchr (start, ' ');
474                         strncpy (buf, cmdline, (start - cmdline + 8));
475                         if (end)
476                                 strcpy (buf + (start - cmdline + 8), end);
477                         else
478                                 buf[start - cmdline + 8] = '\0';
479                 } else {
480                         strcpy (buf, cmdline);
481                         strcat (buf, " console=");
482                 }
483         } else {
484                 strcpy (buf, "console=");
485         }
486
487         setenv ("bootargs", buf);
488         debug ("after silent fix-up: %s\n", buf);
489 }
490 #endif /* CONFIG_SILENT_CONSOLE */
491
492 #ifdef CONFIG_PPC
493 static void
494 do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
495                 int     argc, char *argv[],
496                 ulong   addr,
497                 ulong   *len_ptr,
498                 int     verify)
499 {
500         DECLARE_GLOBAL_DATA_PTR;
501
502         ulong   sp;
503         ulong   len, checksum;
504         ulong   initrd_start, initrd_end;
505         ulong   cmd_start, cmd_end;
506         ulong   initrd_high;
507         ulong   data;
508         int     initrd_copy_to_ram = 1;
509         char    *cmdline;
510         char    *s;
511         bd_t    *kbd;
512         void    (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
513         image_header_t *hdr = &header;
514
515         if ((s = getenv ("initrd_high")) != NULL) {
516                 /* a value of "no" or a similar string will act like 0,
517                  * turning the "load high" feature off. This is intentional.
518                  */
519                 initrd_high = simple_strtoul(s, NULL, 16);
520                 if (initrd_high == ~0)
521                         initrd_copy_to_ram = 0;
522         } else {        /* not set, no restrictions to load high */
523                 initrd_high = ~0;
524         }
525
526 #ifdef CONFIG_LOGBUFFER
527         kbd=gd->bd;
528         /* Prevent initrd from overwriting logbuffer */
529         if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD))
530                 initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD;
531         debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN);
532 #endif
533
534         /*
535          * Booting a (Linux) kernel image
536          *
537          * Allocate space for command line and board info - the
538          * address should be as high as possible within the reach of
539          * the kernel (see CFG_BOOTMAPSZ settings), but in unused
540          * memory, which means far enough below the current stack
541          * pointer.
542          */
543
544         asm( "mr %0,1": "=r"(sp) : );
545
546         debug ("## Current stack ends at 0x%08lX ", sp);
547
548         sp -= 2048;             /* just to be sure */
549         if (sp > CFG_BOOTMAPSZ)
550                 sp = CFG_BOOTMAPSZ;
551         sp &= ~0xF;
552
553         debug ("=> set upper limit to 0x%08lX\n", sp);
554
555         cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
556         kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
557
558         if ((s = getenv("bootargs")) == NULL)
559                 s = "";
560
561         strcpy (cmdline, s);
562
563         cmd_start    = (ulong)&cmdline[0];
564         cmd_end      = cmd_start + strlen(cmdline);
565
566         *kbd = *(gd->bd);
567
568 #ifdef  DEBUG
569         printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
570
571         do_bdinfo (NULL, 0, 0, NULL);
572 #endif
573
574         if ((s = getenv ("clocks_in_mhz")) != NULL) {
575                 /* convert all clock information to MHz */
576                 kbd->bi_intfreq /= 1000000L;
577                 kbd->bi_busfreq /= 1000000L;
578 #if defined(CONFIG_MPC8220)
579         kbd->bi_inpfreq /= 1000000L;
580         kbd->bi_pcifreq /= 1000000L;
581         kbd->bi_pevfreq /= 1000000L;
582         kbd->bi_flbfreq /= 1000000L;
583         kbd->bi_vcofreq /= 1000000L;
584 #endif
585 #if defined(CONFIG_CPM2)
586                 kbd->bi_cpmfreq /= 1000000L;
587                 kbd->bi_brgfreq /= 1000000L;
588                 kbd->bi_sccfreq /= 1000000L;
589                 kbd->bi_vco     /= 1000000L;
590 #endif
591 #if defined(CONFIG_MPC5xxx)
592                 kbd->bi_ipbfreq /= 1000000L;
593                 kbd->bi_pcifreq /= 1000000L;
594 #endif /* CONFIG_MPC5xxx */
595         }
596
597         kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))hdr->ih_ep;
598
599         /*
600          * Check if there is an initrd image
601          */
602         if (argc >= 3) {
603                 SHOW_BOOT_PROGRESS (9);
604
605                 addr = simple_strtoul(argv[2], NULL, 16);
606
607                 printf ("## Loading RAMDisk Image at %08lx ...\n", addr);
608
609                 /* Copy header so we can blank CRC field for re-calculation */
610                 memmove (&header, (char *)addr, sizeof(image_header_t));
611
612                 if (hdr->ih_magic  != IH_MAGIC) {
613                         puts ("Bad Magic Number\n");
614                         SHOW_BOOT_PROGRESS (-10);
615                         do_reset (cmdtp, flag, argc, argv);
616                 }
617
618                 data = (ulong)&header;
619                 len  = sizeof(image_header_t);
620
621                 checksum = hdr->ih_hcrc;
622                 hdr->ih_hcrc = 0;
623
624                 if (crc32 (0, (char *)data, len) != checksum) {
625                         puts ("Bad Header Checksum\n");
626                         SHOW_BOOT_PROGRESS (-11);
627                         do_reset (cmdtp, flag, argc, argv);
628                 }
629
630                 SHOW_BOOT_PROGRESS (10);
631
632                 print_image_hdr (hdr);
633
634                 data = addr + sizeof(image_header_t);
635                 len  = hdr->ih_size;
636
637                 if (verify) {
638                         ulong csum = 0;
639 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
640                         ulong cdata = data, edata = cdata + len;
641 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
642
643                         puts ("   Verifying Checksum ... ");
644
645 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
646
647                         while (cdata < edata) {
648                                 ulong chunk = edata - cdata;
649
650                                 if (chunk > CHUNKSZ)
651                                         chunk = CHUNKSZ;
652                                 csum = crc32 (csum, (char *)cdata, chunk);
653                                 cdata += chunk;
654
655                                 WATCHDOG_RESET();
656                         }
657 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
658                         csum = crc32 (0, (char *)data, len);
659 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
660
661                         if (csum != hdr->ih_dcrc) {
662                                 puts ("Bad Data CRC\n");
663                                 SHOW_BOOT_PROGRESS (-12);
664                                 do_reset (cmdtp, flag, argc, argv);
665                         }
666                         puts ("OK\n");
667                 }
668
669                 SHOW_BOOT_PROGRESS (11);
670
671                 if ((hdr->ih_os   != IH_OS_LINUX)       ||
672                     (hdr->ih_arch != IH_CPU_PPC)        ||
673                     (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
674                         puts ("No Linux PPC Ramdisk Image\n");
675                         SHOW_BOOT_PROGRESS (-13);
676                         do_reset (cmdtp, flag, argc, argv);
677                 }
678
679                 /*
680                  * Now check if we have a multifile image
681                  */
682         } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
683                 u_long tail    = ntohl(len_ptr[0]) % 4;
684                 int i;
685
686                 SHOW_BOOT_PROGRESS (13);
687
688                 /* skip kernel length and terminator */
689                 data = (ulong)(&len_ptr[2]);
690                 /* skip any additional image length fields */
691                 for (i=1; len_ptr[i]; ++i)
692                         data += 4;
693                 /* add kernel length, and align */
694                 data += ntohl(len_ptr[0]);
695                 if (tail) {
696                         data += 4 - tail;
697                 }
698
699                 len   = ntohl(len_ptr[1]);
700
701         } else {
702                 /*
703                  * no initrd image
704                  */
705                 SHOW_BOOT_PROGRESS (14);
706
707                 len = data = 0;
708         }
709
710         if (!data) {
711                 debug ("No initrd\n");
712         }
713
714         if (data) {
715             if (!initrd_copy_to_ram) {  /* zero-copy ramdisk support */
716                 initrd_start = data;
717                 initrd_end = initrd_start + len;
718             } else {
719                 initrd_start  = (ulong)kbd - len;
720                 initrd_start &= ~(4096 - 1);    /* align on page */
721
722                 if (initrd_high) {
723                         ulong nsp;
724
725                         /*
726                          * the inital ramdisk does not need to be within
727                          * CFG_BOOTMAPSZ as it is not accessed until after
728                          * the mm system is initialised.
729                          *
730                          * do the stack bottom calculation again and see if
731                          * the initrd will fit just below the monitor stack
732                          * bottom without overwriting the area allocated
733                          * above for command line args and board info.
734                          */
735                         asm( "mr %0,1": "=r"(nsp) : );
736                         nsp -= 2048;            /* just to be sure */
737                         nsp &= ~0xF;
738                         if (nsp > initrd_high)  /* limit as specified */
739                                 nsp = initrd_high;
740                         nsp -= len;
741                         nsp &= ~(4096 - 1);     /* align on page */
742                         if (nsp >= sp)
743                                 initrd_start = nsp;
744                 }
745
746                 SHOW_BOOT_PROGRESS (12);
747
748                 debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
749                         data, data + len - 1, len, len);
750
751                 initrd_end    = initrd_start + len;
752                 printf ("   Loading Ramdisk to %08lx, end %08lx ... ",
753                         initrd_start, initrd_end);
754 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
755                 {
756                         size_t l = len;
757                         void *to = (void *)initrd_start;
758                         void *from = (void *)data;
759
760                         while (l > 0) {
761                                 size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l;
762                                 WATCHDOG_RESET();
763                                 memmove (to, from, tail);
764                                 to += tail;
765                                 from += tail;
766                                 l -= tail;
767                         }
768                 }
769 #else   /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
770                 memmove ((void *)initrd_start, (void *)data, len);
771 #endif  /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
772                 puts ("OK\n");
773             }
774         } else {
775                 initrd_start = 0;
776                 initrd_end = 0;
777         }
778
779
780         debug ("## Transferring control to Linux (at address %08lx) ...\n",
781                 (ulong)kernel);
782
783         SHOW_BOOT_PROGRESS (15);
784
785 #if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
786         unlock_ram_in_cache();
787 #endif
788         /*
789          * Linux Kernel Parameters:
790          *   r3: ptr to board info data
791          *   r4: initrd_start or 0 if no initrd
792          *   r5: initrd_end - unused if r4 is 0
793          *   r6: Start of command line string
794          *   r7: End   of command line string
795          */
796         (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
797 }
798 #endif /* CONFIG_PPC */
799
800 static void
801 do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
802                 int     argc, char *argv[],
803                 ulong   addr,
804                 ulong   *len_ptr,
805                 int     verify)
806 {
807         DECLARE_GLOBAL_DATA_PTR;
808
809         image_header_t *hdr = &header;
810
811         void    (*loader)(bd_t *, image_header_t *, char *, char *);
812         image_header_t *img_addr;
813         char     *consdev;
814         char     *cmdline;
815
816
817         /*
818          * Booting a (NetBSD) kernel image
819          *
820          * This process is pretty similar to a standalone application:
821          * The (first part of an multi-) image must be a stage-2 loader,
822          * which in turn is responsible for loading & invoking the actual
823          * kernel.  The only differences are the parameters being passed:
824          * besides the board info strucure, the loader expects a command
825          * line, the name of the console device, and (optionally) the
826          * address of the original image header.
827          */
828
829         img_addr = 0;
830         if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]))
831                 img_addr = (image_header_t *) addr;
832
833
834         consdev = "";
835 #if   defined (CONFIG_8xx_CONS_SMC1)
836         consdev = "smc1";
837 #elif defined (CONFIG_8xx_CONS_SMC2)
838         consdev = "smc2";
839 #elif defined (CONFIG_8xx_CONS_SCC2)
840         consdev = "scc2";
841 #elif defined (CONFIG_8xx_CONS_SCC3)
842         consdev = "scc3";
843 #endif
844
845         if (argc > 2) {
846                 ulong len;
847                 int   i;
848
849                 for (i=2, len=0 ; i<argc ; i+=1)
850                         len += strlen (argv[i]) + 1;
851                 cmdline = malloc (len);
852
853                 for (i=2, len=0 ; i<argc ; i+=1) {
854                         if (i > 2)
855                                 cmdline[len++] = ' ';
856                         strcpy (&cmdline[len], argv[i]);
857                         len += strlen (argv[i]);
858                 }
859         } else if ((cmdline = getenv("bootargs")) == NULL) {
860                 cmdline = "";
861         }
862
863         loader = (void (*)(bd_t *, image_header_t *, char *, char *)) hdr->ih_ep;
864
865         printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
866                 (ulong)loader);
867
868         SHOW_BOOT_PROGRESS (15);
869
870         /*
871          * NetBSD Stage-2 Loader Parameters:
872          *   r3: ptr to board info data
873          *   r4: image address
874          *   r5: console device
875          *   r6: boot args string
876          */
877         (*loader) (gd->bd, img_addr, consdev, cmdline);
878 }
879
880 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
881
882 /* Function that returns a character from the environment */
883 extern uchar (*env_get_char)(int);
884
885 static void
886 do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
887                 int     argc, char *argv[],
888                 ulong   addr,
889                 ulong   *len_ptr,
890                 int     verify)
891 {
892         DECLARE_GLOBAL_DATA_PTR;
893         ulong top;
894         char *s, *cmdline;
895         char **fwenv, **ss;
896         int i, j, nxt, len, envno, envsz;
897         bd_t *kbd;
898         void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top);
899         image_header_t *hdr = &header;
900
901         /*
902          * Booting an ARTOS kernel image + application
903          */
904
905         /* this used to be the top of memory, but was wrong... */
906 #ifdef CONFIG_PPC
907         /* get stack pointer */
908         asm volatile ("mr %0,1" : "=r"(top) );
909 #endif
910         debug ("## Current stack ends at 0x%08lX ", top);
911
912         top -= 2048;            /* just to be sure */
913         if (top > CFG_BOOTMAPSZ)
914                 top = CFG_BOOTMAPSZ;
915         top &= ~0xF;
916
917         debug ("=> set upper limit to 0x%08lX\n", top);
918
919         /* first check the artos specific boot args, then the linux args*/
920         if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL)
921                 s = "";
922
923         /* get length of cmdline, and place it */
924         len = strlen(s);
925         top = (top - (len + 1)) & ~0xF;
926         cmdline = (char *)top;
927         debug ("## cmdline at 0x%08lX ", top);
928         strcpy(cmdline, s);
929
930         /* copy bdinfo */
931         top = (top - sizeof(bd_t)) & ~0xF;
932         debug ("## bd at 0x%08lX ", top);
933         kbd = (bd_t *)top;
934         memcpy(kbd, gd->bd, sizeof(bd_t));
935
936         /* first find number of env entries, and their size */
937         envno = 0;
938         envsz = 0;
939         for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
940                 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
941                         ;
942                 envno++;
943                 envsz += (nxt - i) + 1; /* plus trailing zero */
944         }
945         envno++;        /* plus the terminating zero */
946         debug ("## %u envvars total size %u ", envno, envsz);
947
948         top = (top - sizeof(char **)*envno) & ~0xF;
949         fwenv = (char **)top;
950         debug ("## fwenv at 0x%08lX ", top);
951
952         top = (top - envsz) & ~0xF;
953         s = (char *)top;
954         ss = fwenv;
955
956         /* now copy them */
957         for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
958                 for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
959                         ;
960                 *ss++ = s;
961                 for (j = i; j < nxt; ++j)
962                         *s++ = env_get_char(j);
963                 *s++ = '\0';
964         }
965         *ss++ = NULL;   /* terminate */
966
967         entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep);
968         (*entry)(kbd, cmdline, fwenv, top);
969 }
970 #endif
971
972
973 #if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
974 int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
975 {
976         int rcode = 0;
977 #ifndef CFG_HUSH_PARSER
978         if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1;
979 #else
980         if (parse_string_outer(getenv("bootcmd"),
981                 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1;
982 #endif
983         return rcode;
984 }
985
986 U_BOOT_CMD(
987         boot,   1,      1,      do_bootd,
988         "boot    - boot default, i.e., run 'bootcmd'\n",
989         NULL
990 );
991
992 /* keep old command name "bootd" for backward compatibility */
993 U_BOOT_CMD(
994         bootd, 1,       1,      do_bootd,
995         "bootd   - boot default, i.e., run 'bootcmd'\n",
996         NULL
997 );
998
999 #endif
1000
1001 #if (CONFIG_COMMANDS & CFG_CMD_IMI)
1002 int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1003 {
1004         int     arg;
1005         ulong   addr;
1006         int     rcode=0;
1007
1008         if (argc < 2) {
1009                 return image_info (load_addr);
1010         }
1011
1012         for (arg=1; arg <argc; ++arg) {
1013                 addr = simple_strtoul(argv[arg], NULL, 16);
1014                 if (image_info (addr) != 0) rcode = 1;
1015         }
1016         return rcode;
1017 }
1018
1019 static int image_info (ulong addr)
1020 {
1021         ulong   data, len, checksum;
1022         image_header_t *hdr = &header;
1023
1024         printf ("\n## Checking Image at %08lx ...\n", addr);
1025
1026         /* Copy header so we can blank CRC field for re-calculation */
1027         memmove (&header, (char *)addr, sizeof(image_header_t));
1028
1029         if (ntohl(hdr->ih_magic) != IH_MAGIC) {
1030                 puts ("   Bad Magic Number\n");
1031                 return 1;
1032         }
1033
1034         data = (ulong)&header;
1035         len  = sizeof(image_header_t);
1036
1037         checksum = ntohl(hdr->ih_hcrc);
1038         hdr->ih_hcrc = 0;
1039
1040         if (crc32 (0, (char *)data, len) != checksum) {
1041                 puts ("   Bad Header Checksum\n");
1042                 return 1;
1043         }
1044
1045         /* for multi-file images we need the data part, too */
1046         print_image_hdr ((image_header_t *)addr);
1047
1048         data = addr + sizeof(image_header_t);
1049         len  = ntohl(hdr->ih_size);
1050
1051         puts ("   Verifying Checksum ... ");
1052         if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
1053                 puts ("   Bad Data CRC\n");
1054                 return 1;
1055         }
1056         puts ("OK\n");
1057         return 0;
1058 }
1059
1060 U_BOOT_CMD(
1061         iminfo, CFG_MAXARGS,    1,      do_iminfo,
1062         "iminfo  - print header information for application image\n",
1063         "addr [addr ...]\n"
1064         "    - print header information for application image starting at\n"
1065         "      address 'addr' in memory; this includes verification of the\n"
1066         "      image contents (magic number, header and payload checksums)\n"
1067 );
1068
1069 #endif  /* CFG_CMD_IMI */
1070
1071 #if (CONFIG_COMMANDS & CFG_CMD_IMLS)
1072 /*-----------------------------------------------------------------------
1073  * List all images found in flash.
1074  */
1075 int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1076 {
1077         flash_info_t *info;
1078         int i, j;
1079         image_header_t *hdr;
1080         ulong data, len, checksum;
1081
1082         for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
1083                 if (info->flash_id == FLASH_UNKNOWN)
1084                         goto next_bank;
1085                 for (j=0; j<CFG_MAX_FLASH_SECT; ++j) {
1086
1087                         if (!(hdr=(image_header_t *)info->start[j]) ||
1088                             (ntohl(hdr->ih_magic) != IH_MAGIC))
1089                                 goto next_sector;
1090
1091                         /* Copy header so we can blank CRC field for re-calculation */
1092                         memmove (&header, (char *)hdr, sizeof(image_header_t));
1093
1094                         checksum = ntohl(header.ih_hcrc);
1095                         header.ih_hcrc = 0;
1096
1097                         if (crc32 (0, (char *)&header, sizeof(image_header_t))
1098                             != checksum)
1099                                 goto next_sector;
1100
1101                         printf ("Image at %08lX:\n", (ulong)hdr);
1102                         print_image_hdr( hdr );
1103
1104                         data = (ulong)hdr + sizeof(image_header_t);
1105                         len  = ntohl(hdr->ih_size);
1106
1107                         puts ("   Verifying Checksum ... ");
1108                         if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
1109                                 puts ("   Bad Data CRC\n");
1110                         }
1111                         puts ("OK\n");
1112 next_sector:            ;
1113                 }
1114 next_bank:      ;
1115         }
1116
1117         return (0);
1118 }
1119
1120 U_BOOT_CMD(
1121         imls,   1,              1,      do_imls,
1122         "imls    - list all images found in flash\n",
1123         "\n"
1124         "    - Prints information about all images found at sector\n"
1125         "      boundaries in flash.\n"
1126 );
1127 #endif  /* CFG_CMD_IMLS */
1128
1129 void
1130 print_image_hdr (image_header_t *hdr)
1131 {
1132 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
1133         time_t timestamp = (time_t)ntohl(hdr->ih_time);
1134         struct rtc_time tm;
1135 #endif
1136
1137         printf ("   Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name);
1138 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
1139         to_tm (timestamp, &tm);
1140         printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n",
1141                 tm.tm_year, tm.tm_mon, tm.tm_mday,
1142                 tm.tm_hour, tm.tm_min, tm.tm_sec);
1143 #endif  /* CFG_CMD_DATE, CONFIG_TIMESTAMP */
1144         puts ("   Image Type:   "); print_type(hdr);
1145         printf ("\n   Data Size:    %d Bytes = ", ntohl(hdr->ih_size));
1146         print_size (ntohl(hdr->ih_size), "\n");
1147         printf ("   Load Address: %08x\n"
1148                 "   Entry Point:  %08x\n",
1149                  ntohl(hdr->ih_load), ntohl(hdr->ih_ep));
1150
1151         if (hdr->ih_type == IH_TYPE_MULTI) {
1152                 int i;
1153                 ulong len;
1154                 ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
1155
1156                 puts ("   Contents:\n");
1157                 for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) {
1158                         printf ("   Image %d: %8ld Bytes = ", i, len);
1159                         print_size (len, "\n");
1160                 }
1161         }
1162 }
1163
1164
1165 static void
1166 print_type (image_header_t *hdr)
1167 {
1168         char *os, *arch, *type, *comp;
1169
1170         switch (hdr->ih_os) {
1171         case IH_OS_INVALID:     os = "Invalid OS";              break;
1172         case IH_OS_NETBSD:      os = "NetBSD";                  break;
1173         case IH_OS_LINUX:       os = "Linux";                   break;
1174         case IH_OS_VXWORKS:     os = "VxWorks";                 break;
1175         case IH_OS_QNX:         os = "QNX";                     break;
1176         case IH_OS_U_BOOT:      os = "U-Boot";                  break;
1177         case IH_OS_RTEMS:       os = "RTEMS";                   break;
1178 #ifdef CONFIG_ARTOS
1179         case IH_OS_ARTOS:       os = "ARTOS";                   break;
1180 #endif
1181 #ifdef CONFIG_LYNXKDI
1182         case IH_OS_LYNXOS:      os = "LynxOS";                  break;
1183 #endif
1184         default:                os = "Unknown OS";              break;
1185         }
1186
1187         switch (hdr->ih_arch) {
1188         case IH_CPU_INVALID:    arch = "Invalid CPU";           break;
1189         case IH_CPU_ALPHA:      arch = "Alpha";                 break;
1190         case IH_CPU_ARM:        arch = "ARM";                   break;
1191         case IH_CPU_I386:       arch = "Intel x86";             break;
1192         case IH_CPU_IA64:       arch = "IA64";                  break;
1193         case IH_CPU_MIPS:       arch = "MIPS";                  break;
1194         case IH_CPU_MIPS64:     arch = "MIPS 64 Bit";           break;
1195         case IH_CPU_PPC:        arch = "PowerPC";               break;
1196         case IH_CPU_S390:       arch = "IBM S390";              break;
1197         case IH_CPU_SH:         arch = "SuperH";                break;
1198         case IH_CPU_SPARC:      arch = "SPARC";                 break;
1199         case IH_CPU_SPARC64:    arch = "SPARC 64 Bit";          break;
1200         case IH_CPU_M68K:       arch = "M68K";                  break;
1201         case IH_CPU_MICROBLAZE: arch = "Microblaze";            break;
1202         case IH_CPU_NIOS:       arch = "Nios";                  break;
1203         case IH_CPU_NIOS2:      arch = "Nios-II";               break;
1204         default:                arch = "Unknown Architecture";  break;
1205         }
1206
1207         switch (hdr->ih_type) {
1208         case IH_TYPE_INVALID:   type = "Invalid Image";         break;
1209         case IH_TYPE_STANDALONE:type = "Standalone Program";    break;
1210         case IH_TYPE_KERNEL:    type = "Kernel Image";          break;
1211         case IH_TYPE_RAMDISK:   type = "RAMDisk Image";         break;
1212         case IH_TYPE_MULTI:     type = "Multi-File Image";      break;
1213         case IH_TYPE_FIRMWARE:  type = "Firmware";              break;
1214         case IH_TYPE_SCRIPT:    type = "Script";                break;
1215         default:                type = "Unknown Image";         break;
1216         }
1217
1218         switch (hdr->ih_comp) {
1219         case IH_COMP_NONE:      comp = "uncompressed";          break;
1220         case IH_COMP_GZIP:      comp = "gzip compressed";       break;
1221         case IH_COMP_BZIP2:     comp = "bzip2 compressed";      break;
1222         default:                comp = "unknown compression";   break;
1223         }
1224
1225         printf ("%s %s %s (%s)", arch, os, type, comp);
1226 }
1227
1228 #define ZALLOC_ALIGNMENT        16
1229
1230 static void *zalloc(void *x, unsigned items, unsigned size)
1231 {
1232         void *p;
1233
1234         size *= items;
1235         size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
1236
1237         p = malloc (size);
1238
1239         return (p);
1240 }
1241
1242 static void zfree(void *x, void *addr, unsigned nb)
1243 {
1244         free (addr);
1245 }
1246
1247 #define HEAD_CRC        2
1248 #define EXTRA_FIELD     4
1249 #define ORIG_NAME       8
1250 #define COMMENT         0x10
1251 #define RESERVED        0xe0
1252
1253 #define DEFLATED        8
1254
1255 int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
1256 {
1257         z_stream s;
1258         int r, i, flags;
1259
1260         /* skip header */
1261         i = 10;
1262         flags = src[3];
1263         if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
1264                 puts ("Error: Bad gzipped data\n");
1265                 return (-1);
1266         }
1267         if ((flags & EXTRA_FIELD) != 0)
1268                 i = 12 + src[10] + (src[11] << 8);
1269         if ((flags & ORIG_NAME) != 0)
1270                 while (src[i++] != 0)
1271                         ;
1272         if ((flags & COMMENT) != 0)
1273                 while (src[i++] != 0)
1274                         ;
1275         if ((flags & HEAD_CRC) != 0)
1276                 i += 2;
1277         if (i >= *lenp) {
1278                 puts ("Error: gunzip out of data in header\n");
1279                 return (-1);
1280         }
1281
1282         s.zalloc = zalloc;
1283         s.zfree = zfree;
1284 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
1285         s.outcb = (cb_func)WATCHDOG_RESET;
1286 #else
1287         s.outcb = Z_NULL;
1288 #endif  /* CONFIG_HW_WATCHDOG */
1289
1290         r = inflateInit2(&s, -MAX_WBITS);
1291         if (r != Z_OK) {
1292                 printf ("Error: inflateInit2() returned %d\n", r);
1293                 return (-1);
1294         }
1295         s.next_in = src + i;
1296         s.avail_in = *lenp - i;
1297         s.next_out = dst;
1298         s.avail_out = dstlen;
1299         r = inflate(&s, Z_FINISH);
1300         if (r != Z_OK && r != Z_STREAM_END) {
1301                 printf ("Error: inflate() returned %d\n", r);
1302                 return (-1);
1303         }
1304         *lenp = s.next_out - (unsigned char *) dst;
1305         inflateEnd(&s);
1306
1307         return (0);
1308 }
1309
1310 #ifdef CONFIG_BZIP2
1311 void bz_internal_error(int errcode)
1312 {
1313         printf ("BZIP2 internal error %d\n", errcode);
1314 }
1315 #endif /* CONFIG_BZIP2 */
1316
1317 static void
1318 do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
1319                 ulong addr, ulong *len_ptr, int verify)
1320 {
1321         DECLARE_GLOBAL_DATA_PTR;
1322         image_header_t *hdr = &header;
1323         void    (*entry_point)(bd_t *);
1324
1325         entry_point = (void (*)(bd_t *)) hdr->ih_ep;
1326
1327         printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
1328                 (ulong)entry_point);
1329
1330         SHOW_BOOT_PROGRESS (15);
1331
1332         /*
1333          * RTEMS Parameters:
1334          *   r3: ptr to board info data
1335          */
1336
1337         (*entry_point ) ( gd->bd );
1338 }
1339
1340 #if (CONFIG_COMMANDS & CFG_CMD_ELF)
1341 static void
1342 do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
1343                   ulong addr, ulong *len_ptr, int verify)
1344 {
1345         image_header_t *hdr = &header;
1346         char str[80];
1347
1348         sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
1349         setenv("loadaddr", str);
1350         do_bootvx(cmdtp, 0, 0, NULL);
1351 }
1352
1353 static void
1354 do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
1355                  ulong addr, ulong *len_ptr, int verify)
1356 {
1357         image_header_t *hdr = &header;
1358         char *local_args[2];
1359         char str[16];
1360
1361         sprintf(str, "%x", hdr->ih_ep); /* write entry-point into string */
1362         local_args[0] = argv[0];
1363         local_args[1] = str;    /* and provide it via the arguments */
1364         do_bootelf(cmdtp, 0, 2, local_args);
1365 }
1366 #endif /* CFG_CMD_ELF */
1367
1368 #ifdef CONFIG_LYNXKDI
1369 static void
1370 do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
1371                  int    argc, char *argv[],
1372                  ulong  addr,
1373                  ulong  *len_ptr,
1374                  int    verify)
1375 {
1376         lynxkdi_boot( &header );
1377 }
1378
1379 #endif /* CONFIG_LYNXKDI */