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