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