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