]> git.ipfire.org Git - people/ms/u-boot.git/blame - common/cmd_bootm.c
Merge branch 'u-boot-microblaze/zynq' into 'u-boot-arm/master'
[people/ms/u-boot.git] / common / cmd_bootm.c
CommitLineData
47d1a6e1 1/*
ca95c9df 2 * (C) Copyright 2000-2009
47d1a6e1
WD
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
1a459660 5 * SPDX-License-Identifier: GPL-2.0+
47d1a6e1
WD
6 */
7
b97a2a0a 8
47d1a6e1
WD
9/*
10 * Boot support
11 */
12#include <common.h>
13#include <watchdog.h>
14#include <command.h>
47d1a6e1
WD
15#include <image.h>
16#include <malloc.h>
a31e091a 17#include <u-boot/zlib.h>
c29fdfc1 18#include <bzlib.h>
7f70e853 19#include <environment.h>
4ed6552f 20#include <lmb.h>
49c3a861 21#include <linux/ctype.h>
47d1a6e1 22#include <asm/byteorder.h>
35e7b0f1 23#include <asm/io.h>
5bf2766b 24#include <linux/compiler.h>
8bde7f77 25
871a57bb
MY
26#if defined(CONFIG_BOOTM_VXWORKS) && \
27 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
28#include <vxworks.h>
29#endif
30
ebb86c4e 31#if defined(CONFIG_CMD_USB)
3d71c81a
MK
32#include <usb.h>
33#endif
34
6d0f6bcf 35#ifdef CONFIG_SYS_HUSH_PARSER
47d1a6e1
WD
36#include <hush.h>
37#endif
38
54f9c866 39#if defined(CONFIG_OF_LIBFDT)
54f9c866
KG
40#include <libfdt.h>
41#include <fdt_support.h>
42#endif
43
fc9c1727 44#ifdef CONFIG_LZMA
fc9c1727 45#include <lzma/LzmaTypes.h>
caf72ff3 46#include <lzma/LzmaDec.h>
fc9c1727
LCM
47#include <lzma/LzmaTools.h>
48#endif /* CONFIG_LZMA */
49
20dde48b
PK
50#ifdef CONFIG_LZO
51#include <linux/lzo.h>
52#endif /* CONFIG_LZO */
53
1ee1180b 54DECLARE_GLOBAL_DATA_PTR;
228f29ac 55
6d0f6bcf
JCPV
56#ifndef CONFIG_SYS_BOOTM_LEN
57#define CONFIG_SYS_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */
2abbe075
WD
58#endif
59
321359f2
MB
60#ifdef CONFIG_BZIP2
61extern void bz_internal_error(int);
47d1a6e1
WD
62#endif
63
baa26db4 64#if defined(CONFIG_CMD_IMI)
712fbcf3 65static int image_info(unsigned long addr);
47d1a6e1 66#endif
27b207fd 67
baa26db4 68#if defined(CONFIG_CMD_IMLS)
27b207fd 69#include <flash.h>
ca5def3f 70#include <mtd/cfi_flash.h>
e6f2e902 71extern flash_info_t flash_info[]; /* info for FLASH chips */
8fdf1e0f
VK
72#endif
73
74#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
712fbcf3 75static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
27b207fd
WD
76#endif
77
8fdf1e0f
VK
78#include <linux/err.h>
79#include <nand.h>
80
be2e5a09 81#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
712fbcf3 82static void fixup_silent_linux(void);
1ee1180b 83#endif
47d1a6e1 84
c5cbe1e2
SG
85static int do_bootm_standalone(int flag, int argc, char * const argv[],
86 bootm_headers_t *images);
87
35e7b0f1 88static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
712fbcf3
SW
89 char * const argv[], bootm_headers_t *images,
90 ulong *os_data, ulong *os_len);
47d1a6e1
WD
91
92/*
93 * Continue booting an OS image; caller already has:
94 * - copied image header to global variable `header'
95 * - checked header magic number, checksums (both header & image),
96 * - verified image architecture (PPC) and type (KERNEL or MULTI),
97 * - loaded (first part of) image to header load address,
98 * - disabled interrupts.
983c72f4 99 *
35fc84fa 100 * @flag: Flags indicating what to do (BOOTM_STATE_...)
983c72f4
SG
101 * @argc: Number of arguments. Note that the arguments are shifted down
102 * so that 0 is the first argument not processed by U-Boot, and
103 * argc is adjusted accordingly. This avoids confusion as to how
104 * many arguments are available for the OS.
105 * @images: Pointers to os/initrd/fdt
106 * @return 1 on error. On success the OS boots so this function does
107 * not return.
47d1a6e1 108 */
712fbcf3 109typedef int boot_os_fn(int flag, int argc, char * const argv[],
983c72f4 110 bootm_headers_t *images);
1ee1180b 111
b1d0db18 112#ifdef CONFIG_BOOTM_LINUX
1ee1180b 113extern boot_os_fn do_bootm_linux;
b1d0db18
KG
114#endif
115#ifdef CONFIG_BOOTM_NETBSD
1ee1180b 116static boot_os_fn do_bootm_netbsd;
b1d0db18 117#endif
f13e7b2e 118#if defined(CONFIG_LYNXKDI)
1ee1180b 119static boot_os_fn do_bootm_lynxkdi;
712fbcf3 120extern void lynxkdi_boot(image_header_t *);
47d1a6e1 121#endif
b1d0db18 122#ifdef CONFIG_BOOTM_RTEMS
1ee1180b 123static boot_os_fn do_bootm_rtems;
b1d0db18 124#endif
3df61957
TL
125#if defined(CONFIG_BOOTM_OSE)
126static boot_os_fn do_bootm_ose;
127#endif
04d41409
SS
128#if defined(CONFIG_BOOTM_PLAN9)
129static boot_os_fn do_bootm_plan9;
130#endif
871a57bb
MY
131#if defined(CONFIG_BOOTM_VXWORKS) && \
132 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
1ee1180b 133static boot_os_fn do_bootm_vxworks;
17ab52fe
MY
134#endif
135#if defined(CONFIG_CMD_ELF)
1ee1180b 136static boot_os_fn do_bootm_qnxelf;
712fbcf3
SW
137int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
138int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
90253178 139#endif
f5ed9e39
PT
140#if defined(CONFIG_INTEGRITY)
141static boot_os_fn do_bootm_integrity;
142#endif
47d1a6e1 143
0008555f 144static boot_os_fn *boot_os[] = {
c5cbe1e2 145 [IH_OS_U_BOOT] = do_bootm_standalone,
b1d0db18 146#ifdef CONFIG_BOOTM_LINUX
be083159 147 [IH_OS_LINUX] = do_bootm_linux,
b1d0db18
KG
148#endif
149#ifdef CONFIG_BOOTM_NETBSD
be083159 150 [IH_OS_NETBSD] = do_bootm_netbsd,
b1d0db18 151#endif
be083159
KG
152#ifdef CONFIG_LYNXKDI
153 [IH_OS_LYNXOS] = do_bootm_lynxkdi,
154#endif
b1d0db18 155#ifdef CONFIG_BOOTM_RTEMS
be083159 156 [IH_OS_RTEMS] = do_bootm_rtems,
b1d0db18 157#endif
3df61957
TL
158#if defined(CONFIG_BOOTM_OSE)
159 [IH_OS_OSE] = do_bootm_ose,
160#endif
04d41409
SS
161#if defined(CONFIG_BOOTM_PLAN9)
162 [IH_OS_PLAN9] = do_bootm_plan9,
163#endif
871a57bb
MY
164#if defined(CONFIG_BOOTM_VXWORKS) && \
165 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
be083159 166 [IH_OS_VXWORKS] = do_bootm_vxworks,
17ab52fe
MY
167#endif
168#if defined(CONFIG_CMD_ELF)
be083159
KG
169 [IH_OS_QNX] = do_bootm_qnxelf,
170#endif
171#ifdef CONFIG_INTEGRITY
172 [IH_OS_INTEGRITY] = do_bootm_integrity,
173#endif
174};
175
dee17768 176bootm_headers_t images; /* pointers to os/initrd/fdt images */
15940c9a 177
3dfad40a 178/* Allow for arch specific config before we boot */
088f1b19 179static void __arch_preboot_os(void)
3dfad40a
KG
180{
181 /* please define platform specific arch_preboot_os() */
182}
183void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
184
476af299 185#define IH_INITRD_ARCH IH_ARCH_DEFAULT
47d1a6e1 186
a16028da 187#ifdef CONFIG_LMB
44f074c7
MV
188static void boot_start_lmb(bootm_headers_t *images)
189{
391fd93a
BB
190 ulong mem_start;
191 phys_size_t mem_size;
47d1a6e1 192
44f074c7 193 lmb_init(&images->lmb);
47d1a6e1 194
d3f2fa0d
KG
195 mem_start = getenv_bootm_low();
196 mem_size = getenv_bootm_size();
47d1a6e1 197
44f074c7 198 lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
47d1a6e1 199
44f074c7
MV
200 arch_lmb_reserve(&images->lmb);
201 board_lmb_reserve(&images->lmb);
202}
a16028da 203#else
35cf5fe5 204#define lmb_reserve(lmb, base, size)
44f074c7 205static inline void boot_start_lmb(bootm_headers_t *images) { }
a16028da 206#endif
a16028da 207
54841ab5 208static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
a16028da 209{
712fbcf3
SW
210 memset((void *)&images, 0, sizeof(images));
211 images.verify = getenv_yesno("verify");
a16028da 212
44f074c7 213 boot_start_lmb(&images);
47d1a6e1 214
573f14fe 215 bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
35fc84fa
SG
216 images.state = BOOTM_STATE_START;
217
218 return 0;
219}
220
221static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
222 char * const argv[])
223{
224 const void *os_hdr;
9ace3fc8 225 bool ep_found = false;
573f14fe 226
5cf746c3 227 /* get kernel image header, start address and length */
712fbcf3 228 os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
396f635b
KG
229 &images, &images.os.image_start, &images.os.image_len);
230 if (images.os.image_len == 0) {
712fbcf3 231 puts("ERROR: can't get kernel image!\n");
47d1a6e1 232 return 1;
bccae903 233 }
bccae903 234
d5934ad7 235 /* get image parameters */
712fbcf3 236 switch (genimg_get_format(os_hdr)) {
d5934ad7 237 case IMAGE_FORMAT_LEGACY:
712fbcf3
SW
238 images.os.type = image_get_type(os_hdr);
239 images.os.comp = image_get_comp(os_hdr);
240 images.os.os = image_get_os(os_hdr);
bccae903 241
712fbcf3
SW
242 images.os.end = image_get_image_end(os_hdr);
243 images.os.load = image_get_load(os_hdr);
d5934ad7
MB
244 break;
245#if defined(CONFIG_FIT)
246 case IMAGE_FORMAT_FIT:
712fbcf3 247 if (fit_image_get_type(images.fit_hdr_os,
396f635b 248 images.fit_noffset_os, &images.os.type)) {
712fbcf3 249 puts("Can't get image type!\n");
770605e4 250 bootstage_error(BOOTSTAGE_ID_FIT_TYPE);
6986a385
MB
251 return 1;
252 }
47d1a6e1 253
712fbcf3 254 if (fit_image_get_comp(images.fit_hdr_os,
396f635b 255 images.fit_noffset_os, &images.os.comp)) {
712fbcf3 256 puts("Can't get image compression!\n");
770605e4 257 bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION);
6986a385
MB
258 return 1;
259 }
47d1a6e1 260
712fbcf3 261 if (fit_image_get_os(images.fit_hdr_os,
396f635b 262 images.fit_noffset_os, &images.os.os)) {
712fbcf3 263 puts("Can't get image OS!\n");
770605e4 264 bootstage_error(BOOTSTAGE_ID_FIT_OS);
47d1a6e1
WD
265 return 1;
266 }
47d1a6e1 267
712fbcf3 268 images.os.end = fit_get_end(images.fit_hdr_os);
6986a385 269
712fbcf3 270 if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
396f635b 271 &images.os.load)) {
712fbcf3 272 puts("Can't get image load address!\n");
770605e4 273 bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR);
6986a385 274 return 1;
b13fb01a
WD
275 }
276 break;
9ace3fc8
SS
277#endif
278#ifdef CONFIG_ANDROID_BOOT_IMAGE
279 case IMAGE_FORMAT_ANDROID:
280 images.os.type = IH_TYPE_KERNEL;
281 images.os.comp = IH_COMP_NONE;
282 images.os.os = IH_OS_LINUX;
283 images.ep = images.os.load;
284 ep_found = true;
285
286 images.os.end = android_image_get_end(os_hdr);
287 images.os.load = android_image_get_kload(os_hdr);
288 break;
d5934ad7
MB
289#endif
290 default:
712fbcf3 291 puts("ERROR: unknown image format type!\n");
47d1a6e1
WD
292 return 1;
293 }
d5934ad7 294
c160a954
KG
295 /* find kernel entry point */
296 if (images.legacy_hdr_valid) {
712fbcf3 297 images.ep = image_get_ep(&images.legacy_hdr_os_copy);
c160a954
KG
298#if defined(CONFIG_FIT)
299 } else if (images.fit_uname_os) {
35fc84fa
SG
300 int ret;
301
712fbcf3 302 ret = fit_image_get_entry(images.fit_hdr_os,
c19d13b0 303 images.fit_noffset_os, &images.ep);
c160a954 304 if (ret) {
712fbcf3 305 puts("Can't get entry point property!\n");
c160a954
KG
306 return 1;
307 }
308#endif
9ace3fc8 309 } else if (!ep_found) {
712fbcf3 310 puts("Could not find kernel entry point!\n");
c160a954
KG
311 return 1;
312 }
313
b9b50e89
SW
314 if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
315 images.os.load = images.os.image_start;
316 images.ep += images.os.load;
317 }
318
35fc84fa
SG
319 images.os.start = (ulong)os_hdr;
320
321 return 0;
322}
323
225fd8c5
TR
324static int bootm_find_ramdisk(int flag, int argc, char * const argv[])
325{
326 int ret;
327
328 /* find ramdisk */
329 ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
330 &images.rd_start, &images.rd_end);
331 if (ret) {
332 puts("Ramdisk image is corrupt or invalid\n");
333 return 1;
334 }
335
336 return 0;
337}
338
339#if defined(CONFIG_OF_LIBFDT)
340static int bootm_find_fdt(int flag, int argc, char * const argv[])
35fc84fa
SG
341{
342 int ret;
343
225fd8c5
TR
344 /* find flattened device tree */
345 ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
346 &images.ft_addr, &images.ft_len);
347 if (ret) {
348 puts("Could not find a valid device tree\n");
349 return 1;
350 }
351
352 set_working_fdt_addr(images.ft_addr);
353
354 return 0;
355}
356#endif
357
358static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,
359 char * const argv[])
360{
24de2f4b 361 if (((images.os.type == IH_TYPE_KERNEL) ||
b9b50e89 362 (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
24de2f4b 363 (images.os.type == IH_TYPE_MULTI)) &&
871a57bb
MY
364 (images.os.os == IH_OS_LINUX ||
365 images.os.os == IH_OS_VXWORKS)) {
225fd8c5 366 if (bootm_find_ramdisk(flag, argc, argv))
c4f9419c 367 return 1;
06a09918
KG
368
369#if defined(CONFIG_OF_LIBFDT)
225fd8c5 370 if (bootm_find_fdt(flag, argc, argv))
06a09918 371 return 1;
06a09918 372#endif
c4f9419c
KG
373 }
374
396f635b
KG
375 return 0;
376}
3d71c81a 377
396f635b
KG
378#define BOOTM_ERR_RESET -1
379#define BOOTM_ERR_OVERLAP -2
380#define BOOTM_ERR_UNIMPLEMENTED -3
d366438d
TR
381static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
382 int boot_progress)
396f635b 383{
d366438d 384 image_info_t os = images->os;
396f635b
KG
385 uint8_t comp = os.comp;
386 ulong load = os.load;
387 ulong blob_start = os.start;
388 ulong blob_end = os.end;
389 ulong image_start = os.image_start;
390 ulong image_len = os.image_len;
5bf2766b 391 __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN;
d510859b 392 int no_overlap = 0;
aed161e5 393 void *load_buf, *image_buf;
60fdc5f2
MW
394#if defined(CONFIG_LZMA) || defined(CONFIG_LZO)
395 int ret;
396#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */
3d71c81a 397
712fbcf3 398 const char *type_name = genimg_get_type_name(os.type);
c7de829c 399
315c0ace 400 load_buf = map_sysmem(load, unc_len);
aed161e5 401 image_buf = map_sysmem(image_start, image_len);
d5934ad7 402 switch (comp) {
47d1a6e1 403 case IH_COMP_NONE:
717ccc1d 404 if (load == image_start) {
712fbcf3 405 printf(" XIP %s ... ", type_name);
d510859b 406 no_overlap = 1;
47d1a6e1 407 } else {
712fbcf3 408 printf(" Loading %s ... ", type_name);
aed161e5 409 memmove_wd(load_buf, image_buf, image_len, CHUNKSZ);
47d1a6e1 410 }
396f635b 411 *load_end = load + image_len;
47d1a6e1 412 break;
44431cab 413#ifdef CONFIG_GZIP
47d1a6e1 414 case IH_COMP_GZIP:
712fbcf3 415 printf(" Uncompressing %s ... ", type_name);
aed161e5 416 if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) {
712fbcf3
SW
417 puts("GUNZIP: uncompress, out-of-mem or overwrite "
418 "error - must RESET board to recover\n");
396f635b 419 if (boot_progress)
770605e4 420 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
396f635b 421 return BOOTM_ERR_RESET;
47d1a6e1 422 }
7582438c 423
396f635b 424 *load_end = load + image_len;
47d1a6e1 425 break;
44431cab 426#endif /* CONFIG_GZIP */
c29fdfc1
WD
427#ifdef CONFIG_BZIP2
428 case IH_COMP_BZIP2:
712fbcf3 429 printf(" Uncompressing %s ... ", type_name);
5653fc33
WD
430 /*
431 * If we've got less than 4 MB of malloc() space,
432 * use slower decompression algorithm which requires
433 * at most 2300 KB of memory.
434 */
aed161e5
SG
435 int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len,
436 image_buf, image_len,
437 CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
c29fdfc1 438 if (i != BZ_OK) {
712fbcf3 439 printf("BUNZIP2: uncompress or overwrite error %d "
2682ce8a 440 "- must RESET board to recover\n", i);
396f635b 441 if (boot_progress)
770605e4 442 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
396f635b 443 return BOOTM_ERR_RESET;
c29fdfc1 444 }
7582438c 445
396f635b 446 *load_end = load + unc_len;
c29fdfc1
WD
447 break;
448#endif /* CONFIG_BZIP2 */
fc9c1727 449#ifdef CONFIG_LZMA
78e1e846
MF
450 case IH_COMP_LZMA: {
451 SizeT lzma_len = unc_len;
712fbcf3 452 printf(" Uncompressing %s ... ", type_name);
fc9c1727 453
aed161e5
SG
454 ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len,
455 image_buf, image_len);
78e1e846 456 unc_len = lzma_len;
caf72ff3 457 if (ret != SZ_OK) {
712fbcf3 458 printf("LZMA: uncompress or overwrite error %d "
fc9c1727 459 "- must RESET board to recover\n", ret);
770605e4 460 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
fc9c1727
LCM
461 return BOOTM_ERR_RESET;
462 }
463 *load_end = load + unc_len;
464 break;
78e1e846 465 }
fc9c1727 466#endif /* CONFIG_LZMA */
20dde48b 467#ifdef CONFIG_LZO
628af179 468 case IH_COMP_LZO: {
77cc8902 469 size_t size = unc_len;
628af179 470
712fbcf3 471 printf(" Uncompressing %s ... ", type_name);
20dde48b 472
628af179 473 ret = lzop_decompress(image_buf, image_len, load_buf, &size);
20dde48b 474 if (ret != LZO_E_OK) {
712fbcf3 475 printf("LZO: uncompress or overwrite error %d "
20dde48b
PK
476 "- must RESET board to recover\n", ret);
477 if (boot_progress)
770605e4 478 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
20dde48b
PK
479 return BOOTM_ERR_RESET;
480 }
481
628af179 482 *load_end = load + size;
20dde48b 483 break;
628af179 484 }
20dde48b 485#endif /* CONFIG_LZO */
47d1a6e1 486 default:
712fbcf3 487 printf("Unimplemented compression type %d\n", comp);
396f635b 488 return BOOTM_ERR_UNIMPLEMENTED;
47d1a6e1 489 }
99ffccbd
DC
490
491 flush_cache(load, (*load_end - load) * sizeof(ulong));
492
712fbcf3
SW
493 puts("OK\n");
494 debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
770605e4 495 bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
47d1a6e1 496
d510859b 497 if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) {
712fbcf3
SW
498 debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
499 blob_start, blob_end);
500 debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
501 *load_end);
47d1a6e1 502
d366438d
TR
503 /* Check what type of image this is. */
504 if (images->legacy_hdr_valid) {
505 if (image_get_type(&images->legacy_hdr_os_copy)
506 == IH_TYPE_MULTI)
507 puts("WARNING: legacy format multi component image overwritten\n");
508 return BOOTM_ERR_OVERLAP;
509 } else {
510 puts("ERROR: new format image overwritten - must RESET the board to recover\n");
511 bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
512 return BOOTM_ERR_RESET;
513 }
396f635b
KG
514 }
515
516 return 0;
517}
518
c5cbe1e2
SG
519static int do_bootm_standalone(int flag, int argc, char * const argv[],
520 bootm_headers_t *images)
f97ec30b
DZ
521{
522 char *s;
54841ab5 523 int (*appl)(int, char * const []);
f97ec30b
DZ
524
525 /* Don't start if "autostart" is set to "no" */
526 if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) {
c5cbe1e2 527 setenv_hex("filesize", images->os.image_len);
f97ec30b
DZ
528 return 0;
529 }
9c89614d
CE
530 appl = (int (*)(int, char * const []))images->ep;
531 appl(argc, argv);
f97ec30b
DZ
532 return 0;
533}
534
49c3a861
KG
535/* we overload the cmd field with our state machine info instead of a
536 * function pointer */
f74d9bd2 537static cmd_tbl_t cmd_bootm_sub[] = {
49c3a861
KG
538 U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
539 U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
fca43cc8 540#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
49c3a861
KG
541 U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
542#endif
543#ifdef CONFIG_OF_LIBFDT
544 U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
545#endif
49c3a861 546 U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
224c90d1 547 U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
49c3a861 548 U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
d0ae31eb 549 U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
49c3a861
KG
550 U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
551};
552
35fc84fa 553static int boot_selected_os(int argc, char * const argv[], int state,
5ff0d083 554 bootm_headers_t *images, boot_os_fn *boot_fn)
35fc84fa 555{
35fc84fa
SG
556 arch_preboot_os();
557 boot_fn(state, argc, argv, images);
c5cbe1e2
SG
558
559 /* Stand-alone may return when 'autostart' is 'no' */
560 if (images->os.type == IH_TYPE_STANDALONE ||
561 state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
d0ae31eb 562 return 0;
35fc84fa
SG
563 bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
564#ifdef DEBUG
565 puts("\n## Control returned to monitor - resetting...\n");
566#endif
567 return BOOTM_ERR_RESET;
568}
569
385501d3
SG
570/**
571 * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot
572 *
573 * @return interrupt flag (0 if interrupts were disabled, non-zero if they were
574 * enabled)
575 */
576static ulong bootm_disable_interrupts(void)
577{
578 ulong iflag;
579
580 /*
581 * We have reached the point of no return: we are going to
582 * overwrite all exception vector code, so we cannot easily
583 * recover from any failures any more...
584 */
585 iflag = disable_interrupts();
586#ifdef CONFIG_NETCONSOLE
587 /* Stop the ethernet stack if NetConsole could have left it up */
588 eth_halt();
8094972d 589 eth_unregister(eth_get_dev());
385501d3
SG
590#endif
591
592#if defined(CONFIG_CMD_USB)
593 /*
594 * turn off USB to prevent the host controller from writing to the
595 * SDRAM while Linux is booting. This could happen (at least for OHCI
596 * controller), because the HCCA (Host Controller Communication Area)
597 * lies within the SDRAM and the host controller writes continously to
598 * this area (as busmaster!). The HccaFrameNumber is for example
599 * updated every 1 ms within the HCCA structure in SDRAM! For more
600 * details see the OpenHCI specification.
601 */
602 usb_stop();
603#endif
604 return iflag;
605}
606
35fc84fa
SG
607/**
608 * Execute selected states of the bootm command.
609 *
610 * Note the arguments to this state must be the first argument, Any 'bootm'
611 * or sub-command arguments must have already been taken.
612 *
613 * Note that if states contains more than one flag it MUST contain
614 * BOOTM_STATE_START, since this handles and consumes the command line args.
615 *
d366438d
TR
616 * Also note that aside from boot_os_fn functions and bootm_load_os no other
617 * functions we store the return value of in 'ret' may use a negative return
618 * value, without special handling.
619 *
35fc84fa
SG
620 * @param cmdtp Pointer to bootm command table entry
621 * @param flag Command flags (CMD_FLAG_...)
622 * @param argc Number of subcommand arguments (0 = no arguments)
623 * @param argv Arguments
624 * @param states Mask containing states to run (BOOTM_STATE_...)
625 * @param images Image header information
626 * @param boot_progress 1 to show boot progress, 0 to not do this
627 * @return 0 if ok, something else on error. Some errors will cause this
628 * function to perform a reboot! If states contains BOOTM_STATE_OS_GO
629 * then the intent is to boot an OS, so this function will not return
630 * unless the image type is standalone.
631 */
632static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
633 char * const argv[], int states, bootm_headers_t *images,
634 int boot_progress)
635{
636 boot_os_fn *boot_fn;
637 ulong iflag = 0;
a26913f3 638 int ret = 0, need_boot_fn;
35fc84fa
SG
639
640 images->state |= states;
641
642 /*
643 * Work through the states and see how far we get. We stop on
644 * any error.
645 */
646 if (states & BOOTM_STATE_START)
647 ret = bootm_start(cmdtp, flag, argc, argv);
648
649 if (!ret && (states & BOOTM_STATE_FINDOS))
650 ret = bootm_find_os(cmdtp, flag, argc, argv);
651
652 if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
653 ret = bootm_find_other(cmdtp, flag, argc, argv);
654 argc = 0; /* consume the args */
655 }
656
657 /* Load the OS */
658 if (!ret && (states & BOOTM_STATE_LOADOS)) {
659 ulong load_end;
660
385501d3 661 iflag = bootm_disable_interrupts();
d366438d 662 ret = bootm_load_os(images, &load_end, 0);
d366438d 663 if (ret == 0)
35fc84fa
SG
664 lmb_reserve(&images->lmb, images->os.load,
665 (load_end - images->os.load));
970150a1
TR
666 else if (ret && ret != BOOTM_ERR_OVERLAP)
667 goto err;
d366438d
TR
668 else if (ret == BOOTM_ERR_OVERLAP)
669 ret = 0;
bd4a3997 670#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
576aacdb
SG
671 if (images->os.os == IH_OS_LINUX)
672 fixup_silent_linux();
673#endif
35fc84fa
SG
674 }
675
676 /* Relocate the ramdisk */
677#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
678 if (!ret && (states & BOOTM_STATE_RAMDISK)) {
679 ulong rd_len = images->rd_end - images->rd_start;
680
681 ret = boot_ramdisk_high(&images->lmb, images->rd_start,
682 rd_len, &images->initrd_start, &images->initrd_end);
683 if (!ret) {
684 setenv_hex("initrd_start", images->initrd_start);
685 setenv_hex("initrd_end", images->initrd_end);
686 }
687 }
688#endif
689#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
690 if (!ret && (states & BOOTM_STATE_FDT)) {
691 boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
692 ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
693 &images->ft_len);
694 }
695#endif
696
697 /* From now on, we need the OS boot function */
698 if (ret)
699 return ret;
700 boot_fn = boot_os[images->os.os];
a26913f3
SG
701 need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
702 BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
703 BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
704 if (boot_fn == NULL && need_boot_fn) {
35fc84fa
SG
705 if (iflag)
706 enable_interrupts();
707 printf("ERROR: booting os '%s' (%d) is not supported\n",
708 genimg_get_os_name(images->os.os), images->os.os);
709 bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
710 return 1;
711 }
712
713 /* Call various other states that are not generally used */
714 if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
715 ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
716 if (!ret && (states & BOOTM_STATE_OS_BD_T))
717 ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
718 if (!ret && (states & BOOTM_STATE_OS_PREP))
719 ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
720
d0ae31eb
SG
721#ifdef CONFIG_TRACE
722 /* Pretend to run the OS, then run a user command */
723 if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
724 char *cmd_list = getenv("fakegocmd");
725
726 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
5ff0d083 727 images, boot_fn);
d0ae31eb
SG
728 if (!ret && cmd_list)
729 ret = run_command_list(cmd_list, -1, flag);
730 }
731#endif
b7a1d134
SG
732
733 /* Check for unsupported subcommand. */
734 if (ret) {
735 puts("subcommand not supported\n");
736 return ret;
737 }
738
35fc84fa 739 /* Now run the OS! We hope this doesn't return */
b7a1d134 740 if (!ret && (states & BOOTM_STATE_OS_GO))
35fc84fa 741 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
5ff0d083 742 images, boot_fn);
35fc84fa
SG
743
744 /* Deal with any fallout */
d366438d 745err:
35fc84fa
SG
746 if (iflag)
747 enable_interrupts();
d366438d
TR
748
749 if (ret == BOOTM_ERR_UNIMPLEMENTED)
750 bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
751 else if (ret == BOOTM_ERR_RESET)
752 do_reset(cmdtp, flag, argc, argv);
35fc84fa
SG
753
754 return ret;
755}
756
088f1b19 757static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
712fbcf3 758 char * const argv[])
49c3a861
KG
759{
760 int ret = 0;
6d6f1236 761 long state;
49c3a861 762 cmd_tbl_t *c;
49c3a861 763
983c72f4
SG
764 c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
765 argc--; argv++;
49c3a861
KG
766
767 if (c) {
6d6f1236 768 state = (long)c->cmd;
983c72f4 769 if (state == BOOTM_STATE_START)
35fc84fa 770 state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
47e26b1b
WD
771 } else {
772 /* Unrecognized command */
4c12eeb8 773 return CMD_RET_USAGE;
49c3a861
KG
774 }
775
35fc84fa 776 if (state != BOOTM_STATE_START && images.state >= state) {
712fbcf3 777 printf("Trying to execute a command out of order\n");
4c12eeb8 778 return CMD_RET_USAGE;
49c3a861
KG
779 }
780
35fc84fa 781 ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
49c3a861
KG
782
783 return ret;
784}
785
396f635b
KG
786/*******************************************************************/
787/* bootm - boot application image from image in memory */
788/*******************************************************************/
be083159 789
712fbcf3 790int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
396f635b 791{
2e5167cc 792#ifdef CONFIG_NEEDS_MANUAL_RELOC
521af04d 793 static int relocated = 0;
be083159 794
be083159
KG
795 if (!relocated) {
796 int i;
58bd77db
DS
797
798 /* relocate boot function table */
be083159 799 for (i = 0; i < ARRAY_SIZE(boot_os); i++)
ca95c9df
DZ
800 if (boot_os[i] != NULL)
801 boot_os[i] += gd->reloc_off;
58bd77db
DS
802
803 /* relocate names of sub-command table */
804 for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
805 cmd_bootm_sub[i].name += gd->reloc_off;
806
be083159
KG
807 relocated = 1;
808 }
521af04d 809#endif
396f635b 810
49c3a861 811 /* determine if we have a sub command */
983c72f4
SG
812 argc--; argv++;
813 if (argc > 0) {
49c3a861
KG
814 char *endp;
815
983c72f4
SG
816 simple_strtoul(argv[0], &endp, 16);
817 /* endp pointing to NULL means that argv[0] was just a
49c3a861
KG
818 * valid number, pass it along to the normal bootm processing
819 *
820 * If endp is ':' or '#' assume a FIT identifier so pass
821 * along for normal processing.
822 *
823 * Right now we assume the first arg should never be '-'
824 */
825 if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
826 return do_bootm_subcommand(cmdtp, flag, argc, argv);
827 }
828
35fc84fa
SG
829 return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
830 BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
3d187b39
TR
831 BOOTM_STATE_LOADOS |
832#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
833 BOOTM_STATE_OS_CMDLINE |
834#endif
5c427e49
PB
835 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
836 BOOTM_STATE_OS_GO, &images, 1);
47d1a6e1
WD
837}
838
67d668bf
MF
839int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
840{
841 const char *ep = getenv("autostart");
842
843 if (ep && !strcmp(ep, "yes")) {
844 char *local_args[2];
845 local_args[0] = (char *)cmd;
846 local_args[1] = NULL;
847 printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
848 return do_bootm(cmdtp, 0, 1, local_args);
849 }
850
851 return 0;
852}
853
1efd4360 854/**
9a4daad0
MB
855 * image_get_kernel - verify legacy format kernel image
856 * @img_addr: in RAM address of the legacy format image to be verified
857 * @verify: data CRC verification flag
1efd4360 858 *
9a4daad0
MB
859 * image_get_kernel() verifies legacy image integrity and returns pointer to
860 * legacy image header if image verification was completed successfully.
1efd4360
MB
861 *
862 * returns:
9a4daad0
MB
863 * pointer to a legacy image header if valid image was found
864 * otherwise return NULL
1efd4360 865 */
712fbcf3 866static image_header_t *image_get_kernel(ulong img_addr, int verify)
f72da340 867{
1efd4360 868 image_header_t *hdr = (image_header_t *)img_addr;
f72da340 869
1efd4360 870 if (!image_check_magic(hdr)) {
712fbcf3 871 puts("Bad Magic Number\n");
770605e4 872 bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
1efd4360
MB
873 return NULL;
874 }
770605e4 875 bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
f72da340 876
712fbcf3
SW
877 if (!image_check_hcrc(hdr)) {
878 puts("Bad Header Checksum\n");
770605e4 879 bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
1efd4360
MB
880 return NULL;
881 }
882
770605e4 883 bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
712fbcf3 884 image_print_contents(hdr);
1efd4360
MB
885
886 if (verify) {
712fbcf3
SW
887 puts(" Verifying Checksum ... ");
888 if (!image_check_dcrc(hdr)) {
889 printf("Bad Data CRC\n");
770605e4 890 bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
1efd4360 891 return NULL;
f72da340 892 }
712fbcf3 893 puts("OK\n");
f72da340 894 }
770605e4 895 bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
f72da340 896
712fbcf3
SW
897 if (!image_check_target_arch(hdr)) {
898 printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
770605e4 899 bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
1efd4360
MB
900 return NULL;
901 }
902 return hdr;
f72da340 903}
f72da340 904
5cf746c3 905/**
9a4daad0 906 * boot_get_kernel - find kernel image
5cf746c3
MB
907 * @os_data: pointer to a ulong variable, will hold os data start address
908 * @os_len: pointer to a ulong variable, will hold os data length
909 *
9a4daad0 910 * boot_get_kernel() tries to find a kernel image, verifies its integrity
5cf746c3
MB
911 * and locates kernel data.
912 *
913 * returns:
914 * pointer to image header if valid image was found, plus kernel start
915 * address and length, otherwise NULL
916 */
35e7b0f1 917static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
712fbcf3
SW
918 char * const argv[], bootm_headers_t *images, ulong *os_data,
919 ulong *os_len)
5cf746c3
MB
920{
921 image_header_t *hdr;
922 ulong img_addr;
35e7b0f1 923 const void *buf;
d5934ad7 924#if defined(CONFIG_FIT)
d5934ad7
MB
925 const char *fit_uname_config = NULL;
926 const char *fit_uname_kernel = NULL;
6986a385 927 int os_noffset;
d5934ad7 928#endif
56f94be3 929
d5934ad7 930 /* find out kernel image address */
983c72f4 931 if (argc < 1) {
5cf746c3 932 img_addr = load_addr;
712fbcf3 933 debug("* kernel: default image load address = 0x%08lx\n",
d5934ad7
MB
934 load_addr);
935#if defined(CONFIG_FIT)
983c72f4 936 } else if (fit_parse_conf(argv[0], load_addr, &img_addr,
d5934ad7 937 &fit_uname_config)) {
712fbcf3 938 debug("* kernel: config '%s' from image at 0x%08lx\n",
d5934ad7 939 fit_uname_config, img_addr);
983c72f4 940 } else if (fit_parse_subimage(argv[0], load_addr, &img_addr,
d5934ad7 941 &fit_uname_kernel)) {
712fbcf3 942 debug("* kernel: subimage '%s' from image at 0x%08lx\n",
d5934ad7
MB
943 fit_uname_kernel, img_addr);
944#endif
5cf746c3 945 } else {
983c72f4 946 img_addr = simple_strtoul(argv[0], NULL, 16);
712fbcf3 947 debug("* kernel: cmdline image address = 0x%08lx\n", img_addr);
5cf746c3 948 }
47d1a6e1 949
770605e4 950 bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
56f94be3 951
fff888a1 952 /* copy from dataflash if needed */
712fbcf3 953 img_addr = genimg_get_image(img_addr);
5cf746c3 954
d5934ad7 955 /* check image type, for FIT images get FIT kernel node */
6986a385 956 *os_data = *os_len = 0;
35e7b0f1
SG
957 buf = map_sysmem(img_addr, 0);
958 switch (genimg_get_format(buf)) {
d5934ad7 959 case IMAGE_FORMAT_LEGACY:
712fbcf3 960 printf("## Booting kernel from Legacy Image at %08lx ...\n",
6986a385 961 img_addr);
712fbcf3 962 hdr = image_get_kernel(img_addr, images->verify);
1efd4360 963 if (!hdr)
d5934ad7 964 return NULL;
770605e4 965 bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
d5934ad7 966
6986a385 967 /* get os_data and os_len */
712fbcf3 968 switch (image_get_type(hdr)) {
d5934ad7 969 case IH_TYPE_KERNEL:
b9b50e89 970 case IH_TYPE_KERNEL_NOLOAD:
712fbcf3
SW
971 *os_data = image_get_data(hdr);
972 *os_len = image_get_data_size(hdr);
d5934ad7
MB
973 break;
974 case IH_TYPE_MULTI:
712fbcf3 975 image_multi_getimg(hdr, 0, os_data, os_len);
d5934ad7 976 break;
f97ec30b 977 case IH_TYPE_STANDALONE:
712fbcf3
SW
978 *os_data = image_get_data(hdr);
979 *os_len = image_get_data_size(hdr);
f97ec30b 980 break;
d5934ad7 981 default:
712fbcf3
SW
982 printf("Wrong Image Type for %s command\n",
983 cmdtp->name);
770605e4 984 bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
d5934ad7
MB
985 return NULL;
986 }
cb1c4896
MB
987
988 /*
712fbcf3
SW
989 * copy image header to allow for image overwrites during
990 * kernel decompression.
cb1c4896 991 */
712fbcf3
SW
992 memmove(&images->legacy_hdr_os_copy, hdr,
993 sizeof(image_header_t));
cb1c4896
MB
994
995 /* save pointer to image header */
d5934ad7 996 images->legacy_hdr_os = hdr;
47d1a6e1 997
cb1c4896 998 images->legacy_hdr_valid = 1;
770605e4 999 bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
5cf746c3 1000 break;
d5934ad7
MB
1001#if defined(CONFIG_FIT)
1002 case IMAGE_FORMAT_FIT:
4651800d
SG
1003 os_noffset = fit_image_load(images, FIT_KERNEL_PROP,
1004 img_addr,
f320a4d8 1005 &fit_uname_kernel, &fit_uname_config,
4651800d
SG
1006 IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
1007 BOOTSTAGE_ID_FIT_KERNEL_START,
1008 FIT_LOAD_IGNORED, os_data, os_len);
1009 if (os_noffset < 0)
6986a385 1010 return NULL;
47d1a6e1 1011
4651800d 1012 images->fit_hdr_os = map_sysmem(img_addr, 0);
6986a385 1013 images->fit_uname_os = fit_uname_kernel;
f320a4d8 1014 images->fit_uname_cfg = fit_uname_config;
3dfe1101 1015 images->fit_noffset_os = os_noffset;
6986a385 1016 break;
9ace3fc8
SS
1017#endif
1018#ifdef CONFIG_ANDROID_BOOT_IMAGE
1019 case IMAGE_FORMAT_ANDROID:
1020 printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
1021 if (android_image_get_kernel((void *)img_addr, images->verify,
1022 os_data, os_len))
1023 return NULL;
1024 break;
9c4c5ae3 1025#endif
5cf746c3 1026 default:
712fbcf3 1027 printf("Wrong Image Format for %s command\n", cmdtp->name);
770605e4 1028 bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
5cf746c3 1029 return NULL;
47d1a6e1
WD
1030 }
1031
712fbcf3 1032 debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
6986a385 1033 *os_data, *os_len, *os_len);
47d1a6e1 1034
35e7b0f1 1035 return buf;
5cf746c3 1036}
98a9c4d4 1037
088f1b19
KP
1038#ifdef CONFIG_SYS_LONGHELP
1039static char bootm_help_text[] =
1ee1180b
MB
1040 "[addr [arg ...]]\n - boot application image stored in memory\n"
1041 "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
1042 "\t'arg' can be the address of an initrd image\n"
4a2ad5ff 1043#if defined(CONFIG_OF_LIBFDT)
98a9c4d4 1044 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
5441f61a 1045 "\ta third argument is required which is the address of the\n"
98a9c4d4
MM
1046 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1047 "\tuse a '-' for the second argument. If you do not pass a third\n"
1048 "\ta bd_info struct will be passed instead\n"
98a9c4d4 1049#endif
6986a385
MB
1050#if defined(CONFIG_FIT)
1051 "\t\nFor the new multi component uImage format (FIT) addresses\n"
1052 "\tmust be extened to include component or configuration unit name:\n"
1053 "\taddr:<subimg_uname> - direct component image specification\n"
1054 "\taddr#<conf_uname> - configuration specification\n"
1055 "\tUse iminfo command to get the list of existing component\n"
1056 "\timages and configurations.\n"
1057#endif
49c3a861
KG
1058 "\nSub-commands to do part of the bootm sequence. The sub-commands "
1059 "must be\n"
1060 "issued in the order below (it's ok to not issue all sub-commands):\n"
1061 "\tstart [addr [arg ...]]\n"
1062 "\tloados - load OS image\n"
59af76d9 1063#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
49c3a861
KG
1064 "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
1065#endif
1066#if defined(CONFIG_OF_LIBFDT)
1067 "\tfdt - relocate flat device tree\n"
1068#endif
49c3a861 1069 "\tcmdline - OS specific command line processing/setup\n"
224c90d1 1070 "\tbdt - OS specific bd_t processing\n"
49c3a861 1071 "\tprep - OS specific prep before relocation or go\n"
088f1b19
KP
1072 "\tgo - start OS";
1073#endif
1074
1075U_BOOT_CMD(
1076 bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
1077 "boot application image from memory", bootm_help_text
8bde7f77 1078);
47d1a6e1 1079
1ee1180b
MB
1080/*******************************************************************/
1081/* bootd - boot default image */
1082/*******************************************************************/
baa26db4 1083#if defined(CONFIG_CMD_BOOTD)
712fbcf3 1084int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
47d1a6e1
WD
1085{
1086 int rcode = 0;
47d1a6e1 1087
53071532 1088 if (run_command(getenv("bootcmd"), flag) < 0)
1ee1180b 1089 rcode = 1;
47d1a6e1
WD
1090 return rcode;
1091}
47d1a6e1 1092
0d498393 1093U_BOOT_CMD(
1ee1180b 1094 boot, 1, 1, do_bootd,
2fb2604d 1095 "boot default, i.e., run 'bootcmd'",
a89c33db 1096 ""
9d2b18a0 1097);
47d1a6e1 1098
9d2b18a0 1099/* keep old command name "bootd" for backward compatibility */
0d498393 1100U_BOOT_CMD(
1ee1180b 1101 bootd, 1, 1, do_bootd,
2fb2604d 1102 "boot default, i.e., run 'bootcmd'",
a89c33db 1103 ""
8bde7f77 1104);
47d1a6e1 1105
47d1a6e1 1106#endif
47d1a6e1 1107
47d1a6e1 1108
1ee1180b
MB
1109/*******************************************************************/
1110/* iminfo - print header info for a requested image */
1111/*******************************************************************/
baa26db4 1112#if defined(CONFIG_CMD_IMI)
088f1b19 1113static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
47d1a6e1
WD
1114{
1115 int arg;
1116 ulong addr;
1ee1180b 1117 int rcode = 0;
47d1a6e1 1118
47d1a6e1 1119 if (argc < 2) {
712fbcf3 1120 return image_info(load_addr);
47d1a6e1 1121 }
47d1a6e1 1122
1ee1180b 1123 for (arg = 1; arg < argc; ++arg) {
712fbcf3
SW
1124 addr = simple_strtoul(argv[arg], NULL, 16);
1125 if (image_info(addr) != 0)
1ee1180b 1126 rcode = 1;
47d1a6e1
WD
1127 }
1128 return rcode;
1129}
47d1a6e1 1130
712fbcf3 1131static int image_info(ulong addr)
47d1a6e1 1132{
d5934ad7 1133 void *hdr = (void *)addr;
47d1a6e1 1134
712fbcf3 1135 printf("\n## Checking Image at %08lx ...\n", addr);
47d1a6e1 1136
712fbcf3 1137 switch (genimg_get_format(hdr)) {
d5934ad7 1138 case IMAGE_FORMAT_LEGACY:
712fbcf3
SW
1139 puts(" Legacy image found\n");
1140 if (!image_check_magic(hdr)) {
1141 puts(" Bad Magic Number\n");
d5934ad7
MB
1142 return 1;
1143 }
47d1a6e1 1144
712fbcf3
SW
1145 if (!image_check_hcrc(hdr)) {
1146 puts(" Bad Header Checksum\n");
d5934ad7 1147 return 1;
47d1a6e1
WD
1148 }
1149
712fbcf3 1150 image_print_contents(hdr);
47d1a6e1 1151
712fbcf3
SW
1152 puts(" Verifying Checksum ... ");
1153 if (!image_check_dcrc(hdr)) {
1154 puts(" Bad Data CRC\n");
d5934ad7 1155 return 1;
47d1a6e1 1156 }
712fbcf3 1157 puts("OK\n");
d5934ad7
MB
1158 return 0;
1159#if defined(CONFIG_FIT)
1160 case IMAGE_FORMAT_FIT:
712fbcf3 1161 puts(" FIT image found\n");
47d1a6e1 1162
712fbcf3
SW
1163 if (!fit_check_format(hdr)) {
1164 puts("Bad FIT image format!\n");
e32fea6a 1165 return 1;
47d1a6e1
WD
1166 }
1167
712fbcf3 1168 fit_print_contents(hdr);
a4f24345 1169
b8da8366 1170 if (!fit_all_image_verify(hdr)) {
712fbcf3 1171 puts("Bad hash in FIT image!\n");
a4f24345
BS
1172 return 1;
1173 }
1174
d5934ad7
MB
1175 return 0;
1176#endif
1177 default:
712fbcf3 1178 puts("Unknown image format!\n");
d5934ad7 1179 break;
47d1a6e1
WD
1180 }
1181
d5934ad7 1182 return 1;
47d1a6e1 1183}
0d498393
WD
1184
1185U_BOOT_CMD(
6d0f6bcf 1186 iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
2fb2604d 1187 "print header information for application image",
8bde7f77
WD
1188 "addr [addr ...]\n"
1189 " - print header information for application image starting at\n"
1190 " address 'addr' in memory; this includes verification of the\n"
a89c33db 1191 " image contents (magic number, header and payload checksums)"
8bde7f77 1192);
25c751e9 1193#endif
87a449c8 1194
25c751e9 1195
1ee1180b
MB
1196/*******************************************************************/
1197/* imls - list all images found in flash */
1198/*******************************************************************/
baa26db4 1199#if defined(CONFIG_CMD_IMLS)
8fdf1e0f 1200static int do_imls_nor(void)
27b207fd
WD
1201{
1202 flash_info_t *info;
1203 int i, j;
d5934ad7 1204 void *hdr;
25c751e9 1205
1ee1180b 1206 for (i = 0, info = &flash_info[0];
6d0f6bcf 1207 i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
25c751e9 1208
27b207fd
WD
1209 if (info->flash_id == FLASH_UNKNOWN)
1210 goto next_bank;
1ee1180b 1211 for (j = 0; j < info->sector_count; ++j) {
25c751e9 1212
d5934ad7
MB
1213 hdr = (void *)info->start[j];
1214 if (!hdr)
b97a2a0a 1215 goto next_sector;
27b207fd 1216
712fbcf3 1217 switch (genimg_get_format(hdr)) {
d5934ad7 1218 case IMAGE_FORMAT_LEGACY:
712fbcf3 1219 if (!image_check_hcrc(hdr))
d5934ad7
MB
1220 goto next_sector;
1221
712fbcf3
SW
1222 printf("Legacy Image at %08lX:\n", (ulong)hdr);
1223 image_print_contents(hdr);
d5934ad7 1224
712fbcf3
SW
1225 puts(" Verifying Checksum ... ");
1226 if (!image_check_dcrc(hdr)) {
1227 puts("Bad Data CRC\n");
d5934ad7 1228 } else {
712fbcf3 1229 puts("OK\n");
d5934ad7
MB
1230 }
1231 break;
1232#if defined(CONFIG_FIT)
1233 case IMAGE_FORMAT_FIT:
712fbcf3 1234 if (!fit_check_format(hdr))
e32fea6a
MB
1235 goto next_sector;
1236
712fbcf3
SW
1237 printf("FIT Image at %08lX:\n", (ulong)hdr);
1238 fit_print_contents(hdr);
d5934ad7 1239 break;
213bf8c8 1240#endif
d5934ad7 1241 default:
27b207fd 1242 goto next_sector;
25c751e9 1243 }
87a449c8 1244
bdccc4fe 1245next_sector: ;
c76f951a 1246 }
bdccc4fe 1247next_bank: ;
27b207fd 1248 }
8fdf1e0f
VK
1249 return 0;
1250}
1251#endif
1252
1253#if defined(CONFIG_CMD_IMLS_NAND)
1254static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
1255 size_t len)
1256{
1257 void *imgdata;
1258 int ret;
1259
1260 imgdata = malloc(len);
1261 if (!imgdata) {
1262 printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
1263 nand_dev, off);
1264 printf(" Low memory(cannot allocate memory for image)\n");
1265 return -ENOMEM;
1266 }
1267
1268 ret = nand_read_skip_bad(nand, off, &len,
1269 imgdata);
1270 if (ret < 0 && ret != -EUCLEAN) {
1271 free(imgdata);
1272 return ret;
1273 }
1274
1275 if (!image_check_hcrc(imgdata)) {
1276 free(imgdata);
1277 return 0;
1278 }
1279
1280 printf("Legacy Image at NAND device %d offset %08llX:\n",
1281 nand_dev, off);
1282 image_print_contents(imgdata);
1283
1284 puts(" Verifying Checksum ... ");
1285 if (!image_check_dcrc(imgdata))
1286 puts("Bad Data CRC\n");
1287 else
1288 puts("OK\n");
1289
1290 free(imgdata);
1291
1292 return 0;
1293}
1294
1295static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
1296 size_t len)
1297{
1298 void *imgdata;
1299 int ret;
1300
1301 imgdata = malloc(len);
1302 if (!imgdata) {
1303 printf("May be a FIT Image at NAND device %d offset %08llX:\n",
1304 nand_dev, off);
1305 printf(" Low memory(cannot allocate memory for image)\n");
1306 return -ENOMEM;
1307 }
1308
1309 ret = nand_read_skip_bad(nand, off, &len,
1310 imgdata);
1311 if (ret < 0 && ret != -EUCLEAN) {
1312 free(imgdata);
1313 return ret;
1314 }
1315
1316 if (!fit_check_format(imgdata)) {
1317 free(imgdata);
1318 return 0;
1319 }
1320
1321 printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
1322
1323 fit_print_contents(imgdata);
1324 free(imgdata);
1325
1326 return 0;
1327}
1328
1329static int do_imls_nand(void)
1330{
1331 nand_info_t *nand;
1332 int nand_dev = nand_curr_device;
1333 size_t len;
1334 loff_t off;
1335 u32 buffer[16];
1336
1337 if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
1338 puts("\nNo NAND devices available\n");
1339 return -ENODEV;
1340 }
1341
1342 printf("\n");
1343
1344 for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
1345 nand = &nand_info[nand_dev];
1346 if (!nand->name || !nand->size)
1347 continue;
1348
1349 for (off = 0; off < nand->size; off += nand->erasesize) {
1350 const image_header_t *header;
1351 int ret;
1352
1353 if (nand_block_isbad(nand, off))
1354 continue;
1355
1356 len = sizeof(buffer);
1357
1358 ret = nand_read(nand, off, &len, (u8 *)buffer);
1359 if (ret < 0 && ret != -EUCLEAN) {
1360 printf("NAND read error %d at offset %08llX\n",
1361 ret, off);
1362 continue;
1363 }
1364
1365 switch (genimg_get_format(buffer)) {
1366 case IMAGE_FORMAT_LEGACY:
1367 header = (const image_header_t *)buffer;
1368
1369 len = image_get_image_size(header);
1370 nand_imls_legacyimage(nand, nand_dev, off, len);
1371 break;
1372#if defined(CONFIG_FIT)
1373 case IMAGE_FORMAT_FIT:
1374 len = fit_get_size(buffer);
1375 nand_imls_fitimage(nand, nand_dev, off, len);
1376 break;
1377#endif
1378 }
1379 }
1380 }
1381
1382 return 0;
1383}
1384#endif
1385
1386#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
1387static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1388{
1389 int ret_nor = 0, ret_nand = 0;
1390
1391#if defined(CONFIG_CMD_IMLS)
1392 ret_nor = do_imls_nor();
1393#endif
1394
1395#if defined(CONFIG_CMD_IMLS_NAND)
1396 ret_nand = do_imls_nand();
1397#endif
1398
1399 if (ret_nor)
1400 return ret_nor;
1401
1402 if (ret_nand)
1403 return ret_nand;
c76f951a 1404
27b207fd
WD
1405 return (0);
1406}
c76f951a 1407
27b207fd
WD
1408U_BOOT_CMD(
1409 imls, 1, 1, do_imls,
2fb2604d 1410 "list all images found in flash",
27b207fd 1411 "\n"
8fdf1e0f
VK
1412 " - Prints information about all images found at sector/block\n"
1413 " boundaries in nor/nand flash."
27b207fd 1414);
98a9c4d4 1415#endif
47d1a6e1 1416
1ee1180b 1417/*******************************************************************/
5cf746c3 1418/* helper routines */
1ee1180b 1419/*******************************************************************/
be2e5a09 1420#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
a558ad71
DA
1421
1422#define CONSOLE_ARG "console="
1423#define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1)
1424
3a8653b3 1425static void fixup_silent_linux(void)
1ee1180b 1426{
a558ad71
DA
1427 char *buf;
1428 const char *env_val;
3a8653b3 1429 char *cmdline = getenv("bootargs");
8d51aacd 1430 int want_silent;
47d1a6e1 1431
8d51aacd
SG
1432 /*
1433 * Only fix cmdline when requested. The environment variable can be:
1434 *
1435 * no - we never fixup
1436 * yes - we always fixup
1437 * unset - we rely on the console silent flag
1438 */
1439 want_silent = getenv_yesno("silent_linux");
1440 if (want_silent == 0)
1441 return;
1442 else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
1ee1180b 1443 return;
47d1a6e1 1444
3a8653b3 1445 debug("before silent fix-up: %s\n", cmdline);
a558ad71
DA
1446 if (cmdline && (cmdline[0] != '\0')) {
1447 char *start = strstr(cmdline, CONSOLE_ARG);
1448
1449 /* Allocate space for maximum possible new command line */
1450 buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1);
1451 if (!buf) {
1452 debug("%s: out of memory\n", __func__);
1453 return;
1454 }
1455
3a8653b3 1456 if (start) {
a558ad71
DA
1457 char *end = strchr(start, ' ');
1458 int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN;
1459
1460 strncpy(buf, cmdline, num_start_bytes);
1ee1180b 1461 if (end)
a558ad71 1462 strcpy(buf + num_start_bytes, end);
1ee1180b 1463 else
a558ad71 1464 buf[num_start_bytes] = '\0';
1ee1180b 1465 } else {
a558ad71 1466 sprintf(buf, "%s %s", cmdline, CONSOLE_ARG);
47d1a6e1 1467 }
a558ad71 1468 env_val = buf;
47d1a6e1 1469 } else {
a558ad71
DA
1470 buf = NULL;
1471 env_val = CONSOLE_ARG;
e7902122 1472 }
10aaf716 1473
a558ad71
DA
1474 setenv("bootargs", env_val);
1475 debug("after silent fix-up: %s\n", env_val);
1476 free(buf);
1ee1180b
MB
1477}
1478#endif /* CONFIG_SILENT_CONSOLE */
38eb508e 1479
eeaef5e4
SS
1480#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9)
1481static void copy_args(char *dest, int argc, char * const argv[], char delim)
1482{
1483 int i;
1484
1485 for (i = 0; i < argc; i++) {
1486 if (i > 0)
1487 *dest++ = delim;
1488 strcpy(dest, argv[i]);
1489 dest += strlen(argv[i]);
1490 }
1491}
1492#endif
38eb508e 1493
1ee1180b
MB
1494/*******************************************************************/
1495/* OS booting routines */
1496/*******************************************************************/
c76f951a 1497
b1d0db18 1498#ifdef CONFIG_BOOTM_NETBSD
712fbcf3 1499static int do_bootm_netbsd(int flag, int argc, char * const argv[],
8a5ea3e6 1500 bootm_headers_t *images)
d791b1dc 1501{
1ee1180b 1502 void (*loader)(bd_t *, image_header_t *, char *, char *);
d5934ad7 1503 image_header_t *os_hdr, *hdr;
f13e7b2e 1504 ulong kernel_data, kernel_len;
1ee1180b
MB
1505 char *consdev;
1506 char *cmdline;
1507
5b629319 1508 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1509 return 0;
49c3a861 1510
d5934ad7
MB
1511#if defined(CONFIG_FIT)
1512 if (!images->legacy_hdr_valid) {
712fbcf3 1513 fit_unsupported_reset("NetBSD");
40d7e99d 1514 return 1;
38eb508e
GVB
1515 }
1516#endif
d5934ad7 1517 hdr = images->legacy_hdr_os;
47d1a6e1
WD
1518
1519 /*
1520 * Booting a (NetBSD) kernel image
1521 *
1522 * This process is pretty similar to a standalone application:
1523 * The (first part of an multi-) image must be a stage-2 loader,
1524 * which in turn is responsible for loading & invoking the actual
1525 * kernel. The only differences are the parameters being passed:
1526 * besides the board info strucure, the loader expects a command
1527 * line, the name of the console device, and (optionally) the
1528 * address of the original image header.
1529 */
d5934ad7 1530 os_hdr = NULL;
712fbcf3
SW
1531 if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
1532 image_multi_getimg(hdr, 1, &kernel_data, &kernel_len);
f13e7b2e 1533 if (kernel_len)
d5934ad7 1534 os_hdr = hdr;
f13e7b2e 1535 }
47d1a6e1
WD
1536
1537 consdev = "";
712fbcf3 1538#if defined(CONFIG_8xx_CONS_SMC1)
47d1a6e1 1539 consdev = "smc1";
712fbcf3 1540#elif defined(CONFIG_8xx_CONS_SMC2)
47d1a6e1 1541 consdev = "smc2";
712fbcf3 1542#elif defined(CONFIG_8xx_CONS_SCC2)
47d1a6e1 1543 consdev = "scc2";
712fbcf3 1544#elif defined(CONFIG_8xx_CONS_SCC3)
47d1a6e1
WD
1545 consdev = "scc3";
1546#endif
1547
983c72f4 1548 if (argc > 0) {
47d1a6e1
WD
1549 ulong len;
1550 int i;
1551
983c72f4 1552 for (i = 0, len = 0; i < argc; i += 1)
712fbcf3
SW
1553 len += strlen(argv[i]) + 1;
1554 cmdline = malloc(len);
eeaef5e4 1555 copy_args(cmdline, argc, argv, ' ');
712fbcf3 1556 } else if ((cmdline = getenv("bootargs")) == NULL) {
47d1a6e1
WD
1557 cmdline = "";
1558 }
1559
c160a954 1560 loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep;
47d1a6e1 1561
712fbcf3
SW
1562 printf("## Transferring control to NetBSD stage-2 loader "
1563 "(at address %08lx) ...\n",
47d1a6e1
WD
1564 (ulong)loader);
1565
770605e4 1566 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
47d1a6e1
WD
1567
1568 /*
1569 * NetBSD Stage-2 Loader Parameters:
e2ce8169
KJ
1570 * arg[0]: pointer to board info data
1571 * arg[1]: image load address
1572 * arg[2]: char pointer to the console device to use
1573 * arg[3]: char pointer to the boot arguments
47d1a6e1 1574 */
712fbcf3 1575 (*loader)(gd->bd, os_hdr, consdev, cmdline);
40d7e99d
KG
1576
1577 return 1;
47d1a6e1 1578}
b1d0db18 1579#endif /* CONFIG_BOOTM_NETBSD*/
47d1a6e1 1580
1ee1180b 1581#ifdef CONFIG_LYNXKDI
712fbcf3 1582static int do_bootm_lynxkdi(int flag, int argc, char * const argv[],
8a5ea3e6 1583 bootm_headers_t *images)
1ee1180b 1584{
cb1c4896 1585 image_header_t *hdr = &images->legacy_hdr_os_copy;
d5934ad7 1586
5b629319 1587 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1588 return 0;
49c3a861 1589
d5934ad7
MB
1590#if defined(CONFIG_FIT)
1591 if (!images->legacy_hdr_valid) {
712fbcf3 1592 fit_unsupported_reset("Lynx");
40d7e99d 1593 return 1;
d5934ad7
MB
1594 }
1595#endif
1596
712fbcf3 1597 lynxkdi_boot((image_header_t *)hdr);
40d7e99d
KG
1598
1599 return 1;
1ee1180b
MB
1600}
1601#endif /* CONFIG_LYNXKDI */
1602
b1d0db18 1603#ifdef CONFIG_BOOTM_RTEMS
712fbcf3 1604static int do_bootm_rtems(int flag, int argc, char * const argv[],
8a5ea3e6 1605 bootm_headers_t *images)
1ee1180b 1606{
1ee1180b 1607 void (*entry_point)(bd_t *);
d791b1dc 1608
5b629319 1609 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1610 return 0;
49c3a861 1611
d5934ad7
MB
1612#if defined(CONFIG_FIT)
1613 if (!images->legacy_hdr_valid) {
712fbcf3 1614 fit_unsupported_reset("RTEMS");
40d7e99d 1615 return 1;
d5934ad7
MB
1616 }
1617#endif
1618
c160a954 1619 entry_point = (void (*)(bd_t *))images->ep;
d791b1dc 1620
712fbcf3 1621 printf("## Transferring control to RTEMS (at address %08lx) ...\n",
d791b1dc
WD
1622 (ulong)entry_point);
1623
770605e4 1624 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
d791b1dc
WD
1625
1626 /*
1627 * RTEMS Parameters:
1628 * r3: ptr to board info data
1629 */
1ee1180b 1630 (*entry_point)(gd->bd);
40d7e99d
KG
1631
1632 return 1;
d791b1dc 1633}
b1d0db18 1634#endif /* CONFIG_BOOTM_RTEMS */
7f70e853 1635
3df61957 1636#if defined(CONFIG_BOOTM_OSE)
712fbcf3 1637static int do_bootm_ose(int flag, int argc, char * const argv[],
3df61957
TL
1638 bootm_headers_t *images)
1639{
1640 void (*entry_point)(void);
1641
5b629319 1642 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1643 return 0;
3df61957
TL
1644
1645#if defined(CONFIG_FIT)
1646 if (!images->legacy_hdr_valid) {
712fbcf3 1647 fit_unsupported_reset("OSE");
3df61957
TL
1648 return 1;
1649 }
1650#endif
1651
1652 entry_point = (void (*)(void))images->ep;
1653
712fbcf3 1654 printf("## Transferring control to OSE (at address %08lx) ...\n",
3df61957
TL
1655 (ulong)entry_point);
1656
770605e4 1657 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
3df61957
TL
1658
1659 /*
1660 * OSE Parameters:
1661 * None
1662 */
1663 (*entry_point)();
1664
1665 return 1;
1666}
1667#endif /* CONFIG_BOOTM_OSE */
1668
04d41409
SS
1669#if defined(CONFIG_BOOTM_PLAN9)
1670static int do_bootm_plan9(int flag, int argc, char * const argv[],
1671 bootm_headers_t *images)
1672{
1673 void (*entry_point)(void);
eeaef5e4 1674 char *s;
04d41409 1675
5b629319 1676 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1677 return 0;
04d41409
SS
1678
1679#if defined(CONFIG_FIT)
1680 if (!images->legacy_hdr_valid) {
1681 fit_unsupported_reset("Plan 9");
1682 return 1;
1683 }
1684#endif
1685
eeaef5e4
SS
1686 /* See README.plan9 */
1687 s = getenv("confaddr");
1688 if (s != NULL) {
1689 char *confaddr = (char *)simple_strtoul(s, NULL, 16);
1690
1691 if (argc > 0) {
1692 copy_args(confaddr, argc, argv, '\n');
1693 } else {
1694 s = getenv("bootargs");
1695 if (s != NULL)
1696 strcpy(confaddr, s);
1697 }
1698 }
1699
04d41409
SS
1700 entry_point = (void (*)(void))images->ep;
1701
1702 printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
1703 (ulong)entry_point);
1704
1705 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1706
1707 /*
1708 * Plan 9 Parameters:
1709 * None
1710 */
1711 (*entry_point)();
1712
1713 return 1;
1714}
1715#endif /* CONFIG_BOOTM_PLAN9 */
1716
871a57bb
MY
1717#if defined(CONFIG_BOOTM_VXWORKS) && \
1718 (defined(CONFIG_PPC) || defined(CONFIG_ARM))
1719
1720void do_bootvx_fdt(bootm_headers_t *images)
1721{
1722#if defined(CONFIG_OF_LIBFDT)
1723 int ret;
1724 char *bootline;
1725 ulong of_size = images->ft_len;
1726 char **of_flat_tree = &images->ft_addr;
1727 struct lmb *lmb = &images->lmb;
1728
1729 if (*of_flat_tree) {
1730 boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
1731
1732 ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
1733 if (ret)
1734 return;
1735
1736 ret = fdt_add_subnode(*of_flat_tree, 0, "chosen");
1737 if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) {
1738 bootline = getenv("bootargs");
1739 if (bootline) {
1740 ret = fdt_find_and_setprop(*of_flat_tree,
1741 "/chosen", "bootargs",
1742 bootline,
1743 strlen(bootline) + 1, 1);
1744 if (ret < 0) {
1745 printf("## ERROR: %s : %s\n", __func__,
1746 fdt_strerror(ret));
1747 return;
1748 }
1749 }
1750 } else {
1751 printf("## ERROR: %s : %s\n", __func__,
1752 fdt_strerror(ret));
1753 return;
1754 }
1755 }
1756#endif
1757
1758 boot_prep_vxworks(images);
1759
1760 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
1761
1762#if defined(CONFIG_OF_LIBFDT)
1763 printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n",
1764 (ulong)images->ep, (ulong)*of_flat_tree);
1765#else
1766 printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep);
1767#endif
1768
1769 boot_jump_vxworks(images);
1770
1771 puts("## vxWorks terminated\n");
1772}
1773
712fbcf3 1774static int do_bootm_vxworks(int flag, int argc, char * const argv[],
8a5ea3e6 1775 bootm_headers_t *images)
47d1a6e1 1776{
5b629319 1777 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1778 return 0;
49c3a861 1779
d5934ad7 1780#if defined(CONFIG_FIT)
cb1c4896 1781 if (!images->legacy_hdr_valid) {
712fbcf3 1782 fit_unsupported_reset("VxWorks");
40d7e99d 1783 return 1;
d5934ad7
MB
1784 }
1785#endif
47d1a6e1 1786
871a57bb 1787 do_bootvx_fdt(images);
40d7e99d
KG
1788
1789 return 1;
47d1a6e1 1790}
17ab52fe 1791#endif
47d1a6e1 1792
17ab52fe 1793#if defined(CONFIG_CMD_ELF)
54841ab5 1794static int do_bootm_qnxelf(int flag, int argc, char * const argv[],
8a5ea3e6 1795 bootm_headers_t *images)
47d1a6e1 1796{
47d1a6e1
WD
1797 char *local_args[2];
1798 char str[16];
d5934ad7 1799
5b629319 1800 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1801 return 0;
49c3a861 1802
d5934ad7
MB
1803#if defined(CONFIG_FIT)
1804 if (!images->legacy_hdr_valid) {
712fbcf3 1805 fit_unsupported_reset("QNX");
40d7e99d 1806 return 1;
d5934ad7
MB
1807 }
1808#endif
47d1a6e1 1809
c160a954 1810 sprintf(str, "%lx", images->ep); /* write entry-point into string */
47d1a6e1
WD
1811 local_args[0] = argv[0];
1812 local_args[1] = str; /* and provide it via the arguments */
40d7e99d
KG
1813 do_bootelf(NULL, 0, 2, local_args);
1814
1815 return 1;
47d1a6e1 1816}
90253178 1817#endif
f5ed9e39
PT
1818
1819#ifdef CONFIG_INTEGRITY
712fbcf3 1820static int do_bootm_integrity(int flag, int argc, char * const argv[],
f5ed9e39
PT
1821 bootm_headers_t *images)
1822{
1823 void (*entry_point)(void);
1824
5b629319 1825 if (flag != BOOTM_STATE_OS_GO)
7af26b16 1826 return 0;
49c3a861 1827
f5ed9e39
PT
1828#if defined(CONFIG_FIT)
1829 if (!images->legacy_hdr_valid) {
712fbcf3 1830 fit_unsupported_reset("INTEGRITY");
f5ed9e39
PT
1831 return 1;
1832 }
1833#endif
1834
1835 entry_point = (void (*)(void))images->ep;
1836
712fbcf3 1837 printf("## Transferring control to INTEGRITY (at address %08lx) ...\n",
f5ed9e39
PT
1838 (ulong)entry_point);
1839
770605e4 1840 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
f5ed9e39
PT
1841
1842 /*
1843 * INTEGRITY Parameters:
1844 * None
1845 */
1846 (*entry_point)();
1847
1848 return 1;
1849}
1850#endif
44f074c7
MV
1851
1852#ifdef CONFIG_CMD_BOOTZ
1853
a5266d6b 1854int __weak bootz_setup(ulong image, ulong *start, ulong *end)
44f074c7
MV
1855{
1856 /* Please define bootz_setup() for your platform */
1857
1858 puts("Your platform's zImage format isn't supported yet!\n");
1859 return -1;
1860}
44f074c7
MV
1861
1862/*
1863 * zImage booting support
1864 */
1865static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
1866 char * const argv[], bootm_headers_t *images)
1867{
1868 int ret;
a5266d6b 1869 ulong zi_start, zi_end;
44f074c7 1870
35fc84fa
SG
1871 ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
1872 images, 1);
44f074c7
MV
1873
1874 /* Setup Linux kernel zImage entry point */
2b9599e0 1875 if (!argc) {
44f074c7
MV
1876 images->ep = load_addr;
1877 debug("* kernel: default image load address = 0x%08lx\n",
1878 load_addr);
1879 } else {
2b9599e0 1880 images->ep = simple_strtoul(argv[0], NULL, 16);
44f074c7
MV
1881 debug("* kernel: cmdline image address = 0x%08lx\n",
1882 images->ep);
1883 }
1884
a5266d6b 1885 ret = bootz_setup(images->ep, &zi_start, &zi_end);
44f074c7
MV
1886 if (ret != 0)
1887 return 1;
1888
1889 lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
1890
225fd8c5
TR
1891 /*
1892 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
1893 * have a header that provide this informaiton.
1894 */
2b9599e0
TR
1895 if (bootm_find_ramdisk(flag, argc, argv))
1896 return 1;
44f074c7 1897
2b9599e0
TR
1898#if defined(CONFIG_OF_LIBFDT)
1899 if (bootm_find_fdt(flag, argc, argv))
1900 return 1;
1901#endif
1902
1903 return 0;
44f074c7
MV
1904}
1905
da620222 1906int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
44f074c7 1907{
35fc84fa 1908 int ret;
44f074c7 1909
2b9599e0
TR
1910 /* Consume 'bootz' */
1911 argc--; argv++;
1912
44f074c7
MV
1913 if (bootz_start(cmdtp, flag, argc, argv, &images))
1914 return 1;
1915
385501d3
SG
1916 /*
1917 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
1918 * disable interrupts ourselves
1919 */
1920 bootm_disable_interrupts();
1921
fb1b139b 1922 images.os.os = IH_OS_LINUX;
35fc84fa 1923 ret = do_bootm_states(cmdtp, flag, argc, argv,
fb1b139b
SG
1924 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
1925 BOOTM_STATE_OS_GO,
d0ae31eb 1926 &images, 1);
f8be7d65 1927
35fc84fa 1928 return ret;
44f074c7
MV
1929}
1930
088f1b19
KP
1931#ifdef CONFIG_SYS_LONGHELP
1932static char bootz_help_text[] =
017e1f3f
MV
1933 "[addr [initrd[:size]] [fdt]]\n"
1934 " - boot Linux zImage stored in memory\n"
44f074c7 1935 "\tThe argument 'initrd' is optional and specifies the address\n"
017e1f3f
MV
1936 "\tof the initrd in memory. The optional argument ':size' allows\n"
1937 "\tspecifying the size of RAW initrd.\n"
44f074c7
MV
1938#if defined(CONFIG_OF_LIBFDT)
1939 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
1940 "\ta third argument is required which is the address of the\n"
1941 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1942 "\tuse a '-' for the second argument. If you do not pass a third\n"
1943 "\ta bd_info struct will be passed instead\n"
1944#endif
088f1b19
KP
1945 "";
1946#endif
1947
1948U_BOOT_CMD(
1949 bootz, CONFIG_SYS_MAXARGS, 1, do_bootz,
1950 "boot Linux zImage image from memory", bootz_help_text
44f074c7
MV
1951);
1952#endif /* CONFIG_CMD_BOOTZ */