xref: /openbmc/u-boot/cmd/bootm.c (revision 2502bfc4)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass  * (C) Copyright 2000-2009
42e192b24SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
52e192b24SSimon Glass  */
62e192b24SSimon Glass 
72e192b24SSimon Glass /*
82e192b24SSimon Glass  * Boot support
92e192b24SSimon Glass  */
102e192b24SSimon Glass #include <common.h>
112e192b24SSimon Glass #include <bootm.h>
122e192b24SSimon Glass #include <command.h>
132e192b24SSimon Glass #include <environment.h>
142e192b24SSimon Glass #include <errno.h>
152e192b24SSimon Glass #include <image.h>
162e192b24SSimon Glass #include <malloc.h>
172e192b24SSimon Glass #include <nand.h>
182e192b24SSimon Glass #include <asm/byteorder.h>
192e192b24SSimon Glass #include <linux/ctype.h>
202e192b24SSimon Glass #include <linux/err.h>
212e192b24SSimon Glass #include <u-boot/zlib.h>
222e192b24SSimon Glass 
232e192b24SSimon Glass DECLARE_GLOBAL_DATA_PTR;
242e192b24SSimon Glass 
252e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
262e192b24SSimon Glass static int image_info(unsigned long addr);
272e192b24SSimon Glass #endif
282e192b24SSimon Glass 
292e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
302e192b24SSimon Glass #include <flash.h>
312e192b24SSimon Glass #include <mtd/cfi_flash.h>
322e192b24SSimon Glass extern flash_info_t flash_info[]; /* info for FLASH chips */
332e192b24SSimon Glass #endif
342e192b24SSimon Glass 
352e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
362e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
372e192b24SSimon Glass #endif
382e192b24SSimon Glass 
392e192b24SSimon Glass /* we overload the cmd field with our state machine info instead of a
402e192b24SSimon Glass  * function pointer */
412e192b24SSimon Glass static cmd_tbl_t cmd_bootm_sub[] = {
422e192b24SSimon Glass 	U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
432e192b24SSimon Glass 	U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
442e192b24SSimon Glass #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
452e192b24SSimon Glass 	U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
462e192b24SSimon Glass #endif
472e192b24SSimon Glass #ifdef CONFIG_OF_LIBFDT
482e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
492e192b24SSimon Glass #endif
502e192b24SSimon Glass 	U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
512e192b24SSimon Glass 	U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
522e192b24SSimon Glass 	U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
532e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
542e192b24SSimon Glass 	U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
552e192b24SSimon Glass };
562e192b24SSimon Glass 
do_bootm_subcommand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])572e192b24SSimon Glass static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
582e192b24SSimon Glass 			char * const argv[])
592e192b24SSimon Glass {
602e192b24SSimon Glass 	int ret = 0;
612e192b24SSimon Glass 	long state;
622e192b24SSimon Glass 	cmd_tbl_t *c;
632e192b24SSimon Glass 
642e192b24SSimon Glass 	c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
652e192b24SSimon Glass 	argc--; argv++;
662e192b24SSimon Glass 
672e192b24SSimon Glass 	if (c) {
682e192b24SSimon Glass 		state = (long)c->cmd;
692e192b24SSimon Glass 		if (state == BOOTM_STATE_START)
702e192b24SSimon Glass 			state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
712e192b24SSimon Glass 	} else {
722e192b24SSimon Glass 		/* Unrecognized command */
732e192b24SSimon Glass 		return CMD_RET_USAGE;
742e192b24SSimon Glass 	}
752e192b24SSimon Glass 
762e192b24SSimon Glass 	if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
772e192b24SSimon Glass 	    images.state >= state) {
782e192b24SSimon Glass 		printf("Trying to execute a command out of order\n");
792e192b24SSimon Glass 		return CMD_RET_USAGE;
802e192b24SSimon Glass 	}
812e192b24SSimon Glass 
822e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
832e192b24SSimon Glass 
842e192b24SSimon Glass 	return ret;
852e192b24SSimon Glass }
862e192b24SSimon Glass 
872e192b24SSimon Glass /*******************************************************************/
882e192b24SSimon Glass /* bootm - boot application image from image in memory */
892e192b24SSimon Glass /*******************************************************************/
902e192b24SSimon Glass 
do_bootm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])912e192b24SSimon Glass int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
922e192b24SSimon Glass {
932e192b24SSimon Glass #ifdef CONFIG_NEEDS_MANUAL_RELOC
942e192b24SSimon Glass 	static int relocated = 0;
952e192b24SSimon Glass 
962e192b24SSimon Glass 	if (!relocated) {
972e192b24SSimon Glass 		int i;
982e192b24SSimon Glass 
992e192b24SSimon Glass 		/* relocate names of sub-command table */
1002e192b24SSimon Glass 		for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
1012e192b24SSimon Glass 			cmd_bootm_sub[i].name += gd->reloc_off;
1022e192b24SSimon Glass 
1032e192b24SSimon Glass 		relocated = 1;
1042e192b24SSimon Glass 	}
1052e192b24SSimon Glass #endif
1062e192b24SSimon Glass 
1072e192b24SSimon Glass 	/* determine if we have a sub command */
1082e192b24SSimon Glass 	argc--; argv++;
1092e192b24SSimon Glass 	if (argc > 0) {
1102e192b24SSimon Glass 		char *endp;
1112e192b24SSimon Glass 
1122e192b24SSimon Glass 		simple_strtoul(argv[0], &endp, 16);
1132e192b24SSimon Glass 		/* endp pointing to NULL means that argv[0] was just a
1142e192b24SSimon Glass 		 * valid number, pass it along to the normal bootm processing
1152e192b24SSimon Glass 		 *
1162e192b24SSimon Glass 		 * If endp is ':' or '#' assume a FIT identifier so pass
1172e192b24SSimon Glass 		 * along for normal processing.
1182e192b24SSimon Glass 		 *
1192e192b24SSimon Glass 		 * Right now we assume the first arg should never be '-'
1202e192b24SSimon Glass 		 */
1212e192b24SSimon Glass 		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
1222e192b24SSimon Glass 			return do_bootm_subcommand(cmdtp, flag, argc, argv);
1232e192b24SSimon Glass 	}
1242e192b24SSimon Glass 
1252e192b24SSimon Glass 	return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
1262e192b24SSimon Glass 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
1272e192b24SSimon Glass 		BOOTM_STATE_LOADOS |
128c2e7e72bSRick Altherr #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
129c2e7e72bSRick Altherr 		BOOTM_STATE_RAMDISK |
130c2e7e72bSRick Altherr #endif
131*2502bfc4SEddie James #ifdef CONFIG_MEASURED_BOOT
132*2502bfc4SEddie James 		BOOTM_STATE_MEASURE |
133*2502bfc4SEddie James #endif
1342e192b24SSimon Glass #if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
1352e192b24SSimon Glass 		BOOTM_STATE_OS_CMDLINE |
1362e192b24SSimon Glass #endif
1372e192b24SSimon Glass 		BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
1382e192b24SSimon Glass 		BOOTM_STATE_OS_GO, &images, 1);
1392e192b24SSimon Glass }
1402e192b24SSimon Glass 
bootm_maybe_autostart(cmd_tbl_t * cmdtp,const char * cmd)1412e192b24SSimon Glass int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
1422e192b24SSimon Glass {
14300caae6dSSimon Glass 	const char *ep = env_get("autostart");
1442e192b24SSimon Glass 
1452e192b24SSimon Glass 	if (ep && !strcmp(ep, "yes")) {
1462e192b24SSimon Glass 		char *local_args[2];
1472e192b24SSimon Glass 		local_args[0] = (char *)cmd;
1482e192b24SSimon Glass 		local_args[1] = NULL;
1492e192b24SSimon Glass 		printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
1502e192b24SSimon Glass 		return do_bootm(cmdtp, 0, 1, local_args);
1512e192b24SSimon Glass 	}
1522e192b24SSimon Glass 
1532e192b24SSimon Glass 	return 0;
1542e192b24SSimon Glass }
1552e192b24SSimon Glass 
1562e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
1572e192b24SSimon Glass static char bootm_help_text[] =
1582e192b24SSimon Glass 	"[addr [arg ...]]\n    - boot application image stored in memory\n"
1592e192b24SSimon Glass 	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
1602e192b24SSimon Glass 	"\t'arg' can be the address of an initrd image\n"
1612e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
1622e192b24SSimon Glass 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
1632e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
1642e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1652e192b24SSimon Glass 	"\tuse a '-' for the second argument. If you do not pass a third\n"
1662e192b24SSimon Glass 	"\ta bd_info struct will be passed instead\n"
1672e192b24SSimon Glass #endif
1682e192b24SSimon Glass #if defined(CONFIG_FIT)
1692e192b24SSimon Glass 	"\t\nFor the new multi component uImage format (FIT) addresses\n"
170da1a3bd4SVagrant Cascadian 	"\tmust be extended to include component or configuration unit name:\n"
1712e192b24SSimon Glass 	"\taddr:<subimg_uname> - direct component image specification\n"
1722e192b24SSimon Glass 	"\taddr#<conf_uname>   - configuration specification\n"
1732e192b24SSimon Glass 	"\tUse iminfo command to get the list of existing component\n"
1742e192b24SSimon Glass 	"\timages and configurations.\n"
1752e192b24SSimon Glass #endif
1762e192b24SSimon Glass 	"\nSub-commands to do part of the bootm sequence.  The sub-commands "
1772e192b24SSimon Glass 	"must be\n"
1782e192b24SSimon Glass 	"issued in the order below (it's ok to not issue all sub-commands):\n"
1792e192b24SSimon Glass 	"\tstart [addr [arg ...]]\n"
1802e192b24SSimon Glass 	"\tloados  - load OS image\n"
1812e192b24SSimon Glass #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
1822e192b24SSimon Glass 	"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
1832e192b24SSimon Glass #endif
1842e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
1852e192b24SSimon Glass 	"\tfdt     - relocate flat device tree\n"
1862e192b24SSimon Glass #endif
1872e192b24SSimon Glass 	"\tcmdline - OS specific command line processing/setup\n"
1882e192b24SSimon Glass 	"\tbdt     - OS specific bd_t processing\n"
1892e192b24SSimon Glass 	"\tprep    - OS specific prep before relocation or go\n"
1902e192b24SSimon Glass #if defined(CONFIG_TRACE)
1912e192b24SSimon Glass 	"\tfake    - OS specific fake start without go\n"
1922e192b24SSimon Glass #endif
1932e192b24SSimon Glass 	"\tgo      - start OS";
1942e192b24SSimon Glass #endif
1952e192b24SSimon Glass 
1962e192b24SSimon Glass U_BOOT_CMD(
1972e192b24SSimon Glass 	bootm,	CONFIG_SYS_MAXARGS,	1,	do_bootm,
1982e192b24SSimon Glass 	"boot application image from memory", bootm_help_text
1992e192b24SSimon Glass );
2002e192b24SSimon Glass 
2012e192b24SSimon Glass /*******************************************************************/
2022e192b24SSimon Glass /* bootd - boot default image */
2032e192b24SSimon Glass /*******************************************************************/
2042e192b24SSimon Glass #if defined(CONFIG_CMD_BOOTD)
do_bootd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2052e192b24SSimon Glass int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2062e192b24SSimon Glass {
20700caae6dSSimon Glass 	return run_command(env_get("bootcmd"), flag);
2082e192b24SSimon Glass }
2092e192b24SSimon Glass 
2102e192b24SSimon Glass U_BOOT_CMD(
2112e192b24SSimon Glass 	boot,	1,	1,	do_bootd,
2122e192b24SSimon Glass 	"boot default, i.e., run 'bootcmd'",
2132e192b24SSimon Glass 	""
2142e192b24SSimon Glass );
2152e192b24SSimon Glass 
2162e192b24SSimon Glass /* keep old command name "bootd" for backward compatibility */
2172e192b24SSimon Glass U_BOOT_CMD(
2182e192b24SSimon Glass 	bootd, 1,	1,	do_bootd,
2192e192b24SSimon Glass 	"boot default, i.e., run 'bootcmd'",
2202e192b24SSimon Glass 	""
2212e192b24SSimon Glass );
2222e192b24SSimon Glass 
2232e192b24SSimon Glass #endif
2242e192b24SSimon Glass 
2252e192b24SSimon Glass 
2262e192b24SSimon Glass /*******************************************************************/
2272e192b24SSimon Glass /* iminfo - print header info for a requested image */
2282e192b24SSimon Glass /*******************************************************************/
2292e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
do_iminfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2302e192b24SSimon Glass static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2312e192b24SSimon Glass {
2322e192b24SSimon Glass 	int	arg;
2332e192b24SSimon Glass 	ulong	addr;
2342e192b24SSimon Glass 	int	rcode = 0;
2352e192b24SSimon Glass 
2362e192b24SSimon Glass 	if (argc < 2) {
2372e192b24SSimon Glass 		return image_info(load_addr);
2382e192b24SSimon Glass 	}
2392e192b24SSimon Glass 
2402e192b24SSimon Glass 	for (arg = 1; arg < argc; ++arg) {
2412e192b24SSimon Glass 		addr = simple_strtoul(argv[arg], NULL, 16);
2422e192b24SSimon Glass 		if (image_info(addr) != 0)
2432e192b24SSimon Glass 			rcode = 1;
2442e192b24SSimon Glass 	}
2452e192b24SSimon Glass 	return rcode;
2462e192b24SSimon Glass }
2472e192b24SSimon Glass 
image_info(ulong addr)2482e192b24SSimon Glass static int image_info(ulong addr)
2492e192b24SSimon Glass {
2502e192b24SSimon Glass 	void *hdr = (void *)addr;
2512e192b24SSimon Glass 
2522e192b24SSimon Glass 	printf("\n## Checking Image at %08lx ...\n", addr);
2532e192b24SSimon Glass 
2542e192b24SSimon Glass 	switch (genimg_get_format(hdr)) {
2552e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
2562e192b24SSimon Glass 	case IMAGE_FORMAT_LEGACY:
2572e192b24SSimon Glass 		puts("   Legacy image found\n");
2582e192b24SSimon Glass 		if (!image_check_magic(hdr)) {
2592e192b24SSimon Glass 			puts("   Bad Magic Number\n");
2602e192b24SSimon Glass 			return 1;
2612e192b24SSimon Glass 		}
2622e192b24SSimon Glass 
2632e192b24SSimon Glass 		if (!image_check_hcrc(hdr)) {
2642e192b24SSimon Glass 			puts("   Bad Header Checksum\n");
2652e192b24SSimon Glass 			return 1;
2662e192b24SSimon Glass 		}
2672e192b24SSimon Glass 
2682e192b24SSimon Glass 		image_print_contents(hdr);
2692e192b24SSimon Glass 
2702e192b24SSimon Glass 		puts("   Verifying Checksum ... ");
2712e192b24SSimon Glass 		if (!image_check_dcrc(hdr)) {
2722e192b24SSimon Glass 			puts("   Bad Data CRC\n");
2732e192b24SSimon Glass 			return 1;
2742e192b24SSimon Glass 		}
2752e192b24SSimon Glass 		puts("OK\n");
2762e192b24SSimon Glass 		return 0;
2772e192b24SSimon Glass #endif
2784f1318b2SMichael Trimarchi #if defined(CONFIG_ANDROID_BOOT_IMAGE)
2794f1318b2SMichael Trimarchi 	case IMAGE_FORMAT_ANDROID:
2804f1318b2SMichael Trimarchi 		puts("   Android image found\n");
2814f1318b2SMichael Trimarchi 		android_print_contents(hdr);
2824f1318b2SMichael Trimarchi 		return 0;
2834f1318b2SMichael Trimarchi #endif
2842e192b24SSimon Glass #if defined(CONFIG_FIT)
2852e192b24SSimon Glass 	case IMAGE_FORMAT_FIT:
2862e192b24SSimon Glass 		puts("   FIT image found\n");
2872e192b24SSimon Glass 
2882e192b24SSimon Glass 		if (!fit_check_format(hdr)) {
2892e192b24SSimon Glass 			puts("Bad FIT image format!\n");
2902e192b24SSimon Glass 			return 1;
2912e192b24SSimon Glass 		}
2922e192b24SSimon Glass 
2932e192b24SSimon Glass 		fit_print_contents(hdr);
2942e192b24SSimon Glass 
2952e192b24SSimon Glass 		if (!fit_all_image_verify(hdr)) {
2962e192b24SSimon Glass 			puts("Bad hash in FIT image!\n");
2972e192b24SSimon Glass 			return 1;
2982e192b24SSimon Glass 		}
2992e192b24SSimon Glass 
3002e192b24SSimon Glass 		return 0;
3012e192b24SSimon Glass #endif
3022e192b24SSimon Glass 	default:
3032e192b24SSimon Glass 		puts("Unknown image format!\n");
3042e192b24SSimon Glass 		break;
3052e192b24SSimon Glass 	}
3062e192b24SSimon Glass 
3072e192b24SSimon Glass 	return 1;
3082e192b24SSimon Glass }
3092e192b24SSimon Glass 
3102e192b24SSimon Glass U_BOOT_CMD(
3112e192b24SSimon Glass 	iminfo,	CONFIG_SYS_MAXARGS,	1,	do_iminfo,
3122e192b24SSimon Glass 	"print header information for application image",
3132e192b24SSimon Glass 	"addr [addr ...]\n"
3142e192b24SSimon Glass 	"    - print header information for application image starting at\n"
3152e192b24SSimon Glass 	"      address 'addr' in memory; this includes verification of the\n"
3162e192b24SSimon Glass 	"      image contents (magic number, header and payload checksums)"
3172e192b24SSimon Glass );
3182e192b24SSimon Glass #endif
3192e192b24SSimon Glass 
3202e192b24SSimon Glass 
3212e192b24SSimon Glass /*******************************************************************/
3222e192b24SSimon Glass /* imls - list all images found in flash */
3232e192b24SSimon Glass /*******************************************************************/
3242e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
do_imls_nor(void)3252e192b24SSimon Glass static int do_imls_nor(void)
3262e192b24SSimon Glass {
3272e192b24SSimon Glass 	flash_info_t *info;
3282e192b24SSimon Glass 	int i, j;
3292e192b24SSimon Glass 	void *hdr;
3302e192b24SSimon Glass 
3312e192b24SSimon Glass 	for (i = 0, info = &flash_info[0];
3322e192b24SSimon Glass 		i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
3332e192b24SSimon Glass 
3342e192b24SSimon Glass 		if (info->flash_id == FLASH_UNKNOWN)
3352e192b24SSimon Glass 			goto next_bank;
3362e192b24SSimon Glass 		for (j = 0; j < info->sector_count; ++j) {
3372e192b24SSimon Glass 
3382e192b24SSimon Glass 			hdr = (void *)info->start[j];
3392e192b24SSimon Glass 			if (!hdr)
3402e192b24SSimon Glass 				goto next_sector;
3412e192b24SSimon Glass 
3422e192b24SSimon Glass 			switch (genimg_get_format(hdr)) {
3432e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
3442e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
3452e192b24SSimon Glass 				if (!image_check_hcrc(hdr))
3462e192b24SSimon Glass 					goto next_sector;
3472e192b24SSimon Glass 
3482e192b24SSimon Glass 				printf("Legacy Image at %08lX:\n", (ulong)hdr);
3492e192b24SSimon Glass 				image_print_contents(hdr);
3502e192b24SSimon Glass 
3512e192b24SSimon Glass 				puts("   Verifying Checksum ... ");
3522e192b24SSimon Glass 				if (!image_check_dcrc(hdr)) {
3532e192b24SSimon Glass 					puts("Bad Data CRC\n");
3542e192b24SSimon Glass 				} else {
3552e192b24SSimon Glass 					puts("OK\n");
3562e192b24SSimon Glass 				}
3572e192b24SSimon Glass 				break;
3582e192b24SSimon Glass #endif
3592e192b24SSimon Glass #if defined(CONFIG_FIT)
3602e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
3612e192b24SSimon Glass 				if (!fit_check_format(hdr))
3622e192b24SSimon Glass 					goto next_sector;
3632e192b24SSimon Glass 
3642e192b24SSimon Glass 				printf("FIT Image at %08lX:\n", (ulong)hdr);
3652e192b24SSimon Glass 				fit_print_contents(hdr);
3662e192b24SSimon Glass 				break;
3672e192b24SSimon Glass #endif
3682e192b24SSimon Glass 			default:
3692e192b24SSimon Glass 				goto next_sector;
3702e192b24SSimon Glass 			}
3712e192b24SSimon Glass 
3722e192b24SSimon Glass next_sector:		;
3732e192b24SSimon Glass 		}
3742e192b24SSimon Glass next_bank:	;
3752e192b24SSimon Glass 	}
3762e192b24SSimon Glass 	return 0;
3772e192b24SSimon Glass }
3782e192b24SSimon Glass #endif
3792e192b24SSimon Glass 
3802e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
nand_imls_legacyimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)381151c06ecSScott Wood static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
382151c06ecSScott Wood 				 loff_t off, size_t len)
3832e192b24SSimon Glass {
3842e192b24SSimon Glass 	void *imgdata;
3852e192b24SSimon Glass 	int ret;
3862e192b24SSimon Glass 
3872e192b24SSimon Glass 	imgdata = malloc(len);
3882e192b24SSimon Glass 	if (!imgdata) {
3892e192b24SSimon Glass 		printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
3902e192b24SSimon Glass 				nand_dev, off);
3912e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
3922e192b24SSimon Glass 		return -ENOMEM;
3932e192b24SSimon Glass 	}
3942e192b24SSimon Glass 
395dbe7881dSGrygorii Strashko 	ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
3962e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
3972e192b24SSimon Glass 		free(imgdata);
3982e192b24SSimon Glass 		return ret;
3992e192b24SSimon Glass 	}
4002e192b24SSimon Glass 
4012e192b24SSimon Glass 	if (!image_check_hcrc(imgdata)) {
4022e192b24SSimon Glass 		free(imgdata);
4032e192b24SSimon Glass 		return 0;
4042e192b24SSimon Glass 	}
4052e192b24SSimon Glass 
4062e192b24SSimon Glass 	printf("Legacy Image at NAND device %d offset %08llX:\n",
4072e192b24SSimon Glass 			nand_dev, off);
4082e192b24SSimon Glass 	image_print_contents(imgdata);
4092e192b24SSimon Glass 
4102e192b24SSimon Glass 	puts("   Verifying Checksum ... ");
4112e192b24SSimon Glass 	if (!image_check_dcrc(imgdata))
4122e192b24SSimon Glass 		puts("Bad Data CRC\n");
4132e192b24SSimon Glass 	else
4142e192b24SSimon Glass 		puts("OK\n");
4152e192b24SSimon Glass 
4162e192b24SSimon Glass 	free(imgdata);
4172e192b24SSimon Glass 
4182e192b24SSimon Glass 	return 0;
4192e192b24SSimon Glass }
4202e192b24SSimon Glass 
nand_imls_fitimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)421151c06ecSScott Wood static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
4222e192b24SSimon Glass 			      size_t len)
4232e192b24SSimon Glass {
4242e192b24SSimon Glass 	void *imgdata;
4252e192b24SSimon Glass 	int ret;
4262e192b24SSimon Glass 
4272e192b24SSimon Glass 	imgdata = malloc(len);
4282e192b24SSimon Glass 	if (!imgdata) {
4292e192b24SSimon Glass 		printf("May be a FIT Image at NAND device %d offset %08llX:\n",
4302e192b24SSimon Glass 				nand_dev, off);
4312e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
4322e192b24SSimon Glass 		return -ENOMEM;
4332e192b24SSimon Glass 	}
4342e192b24SSimon Glass 
435dbe7881dSGrygorii Strashko 	ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
4362e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
4372e192b24SSimon Glass 		free(imgdata);
4382e192b24SSimon Glass 		return ret;
4392e192b24SSimon Glass 	}
4402e192b24SSimon Glass 
4412e192b24SSimon Glass 	if (!fit_check_format(imgdata)) {
4422e192b24SSimon Glass 		free(imgdata);
4432e192b24SSimon Glass 		return 0;
4442e192b24SSimon Glass 	}
4452e192b24SSimon Glass 
4462e192b24SSimon Glass 	printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
4472e192b24SSimon Glass 
4482e192b24SSimon Glass 	fit_print_contents(imgdata);
4492e192b24SSimon Glass 	free(imgdata);
4502e192b24SSimon Glass 
4512e192b24SSimon Glass 	return 0;
4522e192b24SSimon Glass }
4532e192b24SSimon Glass 
do_imls_nand(void)4542e192b24SSimon Glass static int do_imls_nand(void)
4552e192b24SSimon Glass {
456151c06ecSScott Wood 	struct mtd_info *mtd;
4572e192b24SSimon Glass 	int nand_dev = nand_curr_device;
4582e192b24SSimon Glass 	size_t len;
4592e192b24SSimon Glass 	loff_t off;
4602e192b24SSimon Glass 	u32 buffer[16];
4612e192b24SSimon Glass 
4622e192b24SSimon Glass 	if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
4632e192b24SSimon Glass 		puts("\nNo NAND devices available\n");
4642e192b24SSimon Glass 		return -ENODEV;
4652e192b24SSimon Glass 	}
4662e192b24SSimon Glass 
4672e192b24SSimon Glass 	printf("\n");
4682e192b24SSimon Glass 
4692e192b24SSimon Glass 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
470f370b515SGrygorii Strashko 		mtd = get_nand_dev_by_index(nand_dev);
471151c06ecSScott Wood 		if (!mtd->name || !mtd->size)
4722e192b24SSimon Glass 			continue;
4732e192b24SSimon Glass 
474151c06ecSScott Wood 		for (off = 0; off < mtd->size; off += mtd->erasesize) {
4752e192b24SSimon Glass 			const image_header_t *header;
4762e192b24SSimon Glass 			int ret;
4772e192b24SSimon Glass 
478151c06ecSScott Wood 			if (nand_block_isbad(mtd, off))
4792e192b24SSimon Glass 				continue;
4802e192b24SSimon Glass 
4812e192b24SSimon Glass 			len = sizeof(buffer);
4822e192b24SSimon Glass 
483151c06ecSScott Wood 			ret = nand_read(mtd, off, &len, (u8 *)buffer);
4842e192b24SSimon Glass 			if (ret < 0 && ret != -EUCLEAN) {
4852e192b24SSimon Glass 				printf("NAND read error %d at offset %08llX\n",
4862e192b24SSimon Glass 						ret, off);
4872e192b24SSimon Glass 				continue;
4882e192b24SSimon Glass 			}
4892e192b24SSimon Glass 
4902e192b24SSimon Glass 			switch (genimg_get_format(buffer)) {
4912e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
4922e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
4932e192b24SSimon Glass 				header = (const image_header_t *)buffer;
4942e192b24SSimon Glass 
4952e192b24SSimon Glass 				len = image_get_image_size(header);
496151c06ecSScott Wood 				nand_imls_legacyimage(mtd, nand_dev, off, len);
4972e192b24SSimon Glass 				break;
4982e192b24SSimon Glass #endif
4992e192b24SSimon Glass #if defined(CONFIG_FIT)
5002e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
5012e192b24SSimon Glass 				len = fit_get_size(buffer);
502151c06ecSScott Wood 				nand_imls_fitimage(mtd, nand_dev, off, len);
5032e192b24SSimon Glass 				break;
5042e192b24SSimon Glass #endif
5052e192b24SSimon Glass 			}
5062e192b24SSimon Glass 		}
5072e192b24SSimon Glass 	}
5082e192b24SSimon Glass 
5092e192b24SSimon Glass 	return 0;
5102e192b24SSimon Glass }
5112e192b24SSimon Glass #endif
5122e192b24SSimon Glass 
5132e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
do_imls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])5142e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5152e192b24SSimon Glass {
5162e192b24SSimon Glass 	int ret_nor = 0, ret_nand = 0;
5172e192b24SSimon Glass 
5182e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
5192e192b24SSimon Glass 	ret_nor = do_imls_nor();
5202e192b24SSimon Glass #endif
5212e192b24SSimon Glass 
5222e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
5232e192b24SSimon Glass 	ret_nand = do_imls_nand();
5242e192b24SSimon Glass #endif
5252e192b24SSimon Glass 
5262e192b24SSimon Glass 	if (ret_nor)
5272e192b24SSimon Glass 		return ret_nor;
5282e192b24SSimon Glass 
5292e192b24SSimon Glass 	if (ret_nand)
5302e192b24SSimon Glass 		return ret_nand;
5312e192b24SSimon Glass 
5322e192b24SSimon Glass 	return (0);
5332e192b24SSimon Glass }
5342e192b24SSimon Glass 
5352e192b24SSimon Glass U_BOOT_CMD(
5362e192b24SSimon Glass 	imls,	1,		1,	do_imls,
5372e192b24SSimon Glass 	"list all images found in flash",
5382e192b24SSimon Glass 	"\n"
5392e192b24SSimon Glass 	"    - Prints information about all images found at sector/block\n"
5402e192b24SSimon Glass 	"      boundaries in nor/nand flash."
5412e192b24SSimon Glass );
5422e192b24SSimon Glass #endif
543