xref: /openbmc/u-boot/cmd/bootm.c (revision 4f1318b2)
12e192b24SSimon Glass /*
22e192b24SSimon Glass  * (C) Copyright 2000-2009
32e192b24SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
42e192b24SSimon Glass  *
52e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
62e192b24SSimon Glass  */
72e192b24SSimon Glass 
82e192b24SSimon Glass /*
92e192b24SSimon Glass  * Boot support
102e192b24SSimon Glass  */
112e192b24SSimon Glass #include <common.h>
122e192b24SSimon Glass #include <bootm.h>
132e192b24SSimon Glass #include <command.h>
142e192b24SSimon Glass #include <environment.h>
152e192b24SSimon Glass #include <errno.h>
162e192b24SSimon Glass #include <image.h>
172e192b24SSimon Glass #include <lmb.h>
182e192b24SSimon Glass #include <malloc.h>
192e192b24SSimon Glass #include <mapmem.h>
202e192b24SSimon Glass #include <nand.h>
212e192b24SSimon Glass #include <asm/byteorder.h>
222e192b24SSimon Glass #include <linux/compiler.h>
232e192b24SSimon Glass #include <linux/ctype.h>
242e192b24SSimon Glass #include <linux/err.h>
252e192b24SSimon Glass #include <u-boot/zlib.h>
262e192b24SSimon Glass 
272e192b24SSimon Glass DECLARE_GLOBAL_DATA_PTR;
282e192b24SSimon Glass 
292e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
302e192b24SSimon Glass static int image_info(unsigned long addr);
312e192b24SSimon Glass #endif
322e192b24SSimon Glass 
332e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
342e192b24SSimon Glass #include <flash.h>
352e192b24SSimon Glass #include <mtd/cfi_flash.h>
362e192b24SSimon Glass extern flash_info_t flash_info[]; /* info for FLASH chips */
372e192b24SSimon Glass #endif
382e192b24SSimon Glass 
392e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
402e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
412e192b24SSimon Glass #endif
422e192b24SSimon Glass 
432e192b24SSimon Glass bootm_headers_t images;		/* pointers to os/initrd/fdt images */
442e192b24SSimon Glass 
452e192b24SSimon Glass /* we overload the cmd field with our state machine info instead of a
462e192b24SSimon Glass  * function pointer */
472e192b24SSimon Glass static cmd_tbl_t cmd_bootm_sub[] = {
482e192b24SSimon Glass 	U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
492e192b24SSimon Glass 	U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
502e192b24SSimon Glass #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
512e192b24SSimon Glass 	U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
522e192b24SSimon Glass #endif
532e192b24SSimon Glass #ifdef CONFIG_OF_LIBFDT
542e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
552e192b24SSimon Glass #endif
562e192b24SSimon Glass 	U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
572e192b24SSimon Glass 	U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
582e192b24SSimon Glass 	U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
592e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
602e192b24SSimon Glass 	U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
612e192b24SSimon Glass };
622e192b24SSimon Glass 
632e192b24SSimon Glass static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
642e192b24SSimon Glass 			char * const argv[])
652e192b24SSimon Glass {
662e192b24SSimon Glass 	int ret = 0;
672e192b24SSimon Glass 	long state;
682e192b24SSimon Glass 	cmd_tbl_t *c;
692e192b24SSimon Glass 
702e192b24SSimon Glass 	c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
712e192b24SSimon Glass 	argc--; argv++;
722e192b24SSimon Glass 
732e192b24SSimon Glass 	if (c) {
742e192b24SSimon Glass 		state = (long)c->cmd;
752e192b24SSimon Glass 		if (state == BOOTM_STATE_START)
762e192b24SSimon Glass 			state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
772e192b24SSimon Glass 	} else {
782e192b24SSimon Glass 		/* Unrecognized command */
792e192b24SSimon Glass 		return CMD_RET_USAGE;
802e192b24SSimon Glass 	}
812e192b24SSimon Glass 
822e192b24SSimon Glass 	if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
832e192b24SSimon Glass 	    images.state >= state) {
842e192b24SSimon Glass 		printf("Trying to execute a command out of order\n");
852e192b24SSimon Glass 		return CMD_RET_USAGE;
862e192b24SSimon Glass 	}
872e192b24SSimon Glass 
882e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
892e192b24SSimon Glass 
902e192b24SSimon Glass 	return ret;
912e192b24SSimon Glass }
922e192b24SSimon Glass 
932e192b24SSimon Glass /*******************************************************************/
942e192b24SSimon Glass /* bootm - boot application image from image in memory */
952e192b24SSimon Glass /*******************************************************************/
962e192b24SSimon Glass 
972e192b24SSimon Glass int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
982e192b24SSimon Glass {
992e192b24SSimon Glass #ifdef CONFIG_NEEDS_MANUAL_RELOC
1002e192b24SSimon Glass 	static int relocated = 0;
1012e192b24SSimon Glass 
1022e192b24SSimon Glass 	if (!relocated) {
1032e192b24SSimon Glass 		int i;
1042e192b24SSimon Glass 
1052e192b24SSimon Glass 		/* relocate names of sub-command table */
1062e192b24SSimon Glass 		for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
1072e192b24SSimon Glass 			cmd_bootm_sub[i].name += gd->reloc_off;
1082e192b24SSimon Glass 
1092e192b24SSimon Glass 		relocated = 1;
1102e192b24SSimon Glass 	}
1112e192b24SSimon Glass #endif
1122e192b24SSimon Glass 
1132e192b24SSimon Glass 	/* determine if we have a sub command */
1142e192b24SSimon Glass 	argc--; argv++;
1152e192b24SSimon Glass 	if (argc > 0) {
1162e192b24SSimon Glass 		char *endp;
1172e192b24SSimon Glass 
1182e192b24SSimon Glass 		simple_strtoul(argv[0], &endp, 16);
1192e192b24SSimon Glass 		/* endp pointing to NULL means that argv[0] was just a
1202e192b24SSimon Glass 		 * valid number, pass it along to the normal bootm processing
1212e192b24SSimon Glass 		 *
1222e192b24SSimon Glass 		 * If endp is ':' or '#' assume a FIT identifier so pass
1232e192b24SSimon Glass 		 * along for normal processing.
1242e192b24SSimon Glass 		 *
1252e192b24SSimon Glass 		 * Right now we assume the first arg should never be '-'
1262e192b24SSimon Glass 		 */
1272e192b24SSimon Glass 		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
1282e192b24SSimon Glass 			return do_bootm_subcommand(cmdtp, flag, argc, argv);
1292e192b24SSimon Glass 	}
1302e192b24SSimon Glass 
1312e192b24SSimon Glass 	return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
1322e192b24SSimon Glass 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
1332e192b24SSimon Glass 		BOOTM_STATE_LOADOS |
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 
1412e192b24SSimon Glass int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
1422e192b24SSimon Glass {
1432e192b24SSimon Glass 	const char *ep = getenv("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"
1702e192b24SSimon Glass 	"\tmust be extened 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)
2052e192b24SSimon Glass int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2062e192b24SSimon Glass {
2072e192b24SSimon Glass 	return run_command(getenv("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)
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 
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
278*4f1318b2SMichael Trimarchi #if defined(CONFIG_ANDROID_BOOT_IMAGE)
279*4f1318b2SMichael Trimarchi 	case IMAGE_FORMAT_ANDROID:
280*4f1318b2SMichael Trimarchi 		puts("   Android image found\n");
281*4f1318b2SMichael Trimarchi 		android_print_contents(hdr);
282*4f1318b2SMichael Trimarchi 		return 0;
283*4f1318b2SMichael 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)
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)
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 
395151c06ecSScott Wood 	ret = nand_read_skip_bad(mtd, off, &len, 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 
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 
435151c06ecSScott Wood 	ret = nand_read_skip_bad(mtd, off, &len, 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 
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++) {
470b616d9b0SScott Wood 		mtd = nand_info[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)
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
5432e192b24SSimon Glass 
5442e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTZ
5452e192b24SSimon Glass 
5462e192b24SSimon Glass int __weak bootz_setup(ulong image, ulong *start, ulong *end)
5472e192b24SSimon Glass {
5482e192b24SSimon Glass 	/* Please define bootz_setup() for your platform */
5492e192b24SSimon Glass 
5502e192b24SSimon Glass 	puts("Your platform's zImage format isn't supported yet!\n");
5512e192b24SSimon Glass 	return -1;
5522e192b24SSimon Glass }
5532e192b24SSimon Glass 
5542e192b24SSimon Glass /*
5552e192b24SSimon Glass  * zImage booting support
5562e192b24SSimon Glass  */
5572e192b24SSimon Glass static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
5582e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
5592e192b24SSimon Glass {
5602e192b24SSimon Glass 	int ret;
5612e192b24SSimon Glass 	ulong zi_start, zi_end;
5622e192b24SSimon Glass 
5632e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
5642e192b24SSimon Glass 			      images, 1);
5652e192b24SSimon Glass 
5662e192b24SSimon Glass 	/* Setup Linux kernel zImage entry point */
5672e192b24SSimon Glass 	if (!argc) {
5682e192b24SSimon Glass 		images->ep = load_addr;
5692e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
5702e192b24SSimon Glass 				load_addr);
5712e192b24SSimon Glass 	} else {
5722e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
5732e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
5742e192b24SSimon Glass 			images->ep);
5752e192b24SSimon Glass 	}
5762e192b24SSimon Glass 
5772e192b24SSimon Glass 	ret = bootz_setup(images->ep, &zi_start, &zi_end);
5782e192b24SSimon Glass 	if (ret != 0)
5792e192b24SSimon Glass 		return 1;
5802e192b24SSimon Glass 
5812e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
5822e192b24SSimon Glass 
5832e192b24SSimon Glass 	/*
5842e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
5852e192b24SSimon Glass 	 * have a header that provide this informaiton.
5862e192b24SSimon Glass 	 */
5872e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
5882e192b24SSimon Glass 		return 1;
5892e192b24SSimon Glass 
5902e192b24SSimon Glass 	return 0;
5912e192b24SSimon Glass }
5922e192b24SSimon Glass 
5932e192b24SSimon Glass int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5942e192b24SSimon Glass {
5952e192b24SSimon Glass 	int ret;
5962e192b24SSimon Glass 
5972e192b24SSimon Glass 	/* Consume 'bootz' */
5982e192b24SSimon Glass 	argc--; argv++;
5992e192b24SSimon Glass 
6002e192b24SSimon Glass 	if (bootz_start(cmdtp, flag, argc, argv, &images))
6012e192b24SSimon Glass 		return 1;
6022e192b24SSimon Glass 
6032e192b24SSimon Glass 	/*
6042e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
6052e192b24SSimon Glass 	 * disable interrupts ourselves
6062e192b24SSimon Glass 	 */
6072e192b24SSimon Glass 	bootm_disable_interrupts();
6082e192b24SSimon Glass 
6092e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
6102e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
6112e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
6122e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
6132e192b24SSimon Glass 			      &images, 1);
6142e192b24SSimon Glass 
6152e192b24SSimon Glass 	return ret;
6162e192b24SSimon Glass }
6172e192b24SSimon Glass 
6182e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
6192e192b24SSimon Glass static char bootz_help_text[] =
6202e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
6212e192b24SSimon Glass 	"    - boot Linux zImage stored in memory\n"
6222e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
6232e192b24SSimon Glass 	"\tof the initrd in memory. The optional argument ':size' allows\n"
6242e192b24SSimon Glass 	"\tspecifying the size of RAW initrd.\n"
6252e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
6262e192b24SSimon Glass 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
6272e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
6282e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
6292e192b24SSimon Glass 	"\tuse a '-' for the second argument. If you do not pass a third\n"
6302e192b24SSimon Glass 	"\ta bd_info struct will be passed instead\n"
6312e192b24SSimon Glass #endif
6322e192b24SSimon Glass 	"";
6332e192b24SSimon Glass #endif
6342e192b24SSimon Glass 
6352e192b24SSimon Glass U_BOOT_CMD(
6362e192b24SSimon Glass 	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
6372e192b24SSimon Glass 	"boot Linux zImage image from memory", bootz_help_text
6382e192b24SSimon Glass );
6392e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTZ */
6402e192b24SSimon Glass 
6412e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTI
6422e192b24SSimon Glass /* See Documentation/arm64/booting.txt in the Linux kernel */
6432e192b24SSimon Glass struct Image_header {
6442e192b24SSimon Glass 	uint32_t	code0;		/* Executable code */
6452e192b24SSimon Glass 	uint32_t	code1;		/* Executable code */
6462e192b24SSimon Glass 	uint64_t	text_offset;	/* Image load offset, LE */
6472e192b24SSimon Glass 	uint64_t	image_size;	/* Effective Image size, LE */
6482e192b24SSimon Glass 	uint64_t	res1;		/* reserved */
6492e192b24SSimon Glass 	uint64_t	res2;		/* reserved */
6502e192b24SSimon Glass 	uint64_t	res3;		/* reserved */
6512e192b24SSimon Glass 	uint64_t	res4;		/* reserved */
6522e192b24SSimon Glass 	uint32_t	magic;		/* Magic number */
6532e192b24SSimon Glass 	uint32_t	res5;
6542e192b24SSimon Glass };
6552e192b24SSimon Glass 
6562e192b24SSimon Glass #define LINUX_ARM64_IMAGE_MAGIC	0x644d5241
6572e192b24SSimon Glass 
6582e192b24SSimon Glass static int booti_setup(bootm_headers_t *images)
6592e192b24SSimon Glass {
6602e192b24SSimon Glass 	struct Image_header *ih;
6612e192b24SSimon Glass 	uint64_t dst;
662f9a90aceSAndre Przywara 	uint64_t image_size;
6632e192b24SSimon Glass 
6642e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
6652e192b24SSimon Glass 
6662e192b24SSimon Glass 	if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
6672e192b24SSimon Glass 		puts("Bad Linux ARM64 Image magic!\n");
6682e192b24SSimon Glass 		return 1;
6692e192b24SSimon Glass 	}
6702e192b24SSimon Glass 
6712e192b24SSimon Glass 	if (ih->image_size == 0) {
6722e192b24SSimon Glass 		puts("Image lacks image_size field, assuming 16MiB\n");
673f9a90aceSAndre Przywara 		image_size = 16 << 20;
674f9a90aceSAndre Przywara 	} else {
675f9a90aceSAndre Przywara 		image_size = le64_to_cpu(ih->image_size);
6762e192b24SSimon Glass 	}
6772e192b24SSimon Glass 
6782e192b24SSimon Glass 	/*
6792e192b24SSimon Glass 	 * If we are not at the correct run-time location, set the new
6802e192b24SSimon Glass 	 * correct location and then move the image there.
6812e192b24SSimon Glass 	 */
682f9a90aceSAndre Przywara 	dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset);
68362022d52SMasahiro Yamada 
68462022d52SMasahiro Yamada 	unmap_sysmem(ih);
68562022d52SMasahiro Yamada 
6862e192b24SSimon Glass 	if (images->ep != dst) {
6872e192b24SSimon Glass 		void *src;
6882e192b24SSimon Glass 
6892e192b24SSimon Glass 		debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
6902e192b24SSimon Glass 
6912e192b24SSimon Glass 		src = (void *)images->ep;
6922e192b24SSimon Glass 		images->ep = dst;
693f9a90aceSAndre Przywara 		memmove((void *)dst, src, image_size);
6942e192b24SSimon Glass 	}
6952e192b24SSimon Glass 
6962e192b24SSimon Glass 	return 0;
6972e192b24SSimon Glass }
6982e192b24SSimon Glass 
6992e192b24SSimon Glass /*
7002e192b24SSimon Glass  * Image booting support
7012e192b24SSimon Glass  */
7022e192b24SSimon Glass static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
7032e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
7042e192b24SSimon Glass {
7052e192b24SSimon Glass 	int ret;
7062e192b24SSimon Glass 	struct Image_header *ih;
7072e192b24SSimon Glass 
7082e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
7092e192b24SSimon Glass 			      images, 1);
7102e192b24SSimon Glass 
7112e192b24SSimon Glass 	/* Setup Linux kernel Image entry point */
7122e192b24SSimon Glass 	if (!argc) {
7132e192b24SSimon Glass 		images->ep = load_addr;
7142e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
7152e192b24SSimon Glass 				load_addr);
7162e192b24SSimon Glass 	} else {
7172e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
7182e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
7192e192b24SSimon Glass 			images->ep);
7202e192b24SSimon Glass 	}
7212e192b24SSimon Glass 
7222e192b24SSimon Glass 	ret = booti_setup(images);
7232e192b24SSimon Glass 	if (ret != 0)
7242e192b24SSimon Glass 		return 1;
7252e192b24SSimon Glass 
7262e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
7272e192b24SSimon Glass 
7282e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
7292e192b24SSimon Glass 
73062022d52SMasahiro Yamada 	unmap_sysmem(ih);
73162022d52SMasahiro Yamada 
7322e192b24SSimon Glass 	/*
7332e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
7342e192b24SSimon Glass 	 * have a header that provide this informaiton.
7352e192b24SSimon Glass 	 */
7362e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
7372e192b24SSimon Glass 		return 1;
7382e192b24SSimon Glass 
7392e192b24SSimon Glass 	return 0;
7402e192b24SSimon Glass }
7412e192b24SSimon Glass 
7422e192b24SSimon Glass int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7432e192b24SSimon Glass {
7442e192b24SSimon Glass 	int ret;
7452e192b24SSimon Glass 
7462e192b24SSimon Glass 	/* Consume 'booti' */
7472e192b24SSimon Glass 	argc--; argv++;
7482e192b24SSimon Glass 
7492e192b24SSimon Glass 	if (booti_start(cmdtp, flag, argc, argv, &images))
7502e192b24SSimon Glass 		return 1;
7512e192b24SSimon Glass 
7522e192b24SSimon Glass 	/*
7532e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
7542e192b24SSimon Glass 	 * disable interrupts ourselves
7552e192b24SSimon Glass 	 */
7562e192b24SSimon Glass 	bootm_disable_interrupts();
7572e192b24SSimon Glass 
7582e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
7592e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
7602e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
7612e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
7622e192b24SSimon Glass 			      &images, 1);
7632e192b24SSimon Glass 
7642e192b24SSimon Glass 	return ret;
7652e192b24SSimon Glass }
7662e192b24SSimon Glass 
7672e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
7682e192b24SSimon Glass static char booti_help_text[] =
7692e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
7706f6051faSKarsten Merker 	"    - boot arm64 Linux Image stored in memory\n"
7712e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
7726f6051faSKarsten Merker 	"\tof an initrd in memory. The optional parameter ':size' allows\n"
7736f6051faSKarsten Merker 	"\tspecifying the size of a RAW initrd.\n"
7742e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
7756f6051faSKarsten Merker 	"\tSince booting a Linux kernel requires a flat device-tree, a\n"
7766f6051faSKarsten Merker 	"\tthird argument providing the address of the device-tree blob\n"
7776f6051faSKarsten Merker 	"\tis required. To boot a kernel with a device-tree blob but\n"
7786f6051faSKarsten Merker 	"\twithout an initrd image, use a '-' for the initrd argument.\n"
7792e192b24SSimon Glass #endif
7802e192b24SSimon Glass 	"";
7812e192b24SSimon Glass #endif
7822e192b24SSimon Glass 
7832e192b24SSimon Glass U_BOOT_CMD(
7842e192b24SSimon Glass 	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
7852e192b24SSimon Glass 	"boot arm64 Linux Image image from memory", booti_help_text
7862e192b24SSimon Glass );
7872e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTI */
788