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