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