]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_bootm.c
rename CFG_ macros to CONFIG_SYS
[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
25 /*
26  * Boot support
27  */
28 #include <common.h>
29 #include <watchdog.h>
30 #include <command.h>
31 #include <image.h>
32 #include <malloc.h>
33 #include <zlib.h>
34 #include <bzlib.h>
35 #include <environment.h>
36 #include <lmb.h>
37 #include <asm/byteorder.h>
38
39 #if defined(CONFIG_CMD_USB)
40 #include <usb.h>
41 #endif
42
43 #ifdef CONFIG_SYS_HUSH_PARSER
44 #include <hush.h>
45 #endif
46
47 #if defined(CONFIG_OF_LIBFDT)
48 #include <fdt.h>
49 #include <libfdt.h>
50 #include <fdt_support.h>
51 #endif
52
53 #ifdef CONFIG_LZMA
54 #define _7ZIP_BYTE_DEFINED /* Byte already defined by zlib */
55 #include <lzma/LzmaTypes.h>
56 #include <lzma/LzmaDecode.h>
57 #include <lzma/LzmaTools.h>
58 #endif /* CONFIG_LZMA */
59
60 DECLARE_GLOBAL_DATA_PTR;
61
62 extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp);
63 #ifndef CONFIG_SYS_BOOTM_LEN
64 #define CONFIG_SYS_BOOTM_LEN    0x800000        /* use 8MByte as default max gunzip size */
65 #endif
66
67 #ifdef CONFIG_BZIP2
68 extern void bz_internal_error(int);
69 #endif
70
71 #if defined(CONFIG_CMD_IMI)
72 static int image_info (unsigned long addr);
73 #endif
74
75 #if defined(CONFIG_CMD_IMLS)
76 #include <flash.h>
77 extern flash_info_t flash_info[]; /* info for FLASH chips */
78 static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
79 #endif
80
81 #ifdef CONFIG_SILENT_CONSOLE
82 static void fixup_silent_linux (void);
83 #endif
84
85 static image_header_t *image_get_kernel (ulong img_addr, int verify);
86 #if defined(CONFIG_FIT)
87 static int fit_check_kernel (const void *fit, int os_noffset, int verify);
88 #endif
89
90 static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[],
91                 bootm_headers_t *images, ulong *os_data, ulong *os_len);
92 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
93
94 /*
95  *  Continue booting an OS image; caller already has:
96  *  - copied image header to global variable `header'
97  *  - checked header magic number, checksums (both header & image),
98  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
99  *  - loaded (first part of) image to header load address,
100  *  - disabled interrupts.
101  */
102 typedef int boot_os_fn (int flag, int argc, char *argv[],
103                         bootm_headers_t *images); /* pointers to os/initrd/fdt */
104
105 extern boot_os_fn do_bootm_linux;
106 static boot_os_fn do_bootm_netbsd;
107 #if defined(CONFIG_LYNXKDI)
108 static boot_os_fn do_bootm_lynxkdi;
109 extern void lynxkdi_boot (image_header_t *);
110 #endif
111 static boot_os_fn do_bootm_rtems;
112 #if defined(CONFIG_CMD_ELF)
113 static boot_os_fn do_bootm_vxworks;
114 static boot_os_fn do_bootm_qnxelf;
115 int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
116 int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
117 #endif
118 #if defined(CONFIG_INTEGRITY)
119 static boot_os_fn do_bootm_integrity;
120 #endif
121
122 ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */
123 static bootm_headers_t images;          /* pointers to os/initrd/fdt images */
124
125 void __board_lmb_reserve(struct lmb *lmb)
126 {
127         /* please define platform specific board_lmb_reserve() */
128 }
129 void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve")));
130
131 #if defined(__ARM__)
132   #define IH_INITRD_ARCH IH_ARCH_ARM
133 #elif defined(__avr32__)
134   #define IH_INITRD_ARCH IH_ARCH_AVR32
135 #elif defined(__bfin__)
136   #define IH_INITRD_ARCH IH_ARCH_BLACKFIN
137 #elif defined(__I386__)
138   #define IH_INITRD_ARCH IH_ARCH_I386
139 #elif defined(__M68K__)
140   #define IH_INITRD_ARCH IH_ARCH_M68K
141 #elif defined(__microblaze__)
142   #define IH_INITRD_ARCH IH_ARCH_MICROBLAZE
143 #elif defined(__mips__)
144   #define IH_INITRD_ARCH IH_ARCH_MIPS
145 #elif defined(__nios__)
146   #define IH_INITRD_ARCH IH_ARCH_NIOS
147 #elif defined(__nios2__)
148   #define IH_INITRD_ARCH IH_ARCH_NIOS2
149 #elif defined(__PPC__)
150   #define IH_INITRD_ARCH IH_ARCH_PPC
151 #elif defined(__sh__)
152   #define IH_INITRD_ARCH IH_ARCH_SH
153 #elif defined(__sparc__)
154   #define IH_INITRD_ARCH IH_ARCH_SPARC
155 #else
156 # error Unknown CPU type
157 #endif
158
159 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
160 {
161         ulong           mem_start;
162         phys_size_t     mem_size;
163         void            *os_hdr;
164         int             ret;
165
166         memset ((void *)&images, 0, sizeof (images));
167         images.verify = getenv_yesno ("verify");
168
169         lmb_init(&images.lmb);
170
171         mem_start = getenv_bootm_low();
172         mem_size = getenv_bootm_size();
173
174         lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
175
176         board_lmb_reserve(&images.lmb);
177
178         /* get kernel image header, start address and length */
179         os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,
180                         &images, &images.os.image_start, &images.os.image_len);
181         if (images.os.image_len == 0) {
182                 puts ("ERROR: can't get kernel image!\n");
183                 return 1;
184         }
185
186         /* get image parameters */
187         switch (genimg_get_format (os_hdr)) {
188         case IMAGE_FORMAT_LEGACY:
189                 images.os.type = image_get_type (os_hdr);
190                 images.os.comp = image_get_comp (os_hdr);
191                 images.os.os = image_get_os (os_hdr);
192
193                 images.os.end = image_get_image_end (os_hdr);
194                 images.os.load = image_get_load (os_hdr);
195                 break;
196 #if defined(CONFIG_FIT)
197         case IMAGE_FORMAT_FIT:
198                 if (fit_image_get_type (images.fit_hdr_os,
199                                         images.fit_noffset_os, &images.os.type)) {
200                         puts ("Can't get image type!\n");
201                         show_boot_progress (-109);
202                         return 1;
203                 }
204
205                 if (fit_image_get_comp (images.fit_hdr_os,
206                                         images.fit_noffset_os, &images.os.comp)) {
207                         puts ("Can't get image compression!\n");
208                         show_boot_progress (-110);
209                         return 1;
210                 }
211
212                 if (fit_image_get_os (images.fit_hdr_os,
213                                         images.fit_noffset_os, &images.os.os)) {
214                         puts ("Can't get image OS!\n");
215                         show_boot_progress (-111);
216                         return 1;
217                 }
218
219                 images.os.end = fit_get_end (images.fit_hdr_os);
220
221                 if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os,
222                                         &images.os.load)) {
223                         puts ("Can't get image load address!\n");
224                         show_boot_progress (-112);
225                         return 1;
226                 }
227                 break;
228 #endif
229         default:
230                 puts ("ERROR: unknown image format type!\n");
231                 return 1;
232         }
233
234         /* find kernel entry point */
235         if (images.legacy_hdr_valid) {
236                 images.ep = image_get_ep (&images.legacy_hdr_os_copy);
237 #if defined(CONFIG_FIT)
238         } else if (images.fit_uname_os) {
239                 ret = fit_image_get_entry (images.fit_hdr_os,
240                                 images.fit_noffset_os, &images.ep);
241                 if (ret) {
242                         puts ("Can't get entry point property!\n");
243                         return 1;
244                 }
245 #endif
246         } else {
247                 puts ("Could not find kernel entry point!\n");
248                 return 1;
249         }
250
251         if (images.os.os == IH_OS_LINUX) {
252                 /* find ramdisk */
253                 ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH,
254                                 &images.rd_start, &images.rd_end);
255                 if (ret) {
256                         puts ("Ramdisk image is corrupt or invalid\n");
257                         return 1;
258                 }
259
260 #if defined(CONFIG_OF_LIBFDT)
261 #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
262                 /* find flattened device tree */
263                 ret = boot_get_fdt (flag, argc, argv, &images,
264                                     &images.ft_addr, &images.ft_len);
265                 if (ret) {
266                         puts ("Could not find a valid device tree\n");
267                         return 1;
268                 }
269
270                 set_working_fdt_addr(images.ft_addr);
271 #endif
272 #endif
273         }
274
275         images.os.start = (ulong)os_hdr;
276         images.valid = 1;
277
278         return 0;
279 }
280
281 #define BOOTM_ERR_RESET         -1
282 #define BOOTM_ERR_OVERLAP       -2
283 #define BOOTM_ERR_UNIMPLEMENTED -3
284 static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
285 {
286         uint8_t comp = os.comp;
287         ulong load = os.load;
288         ulong blob_start = os.start;
289         ulong blob_end = os.end;
290         ulong image_start = os.image_start;
291         ulong image_len = os.image_len;
292         uint unc_len = CONFIG_SYS_BOOTM_LEN;
293
294         const char *type_name = genimg_get_type_name (os.type);
295
296         switch (comp) {
297         case IH_COMP_NONE:
298                 if (load == blob_start) {
299                         printf ("   XIP %s ... ", type_name);
300                 } else {
301                         printf ("   Loading %s ... ", type_name);
302
303                         memmove_wd ((void *)load,
304                                    (void *)image_start, image_len, CHUNKSZ);
305                 }
306                 *load_end = load + image_len;
307                 puts("OK\n");
308                 break;
309         case IH_COMP_GZIP:
310                 printf ("   Uncompressing %s ... ", type_name);
311                 if (gunzip ((void *)load, unc_len,
312                                         (uchar *)image_start, &image_len) != 0) {
313                         puts ("GUNZIP: uncompress or overwrite error "
314                                 "- must RESET board to recover\n");
315                         if (boot_progress)
316                                 show_boot_progress (-6);
317                         return BOOTM_ERR_RESET;
318                 }
319
320                 *load_end = load + image_len;
321                 break;
322 #ifdef CONFIG_BZIP2
323         case IH_COMP_BZIP2:
324                 printf ("   Uncompressing %s ... ", type_name);
325                 /*
326                  * If we've got less than 4 MB of malloc() space,
327                  * use slower decompression algorithm which requires
328                  * at most 2300 KB of memory.
329                  */
330                 int i = BZ2_bzBuffToBuffDecompress ((char*)load,
331                                         &unc_len, (char *)image_start, image_len,
332                                         CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
333                 if (i != BZ_OK) {
334                         printf ("BUNZIP2: uncompress or overwrite error %d "
335                                 "- must RESET board to recover\n", i);
336                         if (boot_progress)
337                                 show_boot_progress (-6);
338                         return BOOTM_ERR_RESET;
339                 }
340
341                 *load_end = load + unc_len;
342                 break;
343 #endif /* CONFIG_BZIP2 */
344 #ifdef CONFIG_LZMA
345         case IH_COMP_LZMA:
346                 printf ("   Uncompressing %s ... ", type_name);
347
348                 int ret = lzmaBuffToBuffDecompress(
349                         (unsigned char *)load, &unc_len,
350                         (unsigned char *)image_start, image_len);
351                 if (ret != LZMA_RESULT_OK) {
352                         printf ("LZMA: uncompress or overwrite error %d "
353                                 "- must RESET board to recover\n", ret);
354                         show_boot_progress (-6);
355                         return BOOTM_ERR_RESET;
356                 }
357                 *load_end = load + unc_len;
358                 break;
359 #endif /* CONFIG_LZMA */
360         default:
361                 printf ("Unimplemented compression type %d\n", comp);
362                 return BOOTM_ERR_UNIMPLEMENTED;
363         }
364         puts ("OK\n");
365         debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
366         if (boot_progress)
367                 show_boot_progress (7);
368
369         if ((load < blob_end) && (*load_end > blob_start)) {
370                 debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end);
371                 debug ("images.os.load = 0x%lx, load_end = 0x%lx\n", load, *load_end);
372
373                 return BOOTM_ERR_OVERLAP;
374         }
375
376         return 0;
377 }
378
379 /*******************************************************************/
380 /* bootm - boot application image from image in memory */
381 /*******************************************************************/
382 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
383 {
384
385         ulong           iflag;
386         ulong           load_end = 0;
387         int             ret;
388
389         if (bootm_start(cmdtp, flag, argc, argv))
390                 return 1;
391
392         /*
393          * We have reached the point of no return: we are going to
394          * overwrite all exception vector code, so we cannot easily
395          * recover from any failures any more...
396          */
397         iflag = disable_interrupts();
398
399 #if defined(CONFIG_CMD_USB)
400         /*
401          * turn off USB to prevent the host controller from writing to the
402          * SDRAM while Linux is booting. This could happen (at least for OHCI
403          * controller), because the HCCA (Host Controller Communication Area)
404          * lies within the SDRAM and the host controller writes continously to
405          * this area (as busmaster!). The HccaFrameNumber is for example
406          * updated every 1 ms within the HCCA structure in SDRAM! For more
407          * details see the OpenHCI specification.
408          */
409         usb_stop();
410 #endif
411
412 #ifdef CONFIG_AMIGAONEG3SE
413         /*
414          * We've possible left the caches enabled during
415          * bios emulation, so turn them off again
416          */
417         icache_disable();
418         dcache_disable();
419 #endif
420
421         ret = bootm_load_os(images.os, &load_end, 1);
422
423         if (ret < 0) {
424                 if (ret == BOOTM_ERR_RESET)
425                         do_reset (cmdtp, flag, argc, argv);
426                 if (ret == BOOTM_ERR_OVERLAP) {
427                         if (images.legacy_hdr_valid) {
428                                 if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
429                                         puts ("WARNING: legacy format multi component "
430                                                 "image overwritten\n");
431                         } else {
432                                 puts ("ERROR: new format image overwritten - "
433                                         "must RESET the board to recover\n");
434                                 show_boot_progress (-113);
435                                 do_reset (cmdtp, flag, argc, argv);
436                         }
437                 }
438                 if (ret == BOOTM_ERR_UNIMPLEMENTED) {
439                         if (iflag)
440                                 enable_interrupts();
441                         show_boot_progress (-7);
442                         return 1;
443                 }
444         }
445
446         lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
447
448         show_boot_progress (8);
449
450         switch (images.os.os) {
451         default:                        /* handled by (original) Linux case */
452         case IH_OS_LINUX:
453 #ifdef CONFIG_SILENT_CONSOLE
454             fixup_silent_linux();
455 #endif
456             do_bootm_linux (0, argc, argv, &images);
457             break;
458
459         case IH_OS_NETBSD:
460             do_bootm_netbsd (0, argc, argv, &images);
461             break;
462
463 #ifdef CONFIG_LYNXKDI
464         case IH_OS_LYNXOS:
465             do_bootm_lynxkdi (0, argc, argv, &images);
466             break;
467 #endif
468
469         case IH_OS_RTEMS:
470             do_bootm_rtems (0, argc, argv, &images);
471             break;
472
473 #if defined(CONFIG_CMD_ELF)
474         case IH_OS_VXWORKS:
475             do_bootm_vxworks (0, argc, argv, &images);
476             break;
477
478         case IH_OS_QNX:
479             do_bootm_qnxelf (0, argc, argv, &images);
480             break;
481 #endif
482
483 #ifdef CONFIG_INTEGRITY
484         case IH_OS_INTEGRITY:
485             do_bootm_integrity (0, argc, argv, &images);
486             break;
487 #endif
488         }
489
490         show_boot_progress (-9);
491 #ifdef DEBUG
492         puts ("\n## Control returned to monitor - resetting...\n");
493 #endif
494         do_reset (cmdtp, flag, argc, argv);
495
496         return 1;
497 }
498
499 /**
500  * image_get_kernel - verify legacy format kernel image
501  * @img_addr: in RAM address of the legacy format image to be verified
502  * @verify: data CRC verification flag
503  *
504  * image_get_kernel() verifies legacy image integrity and returns pointer to
505  * legacy image header if image verification was completed successfully.
506  *
507  * returns:
508  *     pointer to a legacy image header if valid image was found
509  *     otherwise return NULL
510  */
511 static image_header_t *image_get_kernel (ulong img_addr, int verify)
512 {
513         image_header_t *hdr = (image_header_t *)img_addr;
514
515         if (!image_check_magic(hdr)) {
516                 puts ("Bad Magic Number\n");
517                 show_boot_progress (-1);
518                 return NULL;
519         }
520         show_boot_progress (2);
521
522         if (!image_check_hcrc (hdr)) {
523                 puts ("Bad Header Checksum\n");
524                 show_boot_progress (-2);
525                 return NULL;
526         }
527
528         show_boot_progress (3);
529         image_print_contents (hdr);
530
531         if (verify) {
532                 puts ("   Verifying Checksum ... ");
533                 if (!image_check_dcrc (hdr)) {
534                         printf ("Bad Data CRC\n");
535                         show_boot_progress (-3);
536                         return NULL;
537                 }
538                 puts ("OK\n");
539         }
540         show_boot_progress (4);
541
542         if (!image_check_target_arch (hdr)) {
543                 printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr));
544                 show_boot_progress (-4);
545                 return NULL;
546         }
547         return hdr;
548 }
549
550 /**
551  * fit_check_kernel - verify FIT format kernel subimage
552  * @fit_hdr: pointer to the FIT image header
553  * os_noffset: kernel subimage node offset within FIT image
554  * @verify: data CRC verification flag
555  *
556  * fit_check_kernel() verifies integrity of the kernel subimage and from
557  * specified FIT image.
558  *
559  * returns:
560  *     1, on success
561  *     0, on failure
562  */
563 #if defined (CONFIG_FIT)
564 static int fit_check_kernel (const void *fit, int os_noffset, int verify)
565 {
566         fit_image_print (fit, os_noffset, "   ");
567
568         if (verify) {
569                 puts ("   Verifying Hash Integrity ... ");
570                 if (!fit_image_check_hashes (fit, os_noffset)) {
571                         puts ("Bad Data Hash\n");
572                         show_boot_progress (-104);
573                         return 0;
574                 }
575                 puts ("OK\n");
576         }
577         show_boot_progress (105);
578
579         if (!fit_image_check_target_arch (fit, os_noffset)) {
580                 puts ("Unsupported Architecture\n");
581                 show_boot_progress (-105);
582                 return 0;
583         }
584
585         show_boot_progress (106);
586         if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) {
587                 puts ("Not a kernel image\n");
588                 show_boot_progress (-106);
589                 return 0;
590         }
591
592         show_boot_progress (107);
593         return 1;
594 }
595 #endif /* CONFIG_FIT */
596
597 /**
598  * boot_get_kernel - find kernel image
599  * @os_data: pointer to a ulong variable, will hold os data start address
600  * @os_len: pointer to a ulong variable, will hold os data length
601  *
602  * boot_get_kernel() tries to find a kernel image, verifies its integrity
603  * and locates kernel data.
604  *
605  * returns:
606  *     pointer to image header if valid image was found, plus kernel start
607  *     address and length, otherwise NULL
608  */
609 static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
610                 bootm_headers_t *images, ulong *os_data, ulong *os_len)
611 {
612         image_header_t  *hdr;
613         ulong           img_addr;
614 #if defined(CONFIG_FIT)
615         void            *fit_hdr;
616         const char      *fit_uname_config = NULL;
617         const char      *fit_uname_kernel = NULL;
618         const void      *data;
619         size_t          len;
620         int             cfg_noffset;
621         int             os_noffset;
622 #endif
623
624         /* find out kernel image address */
625         if (argc < 2) {
626                 img_addr = load_addr;
627                 debug ("*  kernel: default image load address = 0x%08lx\n",
628                                 load_addr);
629 #if defined(CONFIG_FIT)
630         } else if (fit_parse_conf (argv[1], load_addr, &img_addr,
631                                                         &fit_uname_config)) {
632                 debug ("*  kernel: config '%s' from image at 0x%08lx\n",
633                                 fit_uname_config, img_addr);
634         } else if (fit_parse_subimage (argv[1], load_addr, &img_addr,
635                                                         &fit_uname_kernel)) {
636                 debug ("*  kernel: subimage '%s' from image at 0x%08lx\n",
637                                 fit_uname_kernel, img_addr);
638 #endif
639         } else {
640                 img_addr = simple_strtoul(argv[1], NULL, 16);
641                 debug ("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
642         }
643
644         show_boot_progress (1);
645
646         /* copy from dataflash if needed */
647         img_addr = genimg_get_image (img_addr);
648
649         /* check image type, for FIT images get FIT kernel node */
650         *os_data = *os_len = 0;
651         switch (genimg_get_format ((void *)img_addr)) {
652         case IMAGE_FORMAT_LEGACY:
653                 printf ("## Booting kernel from Legacy Image at %08lx ...\n",
654                                 img_addr);
655                 hdr = image_get_kernel (img_addr, images->verify);
656                 if (!hdr)
657                         return NULL;
658                 show_boot_progress (5);
659
660                 /* get os_data and os_len */
661                 switch (image_get_type (hdr)) {
662                 case IH_TYPE_KERNEL:
663                         *os_data = image_get_data (hdr);
664                         *os_len = image_get_data_size (hdr);
665                         break;
666                 case IH_TYPE_MULTI:
667                         image_multi_getimg (hdr, 0, os_data, os_len);
668                         break;
669                 default:
670                         printf ("Wrong Image Type for %s command\n", cmdtp->name);
671                         show_boot_progress (-5);
672                         return NULL;
673                 }
674
675                 /*
676                  * copy image header to allow for image overwrites during kernel
677                  * decompression.
678                  */
679                 memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t));
680
681                 /* save pointer to image header */
682                 images->legacy_hdr_os = hdr;
683
684                 images->legacy_hdr_valid = 1;
685                 show_boot_progress (6);
686                 break;
687 #if defined(CONFIG_FIT)
688         case IMAGE_FORMAT_FIT:
689                 fit_hdr = (void *)img_addr;
690                 printf ("## Booting kernel from FIT Image at %08lx ...\n",
691                                 img_addr);
692
693                 if (!fit_check_format (fit_hdr)) {
694                         puts ("Bad FIT kernel image format!\n");
695                         show_boot_progress (-100);
696                         return NULL;
697                 }
698                 show_boot_progress (100);
699
700                 if (!fit_uname_kernel) {
701                         /*
702                          * no kernel image node unit name, try to get config
703                          * node first. If config unit node name is NULL
704                          * fit_conf_get_node() will try to find default config node
705                          */
706                         show_boot_progress (101);
707                         cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);
708                         if (cfg_noffset < 0) {
709                                 show_boot_progress (-101);
710                                 return NULL;
711                         }
712                         /* save configuration uname provided in the first
713                          * bootm argument
714                          */
715                         images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL);
716                         printf ("   Using '%s' configuration\n", images->fit_uname_cfg);
717                         show_boot_progress (103);
718
719                         os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset);
720                         fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL);
721                 } else {
722                         /* get kernel component image node offset */
723                         show_boot_progress (102);
724                         os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel);
725                 }
726                 if (os_noffset < 0) {
727                         show_boot_progress (-103);
728                         return NULL;
729                 }
730
731                 printf ("   Trying '%s' kernel subimage\n", fit_uname_kernel);
732
733                 show_boot_progress (104);
734                 if (!fit_check_kernel (fit_hdr, os_noffset, images->verify))
735                         return NULL;
736
737                 /* get kernel image data address and length */
738                 if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) {
739                         puts ("Could not find kernel subimage data!\n");
740                         show_boot_progress (-107);
741                         return NULL;
742                 }
743                 show_boot_progress (108);
744
745                 *os_len = len;
746                 *os_data = (ulong)data;
747                 images->fit_hdr_os = fit_hdr;
748                 images->fit_uname_os = fit_uname_kernel;
749                 images->fit_noffset_os = os_noffset;
750                 break;
751 #endif
752         default:
753                 printf ("Wrong Image Format for %s command\n", cmdtp->name);
754                 show_boot_progress (-108);
755                 return NULL;
756         }
757
758         debug ("   kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
759                         *os_data, *os_len, *os_len);
760
761         return (void *)img_addr;
762 }
763
764 U_BOOT_CMD(
765         bootm,  CONFIG_SYS_MAXARGS,     1,      do_bootm,
766         "bootm   - boot application image from memory\n",
767         "[addr [arg ...]]\n    - boot application image stored in memory\n"
768         "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
769         "\t'arg' can be the address of an initrd image\n"
770 #if defined(CONFIG_OF_LIBFDT)
771         "\tWhen booting a Linux kernel which requires a flat device-tree\n"
772         "\ta third argument is required which is the address of the\n"
773         "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
774         "\tuse a '-' for the second argument. If you do not pass a third\n"
775         "\ta bd_info struct will be passed instead\n"
776 #endif
777 #if defined(CONFIG_FIT)
778         "\t\nFor the new multi component uImage format (FIT) addresses\n"
779         "\tmust be extened to include component or configuration unit name:\n"
780         "\taddr:<subimg_uname> - direct component image specification\n"
781         "\taddr#<conf_uname>   - configuration specification\n"
782         "\tUse iminfo command to get the list of existing component\n"
783         "\timages and configurations.\n"
784 #endif
785 );
786
787 /*******************************************************************/
788 /* bootd - boot default image */
789 /*******************************************************************/
790 #if defined(CONFIG_CMD_BOOTD)
791 int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
792 {
793         int rcode = 0;
794
795 #ifndef CONFIG_SYS_HUSH_PARSER
796         if (run_command (getenv ("bootcmd"), flag) < 0)
797                 rcode = 1;
798 #else
799         if (parse_string_outer (getenv ("bootcmd"),
800                         FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0)
801                 rcode = 1;
802 #endif
803         return rcode;
804 }
805
806 U_BOOT_CMD(
807         boot,   1,      1,      do_bootd,
808         "boot    - boot default, i.e., run 'bootcmd'\n",
809         NULL
810 );
811
812 /* keep old command name "bootd" for backward compatibility */
813 U_BOOT_CMD(
814         bootd, 1,       1,      do_bootd,
815         "bootd   - boot default, i.e., run 'bootcmd'\n",
816         NULL
817 );
818
819 #endif
820
821
822 /*******************************************************************/
823 /* iminfo - print header info for a requested image */
824 /*******************************************************************/
825 #if defined(CONFIG_CMD_IMI)
826 int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
827 {
828         int     arg;
829         ulong   addr;
830         int     rcode = 0;
831
832         if (argc < 2) {
833                 return image_info (load_addr);
834         }
835
836         for (arg = 1; arg < argc; ++arg) {
837                 addr = simple_strtoul (argv[arg], NULL, 16);
838                 if (image_info (addr) != 0)
839                         rcode = 1;
840         }
841         return rcode;
842 }
843
844 static int image_info (ulong addr)
845 {
846         void *hdr = (void *)addr;
847
848         printf ("\n## Checking Image at %08lx ...\n", addr);
849
850         switch (genimg_get_format (hdr)) {
851         case IMAGE_FORMAT_LEGACY:
852                 puts ("   Legacy image found\n");
853                 if (!image_check_magic (hdr)) {
854                         puts ("   Bad Magic Number\n");
855                         return 1;
856                 }
857
858                 if (!image_check_hcrc (hdr)) {
859                         puts ("   Bad Header Checksum\n");
860                         return 1;
861                 }
862
863                 image_print_contents (hdr);
864
865                 puts ("   Verifying Checksum ... ");
866                 if (!image_check_dcrc (hdr)) {
867                         puts ("   Bad Data CRC\n");
868                         return 1;
869                 }
870                 puts ("OK\n");
871                 return 0;
872 #if defined(CONFIG_FIT)
873         case IMAGE_FORMAT_FIT:
874                 puts ("   FIT image found\n");
875
876                 if (!fit_check_format (hdr)) {
877                         puts ("Bad FIT image format!\n");
878                         return 1;
879                 }
880
881                 fit_print_contents (hdr);
882
883                 if (!fit_all_image_check_hashes (hdr)) {
884                         puts ("Bad hash in FIT image!\n");
885                         return 1;
886                 }
887
888                 return 0;
889 #endif
890         default:
891                 puts ("Unknown image format!\n");
892                 break;
893         }
894
895         return 1;
896 }
897
898 U_BOOT_CMD(
899         iminfo, CONFIG_SYS_MAXARGS,     1,      do_iminfo,
900         "iminfo  - print header information for application image\n",
901         "addr [addr ...]\n"
902         "    - print header information for application image starting at\n"
903         "      address 'addr' in memory; this includes verification of the\n"
904         "      image contents (magic number, header and payload checksums)\n"
905 );
906 #endif
907
908
909 /*******************************************************************/
910 /* imls - list all images found in flash */
911 /*******************************************************************/
912 #if defined(CONFIG_CMD_IMLS)
913 int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
914 {
915         flash_info_t *info;
916         int i, j;
917         void *hdr;
918
919         for (i = 0, info = &flash_info[0];
920                 i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
921
922                 if (info->flash_id == FLASH_UNKNOWN)
923                         goto next_bank;
924                 for (j = 0; j < info->sector_count; ++j) {
925
926                         hdr = (void *)info->start[j];
927                         if (!hdr)
928                                 goto next_sector;
929
930                         switch (genimg_get_format (hdr)) {
931                         case IMAGE_FORMAT_LEGACY:
932                                 if (!image_check_hcrc (hdr))
933                                         goto next_sector;
934
935                                 printf ("Legacy Image at %08lX:\n", (ulong)hdr);
936                                 image_print_contents (hdr);
937
938                                 puts ("   Verifying Checksum ... ");
939                                 if (!image_check_dcrc (hdr)) {
940                                         puts ("Bad Data CRC\n");
941                                 } else {
942                                         puts ("OK\n");
943                                 }
944                                 break;
945 #if defined(CONFIG_FIT)
946                         case IMAGE_FORMAT_FIT:
947                                 if (!fit_check_format (hdr))
948                                         goto next_sector;
949
950                                 printf ("FIT Image at %08lX:\n", (ulong)hdr);
951                                 fit_print_contents (hdr);
952                                 break;
953 #endif
954                         default:
955                                 goto next_sector;
956                         }
957
958 next_sector:            ;
959                 }
960 next_bank:      ;
961         }
962
963         return (0);
964 }
965
966 U_BOOT_CMD(
967         imls,   1,              1,      do_imls,
968         "imls    - list all images found in flash\n",
969         "\n"
970         "    - Prints information about all images found at sector\n"
971         "      boundaries in flash.\n"
972 );
973 #endif
974
975 /*******************************************************************/
976 /* helper routines */
977 /*******************************************************************/
978 #ifdef CONFIG_SILENT_CONSOLE
979 static void fixup_silent_linux ()
980 {
981         char buf[256], *start, *end;
982         char *cmdline = getenv ("bootargs");
983
984         /* Only fix cmdline when requested */
985         if (!(gd->flags & GD_FLG_SILENT))
986                 return;
987
988         debug ("before silent fix-up: %s\n", cmdline);
989         if (cmdline) {
990                 if ((start = strstr (cmdline, "console=")) != NULL) {
991                         end = strchr (start, ' ');
992                         strncpy (buf, cmdline, (start - cmdline + 8));
993                         if (end)
994                                 strcpy (buf + (start - cmdline + 8), end);
995                         else
996                                 buf[start - cmdline + 8] = '\0';
997                 } else {
998                         strcpy (buf, cmdline);
999                         strcat (buf, " console=");
1000                 }
1001         } else {
1002                 strcpy (buf, "console=");
1003         }
1004
1005         setenv ("bootargs", buf);
1006         debug ("after silent fix-up: %s\n", buf);
1007 }
1008 #endif /* CONFIG_SILENT_CONSOLE */
1009
1010
1011 /*******************************************************************/
1012 /* OS booting routines */
1013 /*******************************************************************/
1014
1015 static int do_bootm_netbsd (int flag, int argc, char *argv[],
1016                             bootm_headers_t *images)
1017 {
1018         void (*loader)(bd_t *, image_header_t *, char *, char *);
1019         image_header_t *os_hdr, *hdr;
1020         ulong kernel_data, kernel_len;
1021         char *consdev;
1022         char *cmdline;
1023
1024 #if defined(CONFIG_FIT)
1025         if (!images->legacy_hdr_valid) {
1026                 fit_unsupported_reset ("NetBSD");
1027                 return 1;
1028         }
1029 #endif
1030         hdr = images->legacy_hdr_os;
1031
1032         /*
1033          * Booting a (NetBSD) kernel image
1034          *
1035          * This process is pretty similar to a standalone application:
1036          * The (first part of an multi-) image must be a stage-2 loader,
1037          * which in turn is responsible for loading & invoking the actual
1038          * kernel.  The only differences are the parameters being passed:
1039          * besides the board info strucure, the loader expects a command
1040          * line, the name of the console device, and (optionally) the
1041          * address of the original image header.
1042          */
1043         os_hdr = NULL;
1044         if (image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
1045                 image_multi_getimg (hdr, 1, &kernel_data, &kernel_len);
1046                 if (kernel_len)
1047                         os_hdr = hdr;
1048         }
1049
1050         consdev = "";
1051 #if   defined (CONFIG_8xx_CONS_SMC1)
1052         consdev = "smc1";
1053 #elif defined (CONFIG_8xx_CONS_SMC2)
1054         consdev = "smc2";
1055 #elif defined (CONFIG_8xx_CONS_SCC2)
1056         consdev = "scc2";
1057 #elif defined (CONFIG_8xx_CONS_SCC3)
1058         consdev = "scc3";
1059 #endif
1060
1061         if (argc > 2) {
1062                 ulong len;
1063                 int   i;
1064
1065                 for (i = 2, len = 0; i < argc; i += 1)
1066                         len += strlen (argv[i]) + 1;
1067                 cmdline = malloc (len);
1068
1069                 for (i = 2, len = 0; i < argc; i += 1) {
1070                         if (i > 2)
1071                                 cmdline[len++] = ' ';
1072                         strcpy (&cmdline[len], argv[i]);
1073                         len += strlen (argv[i]);
1074                 }
1075         } else if ((cmdline = getenv ("bootargs")) == NULL) {
1076                 cmdline = "";
1077         }
1078
1079         loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep;
1080
1081         printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
1082                 (ulong)loader);
1083
1084         show_boot_progress (15);
1085
1086         /*
1087          * NetBSD Stage-2 Loader Parameters:
1088          *   r3: ptr to board info data
1089          *   r4: image address
1090          *   r5: console device
1091          *   r6: boot args string
1092          */
1093         (*loader) (gd->bd, os_hdr, consdev, cmdline);
1094
1095         return 1;
1096 }
1097
1098 #ifdef CONFIG_LYNXKDI
1099 static int do_bootm_lynxkdi (int flag, int argc, char *argv[],
1100                              bootm_headers_t *images)
1101 {
1102         image_header_t *hdr = &images->legacy_hdr_os_copy;
1103
1104 #if defined(CONFIG_FIT)
1105         if (!images->legacy_hdr_valid) {
1106                 fit_unsupported_reset ("Lynx");
1107                 return 1;
1108         }
1109 #endif
1110
1111         lynxkdi_boot ((image_header_t *)hdr);
1112
1113         return 1;
1114 }
1115 #endif /* CONFIG_LYNXKDI */
1116
1117 static int do_bootm_rtems (int flag, int argc, char *argv[],
1118                            bootm_headers_t *images)
1119 {
1120         void (*entry_point)(bd_t *);
1121
1122 #if defined(CONFIG_FIT)
1123         if (!images->legacy_hdr_valid) {
1124                 fit_unsupported_reset ("RTEMS");
1125                 return 1;
1126         }
1127 #endif
1128
1129         entry_point = (void (*)(bd_t *))images->ep;
1130
1131         printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
1132                 (ulong)entry_point);
1133
1134         show_boot_progress (15);
1135
1136         /*
1137          * RTEMS Parameters:
1138          *   r3: ptr to board info data
1139          */
1140         (*entry_point)(gd->bd);
1141
1142         return 1;
1143 }
1144
1145 #if defined(CONFIG_CMD_ELF)
1146 static int do_bootm_vxworks (int flag, int argc, char *argv[],
1147                              bootm_headers_t *images)
1148 {
1149         char str[80];
1150
1151 #if defined(CONFIG_FIT)
1152         if (!images->legacy_hdr_valid) {
1153                 fit_unsupported_reset ("VxWorks");
1154                 return 1;
1155         }
1156 #endif
1157
1158         sprintf(str, "%lx", images->ep); /* write entry-point into string */
1159         setenv("loadaddr", str);
1160         do_bootvx(NULL, 0, 0, NULL);
1161
1162         return 1;
1163 }
1164
1165 static int do_bootm_qnxelf(int flag, int argc, char *argv[],
1166                             bootm_headers_t *images)
1167 {
1168         char *local_args[2];
1169         char str[16];
1170
1171 #if defined(CONFIG_FIT)
1172         if (!images->legacy_hdr_valid) {
1173                 fit_unsupported_reset ("QNX");
1174                 return 1;
1175         }
1176 #endif
1177
1178         sprintf(str, "%lx", images->ep); /* write entry-point into string */
1179         local_args[0] = argv[0];
1180         local_args[1] = str;    /* and provide it via the arguments */
1181         do_bootelf(NULL, 0, 2, local_args);
1182
1183         return 1;
1184 }
1185 #endif
1186
1187 #ifdef CONFIG_INTEGRITY
1188 static int do_bootm_integrity (int flag, int argc, char *argv[],
1189                            bootm_headers_t *images)
1190 {
1191         void (*entry_point)(void);
1192
1193 #if defined(CONFIG_FIT)
1194         if (!images->legacy_hdr_valid) {
1195                 fit_unsupported_reset ("INTEGRITY");
1196                 return 1;
1197         }
1198 #endif
1199
1200         entry_point = (void (*)(void))images->ep;
1201
1202         printf ("## Transferring control to INTEGRITY (at address %08lx) ...\n",
1203                 (ulong)entry_point);
1204
1205         show_boot_progress (15);
1206
1207         /*
1208          * INTEGRITY Parameters:
1209          *   None
1210          */
1211         (*entry_point)();
1212
1213         return 1;
1214 }
1215 #endif