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