]> git.sur5r.net Git - u-boot/blob - common/cmd_bootm.c
[new uImage] Factor out common routines for getting os/arch/type/comp names
[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         const char      *type_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                 os_data = image_get_data (hdr);
193                 os_len = image_get_data_size (hdr);
194                 break;
195         case IH_TYPE_MULTI:
196                 image_multi_getimg (hdr, 0, &os_data, &os_len);
197                 break;
198         default:
199                 printf ("Wrong Image Type for %s command\n", cmdtp->name);
200                 show_boot_progress (-5);
201                 return 1;
202         }
203         show_boot_progress (6);
204
205         /*
206          * We have reached the point of no return: we are going to
207          * overwrite all exception vector code, so we cannot easily
208          * recover from any failures any more...
209          */
210         iflag = disable_interrupts();
211
212 #ifdef CONFIG_AMIGAONEG3SE
213         /*
214          * We've possible left the caches enabled during
215          * bios emulation, so turn them off again
216          */
217         icache_disable();
218         invalidate_l1_instruction_cache();
219         flush_data_cache();
220         dcache_disable();
221 #endif
222
223         type_name = image_get_type_name (image_get_type (hdr));
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 ... ", type_name);
234                 } else {
235                         printf ("   Loading %s ... ", type_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 ... ", type_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 ... ", type_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         const char *os, *arch, *type, *comp;
548
549         os = image_get_os_name (image_get_os (hdr));
550         arch = image_get_arch_name (image_get_arch (hdr));
551         type = image_get_type_name (image_get_type (hdr));
552         comp = image_get_comp_name (image_get_comp (hdr));
553
554         printf ("%s %s %s (%s)", arch, os, type, comp);
555 }
556
557 #ifdef CONFIG_SILENT_CONSOLE
558 static void fixup_silent_linux ()
559 {
560         char buf[256], *start, *end;
561         char *cmdline = getenv ("bootargs");
562
563         /* Only fix cmdline when requested */
564         if (!(gd->flags & GD_FLG_SILENT))
565                 return;
566
567         debug ("before silent fix-up: %s\n", cmdline);
568         if (cmdline) {
569                 if ((start = strstr (cmdline, "console=")) != NULL) {
570                         end = strchr (start, ' ');
571                         strncpy (buf, cmdline, (start - cmdline + 8));
572                         if (end)
573                                 strcpy (buf + (start - cmdline + 8), end);
574                         else
575                                 buf[start - cmdline + 8] = '\0';
576                 } else {
577                         strcpy (buf, cmdline);
578                         strcat (buf, " console=");
579                 }
580         } else {
581                 strcpy (buf, "console=");
582         }
583
584         setenv ("bootargs", buf);
585         debug ("after silent fix-up: %s\n", buf);
586 }
587 #endif /* CONFIG_SILENT_CONSOLE */
588
589
590 /*******************************************************************/
591 /* OS booting routines */
592 /*******************************************************************/
593
594 static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
595                             int argc, char *argv[],
596                             image_header_t *hdr, int verify)
597 {
598         void (*loader)(bd_t *, image_header_t *, char *, char *);
599         image_header_t *img_addr;
600         ulong kernel_data, kernel_len;
601         char *consdev;
602         char *cmdline;
603
604         /*
605          * Booting a (NetBSD) kernel image
606          *
607          * This process is pretty similar to a standalone application:
608          * The (first part of an multi-) image must be a stage-2 loader,
609          * which in turn is responsible for loading & invoking the actual
610          * kernel.  The only differences are the parameters being passed:
611          * besides the board info strucure, the loader expects a command
612          * line, the name of the console device, and (optionally) the
613          * address of the original image header.
614          */
615
616         img_addr = 0;
617         if (image_check_type (hdr, IH_TYPE_MULTI)) {
618                 image_multi_getimg (hdr, 1, &kernel_data, &kernel_len);
619                 if (kernel_len)
620                         img_addr = hdr;
621         }
622
623         consdev = "";
624 #if   defined (CONFIG_8xx_CONS_SMC1)
625         consdev = "smc1";
626 #elif defined (CONFIG_8xx_CONS_SMC2)
627         consdev = "smc2";
628 #elif defined (CONFIG_8xx_CONS_SCC2)
629         consdev = "scc2";
630 #elif defined (CONFIG_8xx_CONS_SCC3)
631         consdev = "scc3";
632 #endif
633
634         if (argc > 2) {
635                 ulong len;
636                 int   i;
637
638                 for (i = 2, len = 0; i < argc; i += 1)
639                         len += strlen (argv[i]) + 1;
640                 cmdline = malloc (len);
641
642                 for (i = 2, len = 0; i < argc; i += 1) {
643                         if (i > 2)
644                                 cmdline[len++] = ' ';
645                         strcpy (&cmdline[len], argv[i]);
646                         len += strlen (argv[i]);
647                 }
648         } else if ((cmdline = getenv ("bootargs")) == NULL) {
649                 cmdline = "";
650         }
651
652         loader = (void (*)(bd_t *, image_header_t *, char *, char *))image_get_ep (hdr);
653
654         printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n",
655                 (ulong)loader);
656
657         show_boot_progress (15);
658
659         /*
660          * NetBSD Stage-2 Loader Parameters:
661          *   r3: ptr to board info data
662          *   r4: image address
663          *   r5: console device
664          *   r6: boot args string
665          */
666         (*loader) (gd->bd, img_addr, consdev, cmdline);
667 }
668
669 #ifdef CONFIG_LYNXKDI
670 static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
671                              int argc, char *argv[],
672                              image_header_t *hdr, int verify)
673 {
674         lynxkdi_boot (hdr);
675 }
676 #endif /* CONFIG_LYNXKDI */
677
678 static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag,
679                            int argc, char *argv[],
680                            image_header_t *hdr, int verify)
681 {
682         void (*entry_point)(bd_t *);
683
684         entry_point = (void (*)(bd_t *))image_get_ep (hdr);
685
686         printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
687                 (ulong)entry_point);
688
689         show_boot_progress (15);
690
691         /*
692          * RTEMS Parameters:
693          *   r3: ptr to board info data
694          */
695         (*entry_point)(gd->bd);
696 }
697
698 #if defined(CONFIG_CMD_ELF)
699 static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag,
700                              int argc, char *argv[],
701                              image_header_t *hdr, int verify)
702 {
703         char str[80];
704
705         sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
706         setenv("loadaddr", str);
707         do_bootvx(cmdtp, 0, 0, NULL);
708 }
709
710 static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag,
711                             int argc, char *argv[],
712                             image_header_t *hdr, int verify)
713 {
714         char *local_args[2];
715         char str[16];
716
717         sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
718         local_args[0] = argv[0];
719         local_args[1] = str;    /* and provide it via the arguments */
720         do_bootelf(cmdtp, 0, 2, local_args);
721 }
722 #endif
723
724 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
725 static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
726                            int argc, char *argv[],
727                            image_header_t *hdr, int verify)
728 {
729         ulong top;
730         char *s, *cmdline;
731         char **fwenv, **ss;
732         int i, j, nxt, len, envno, envsz;
733         bd_t *kbd;
734         void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top);
735
736         /*
737          * Booting an ARTOS kernel image + application
738          */
739
740         /* this used to be the top of memory, but was wrong... */
741 #ifdef CONFIG_PPC
742         /* get stack pointer */
743         asm volatile ("mr %0,1" : "=r"(top) );
744 #endif
745         debug ("## Current stack ends at 0x%08lX ", top);
746
747         top -= 2048;            /* just to be sure */
748         if (top > CFG_BOOTMAPSZ)
749                 top = CFG_BOOTMAPSZ;
750         top &= ~0xF;
751
752         debug ("=> set upper limit to 0x%08lX\n", top);
753
754         /* first check the artos specific boot args, then the linux args*/
755         if ((s = getenv( "abootargs")) == NULL && (s = getenv ("bootargs")) == NULL)
756                 s = "";
757
758         /* get length of cmdline, and place it */
759         len = strlen (s);
760         top = (top - (len + 1)) & ~0xF;
761         cmdline = (char *)top;
762         debug ("## cmdline at 0x%08lX ", top);
763         strcpy (cmdline, s);
764
765         /* copy bdinfo */
766         top = (top - sizeof (bd_t)) & ~0xF;
767         debug ("## bd at 0x%08lX ", top);
768         kbd = (bd_t *)top;
769         memcpy (kbd, gd->bd, sizeof (bd_t));
770
771         /* first find number of env entries, and their size */
772         envno = 0;
773         envsz = 0;
774         for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) {
775                 for (nxt = i; env_get_char (nxt) != '\0'; ++nxt)
776                         ;
777                 envno++;
778                 envsz += (nxt - i) + 1; /* plus trailing zero */
779         }
780         envno++;        /* plus the terminating zero */
781         debug ("## %u envvars total size %u ", envno, envsz);
782
783         top = (top - sizeof (char **) * envno) & ~0xF;
784         fwenv = (char **)top;
785         debug ("## fwenv at 0x%08lX ", top);
786
787         top = (top - envsz) & ~0xF;
788         s = (char *)top;
789         ss = fwenv;
790
791         /* now copy them */
792         for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) {
793                 for (nxt = i; env_get_char (nxt) != '\0'; ++nxt)
794                         ;
795                 *ss++ = s;
796                 for (j = i; j < nxt; ++j)
797                         *s++ = env_get_char (j);
798                 *s++ = '\0';
799         }
800         *ss++ = NULL;   /* terminate */
801
802         entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr);
803         (*entry) (kbd, cmdline, fwenv, top);
804 }
805 #endif