xref: /rk3399_rockchip-uboot/cmd/bootm.c (revision 6f6051fac360cf6ca88cfcfa3cb377778ef5742c)
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
2782e192b24SSimon Glass #if defined(CONFIG_FIT)
2792e192b24SSimon Glass 	case IMAGE_FORMAT_FIT:
2802e192b24SSimon Glass 		puts("   FIT image found\n");
2812e192b24SSimon Glass 
2822e192b24SSimon Glass 		if (!fit_check_format(hdr)) {
2832e192b24SSimon Glass 			puts("Bad FIT image format!\n");
2842e192b24SSimon Glass 			return 1;
2852e192b24SSimon Glass 		}
2862e192b24SSimon Glass 
2872e192b24SSimon Glass 		fit_print_contents(hdr);
2882e192b24SSimon Glass 
2892e192b24SSimon Glass 		if (!fit_all_image_verify(hdr)) {
2902e192b24SSimon Glass 			puts("Bad hash in FIT image!\n");
2912e192b24SSimon Glass 			return 1;
2922e192b24SSimon Glass 		}
2932e192b24SSimon Glass 
2942e192b24SSimon Glass 		return 0;
2952e192b24SSimon Glass #endif
2962e192b24SSimon Glass 	default:
2972e192b24SSimon Glass 		puts("Unknown image format!\n");
2982e192b24SSimon Glass 		break;
2992e192b24SSimon Glass 	}
3002e192b24SSimon Glass 
3012e192b24SSimon Glass 	return 1;
3022e192b24SSimon Glass }
3032e192b24SSimon Glass 
3042e192b24SSimon Glass U_BOOT_CMD(
3052e192b24SSimon Glass 	iminfo,	CONFIG_SYS_MAXARGS,	1,	do_iminfo,
3062e192b24SSimon Glass 	"print header information for application image",
3072e192b24SSimon Glass 	"addr [addr ...]\n"
3082e192b24SSimon Glass 	"    - print header information for application image starting at\n"
3092e192b24SSimon Glass 	"      address 'addr' in memory; this includes verification of the\n"
3102e192b24SSimon Glass 	"      image contents (magic number, header and payload checksums)"
3112e192b24SSimon Glass );
3122e192b24SSimon Glass #endif
3132e192b24SSimon Glass 
3142e192b24SSimon Glass 
3152e192b24SSimon Glass /*******************************************************************/
3162e192b24SSimon Glass /* imls - list all images found in flash */
3172e192b24SSimon Glass /*******************************************************************/
3182e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
3192e192b24SSimon Glass static int do_imls_nor(void)
3202e192b24SSimon Glass {
3212e192b24SSimon Glass 	flash_info_t *info;
3222e192b24SSimon Glass 	int i, j;
3232e192b24SSimon Glass 	void *hdr;
3242e192b24SSimon Glass 
3252e192b24SSimon Glass 	for (i = 0, info = &flash_info[0];
3262e192b24SSimon Glass 		i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
3272e192b24SSimon Glass 
3282e192b24SSimon Glass 		if (info->flash_id == FLASH_UNKNOWN)
3292e192b24SSimon Glass 			goto next_bank;
3302e192b24SSimon Glass 		for (j = 0; j < info->sector_count; ++j) {
3312e192b24SSimon Glass 
3322e192b24SSimon Glass 			hdr = (void *)info->start[j];
3332e192b24SSimon Glass 			if (!hdr)
3342e192b24SSimon Glass 				goto next_sector;
3352e192b24SSimon Glass 
3362e192b24SSimon Glass 			switch (genimg_get_format(hdr)) {
3372e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
3382e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
3392e192b24SSimon Glass 				if (!image_check_hcrc(hdr))
3402e192b24SSimon Glass 					goto next_sector;
3412e192b24SSimon Glass 
3422e192b24SSimon Glass 				printf("Legacy Image at %08lX:\n", (ulong)hdr);
3432e192b24SSimon Glass 				image_print_contents(hdr);
3442e192b24SSimon Glass 
3452e192b24SSimon Glass 				puts("   Verifying Checksum ... ");
3462e192b24SSimon Glass 				if (!image_check_dcrc(hdr)) {
3472e192b24SSimon Glass 					puts("Bad Data CRC\n");
3482e192b24SSimon Glass 				} else {
3492e192b24SSimon Glass 					puts("OK\n");
3502e192b24SSimon Glass 				}
3512e192b24SSimon Glass 				break;
3522e192b24SSimon Glass #endif
3532e192b24SSimon Glass #if defined(CONFIG_FIT)
3542e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
3552e192b24SSimon Glass 				if (!fit_check_format(hdr))
3562e192b24SSimon Glass 					goto next_sector;
3572e192b24SSimon Glass 
3582e192b24SSimon Glass 				printf("FIT Image at %08lX:\n", (ulong)hdr);
3592e192b24SSimon Glass 				fit_print_contents(hdr);
3602e192b24SSimon Glass 				break;
3612e192b24SSimon Glass #endif
3622e192b24SSimon Glass 			default:
3632e192b24SSimon Glass 				goto next_sector;
3642e192b24SSimon Glass 			}
3652e192b24SSimon Glass 
3662e192b24SSimon Glass next_sector:		;
3672e192b24SSimon Glass 		}
3682e192b24SSimon Glass next_bank:	;
3692e192b24SSimon Glass 	}
3702e192b24SSimon Glass 	return 0;
3712e192b24SSimon Glass }
3722e192b24SSimon Glass #endif
3732e192b24SSimon Glass 
3742e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
3752e192b24SSimon Glass static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
3762e192b24SSimon Glass 		size_t len)
3772e192b24SSimon Glass {
3782e192b24SSimon Glass 	void *imgdata;
3792e192b24SSimon Glass 	int ret;
3802e192b24SSimon Glass 
3812e192b24SSimon Glass 	imgdata = malloc(len);
3822e192b24SSimon Glass 	if (!imgdata) {
3832e192b24SSimon Glass 		printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
3842e192b24SSimon Glass 				nand_dev, off);
3852e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
3862e192b24SSimon Glass 		return -ENOMEM;
3872e192b24SSimon Glass 	}
3882e192b24SSimon Glass 
3892e192b24SSimon Glass 	ret = nand_read_skip_bad(nand, off, &len,
3902e192b24SSimon Glass 			imgdata);
3912e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
3922e192b24SSimon Glass 		free(imgdata);
3932e192b24SSimon Glass 		return ret;
3942e192b24SSimon Glass 	}
3952e192b24SSimon Glass 
3962e192b24SSimon Glass 	if (!image_check_hcrc(imgdata)) {
3972e192b24SSimon Glass 		free(imgdata);
3982e192b24SSimon Glass 		return 0;
3992e192b24SSimon Glass 	}
4002e192b24SSimon Glass 
4012e192b24SSimon Glass 	printf("Legacy Image at NAND device %d offset %08llX:\n",
4022e192b24SSimon Glass 			nand_dev, off);
4032e192b24SSimon Glass 	image_print_contents(imgdata);
4042e192b24SSimon Glass 
4052e192b24SSimon Glass 	puts("   Verifying Checksum ... ");
4062e192b24SSimon Glass 	if (!image_check_dcrc(imgdata))
4072e192b24SSimon Glass 		puts("Bad Data CRC\n");
4082e192b24SSimon Glass 	else
4092e192b24SSimon Glass 		puts("OK\n");
4102e192b24SSimon Glass 
4112e192b24SSimon Glass 	free(imgdata);
4122e192b24SSimon Glass 
4132e192b24SSimon Glass 	return 0;
4142e192b24SSimon Glass }
4152e192b24SSimon Glass 
4162e192b24SSimon Glass static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
4172e192b24SSimon Glass 		size_t len)
4182e192b24SSimon Glass {
4192e192b24SSimon Glass 	void *imgdata;
4202e192b24SSimon Glass 	int ret;
4212e192b24SSimon Glass 
4222e192b24SSimon Glass 	imgdata = malloc(len);
4232e192b24SSimon Glass 	if (!imgdata) {
4242e192b24SSimon Glass 		printf("May be a FIT Image at NAND device %d offset %08llX:\n",
4252e192b24SSimon Glass 				nand_dev, off);
4262e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
4272e192b24SSimon Glass 		return -ENOMEM;
4282e192b24SSimon Glass 	}
4292e192b24SSimon Glass 
4302e192b24SSimon Glass 	ret = nand_read_skip_bad(nand, off, &len,
4312e192b24SSimon Glass 			imgdata);
4322e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
4332e192b24SSimon Glass 		free(imgdata);
4342e192b24SSimon Glass 		return ret;
4352e192b24SSimon Glass 	}
4362e192b24SSimon Glass 
4372e192b24SSimon Glass 	if (!fit_check_format(imgdata)) {
4382e192b24SSimon Glass 		free(imgdata);
4392e192b24SSimon Glass 		return 0;
4402e192b24SSimon Glass 	}
4412e192b24SSimon Glass 
4422e192b24SSimon Glass 	printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
4432e192b24SSimon Glass 
4442e192b24SSimon Glass 	fit_print_contents(imgdata);
4452e192b24SSimon Glass 	free(imgdata);
4462e192b24SSimon Glass 
4472e192b24SSimon Glass 	return 0;
4482e192b24SSimon Glass }
4492e192b24SSimon Glass 
4502e192b24SSimon Glass static int do_imls_nand(void)
4512e192b24SSimon Glass {
4522e192b24SSimon Glass 	nand_info_t *nand;
4532e192b24SSimon Glass 	int nand_dev = nand_curr_device;
4542e192b24SSimon Glass 	size_t len;
4552e192b24SSimon Glass 	loff_t off;
4562e192b24SSimon Glass 	u32 buffer[16];
4572e192b24SSimon Glass 
4582e192b24SSimon Glass 	if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
4592e192b24SSimon Glass 		puts("\nNo NAND devices available\n");
4602e192b24SSimon Glass 		return -ENODEV;
4612e192b24SSimon Glass 	}
4622e192b24SSimon Glass 
4632e192b24SSimon Glass 	printf("\n");
4642e192b24SSimon Glass 
4652e192b24SSimon Glass 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
4662e192b24SSimon Glass 		nand = &nand_info[nand_dev];
4672e192b24SSimon Glass 		if (!nand->name || !nand->size)
4682e192b24SSimon Glass 			continue;
4692e192b24SSimon Glass 
4702e192b24SSimon Glass 		for (off = 0; off < nand->size; off += nand->erasesize) {
4712e192b24SSimon Glass 			const image_header_t *header;
4722e192b24SSimon Glass 			int ret;
4732e192b24SSimon Glass 
4742e192b24SSimon Glass 			if (nand_block_isbad(nand, off))
4752e192b24SSimon Glass 				continue;
4762e192b24SSimon Glass 
4772e192b24SSimon Glass 			len = sizeof(buffer);
4782e192b24SSimon Glass 
4792e192b24SSimon Glass 			ret = nand_read(nand, off, &len, (u8 *)buffer);
4802e192b24SSimon Glass 			if (ret < 0 && ret != -EUCLEAN) {
4812e192b24SSimon Glass 				printf("NAND read error %d at offset %08llX\n",
4822e192b24SSimon Glass 						ret, off);
4832e192b24SSimon Glass 				continue;
4842e192b24SSimon Glass 			}
4852e192b24SSimon Glass 
4862e192b24SSimon Glass 			switch (genimg_get_format(buffer)) {
4872e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
4882e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
4892e192b24SSimon Glass 				header = (const image_header_t *)buffer;
4902e192b24SSimon Glass 
4912e192b24SSimon Glass 				len = image_get_image_size(header);
4922e192b24SSimon Glass 				nand_imls_legacyimage(nand, nand_dev, off, len);
4932e192b24SSimon Glass 				break;
4942e192b24SSimon Glass #endif
4952e192b24SSimon Glass #if defined(CONFIG_FIT)
4962e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
4972e192b24SSimon Glass 				len = fit_get_size(buffer);
4982e192b24SSimon Glass 				nand_imls_fitimage(nand, nand_dev, off, len);
4992e192b24SSimon Glass 				break;
5002e192b24SSimon Glass #endif
5012e192b24SSimon Glass 			}
5022e192b24SSimon Glass 		}
5032e192b24SSimon Glass 	}
5042e192b24SSimon Glass 
5052e192b24SSimon Glass 	return 0;
5062e192b24SSimon Glass }
5072e192b24SSimon Glass #endif
5082e192b24SSimon Glass 
5092e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
5102e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5112e192b24SSimon Glass {
5122e192b24SSimon Glass 	int ret_nor = 0, ret_nand = 0;
5132e192b24SSimon Glass 
5142e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
5152e192b24SSimon Glass 	ret_nor = do_imls_nor();
5162e192b24SSimon Glass #endif
5172e192b24SSimon Glass 
5182e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
5192e192b24SSimon Glass 	ret_nand = do_imls_nand();
5202e192b24SSimon Glass #endif
5212e192b24SSimon Glass 
5222e192b24SSimon Glass 	if (ret_nor)
5232e192b24SSimon Glass 		return ret_nor;
5242e192b24SSimon Glass 
5252e192b24SSimon Glass 	if (ret_nand)
5262e192b24SSimon Glass 		return ret_nand;
5272e192b24SSimon Glass 
5282e192b24SSimon Glass 	return (0);
5292e192b24SSimon Glass }
5302e192b24SSimon Glass 
5312e192b24SSimon Glass U_BOOT_CMD(
5322e192b24SSimon Glass 	imls,	1,		1,	do_imls,
5332e192b24SSimon Glass 	"list all images found in flash",
5342e192b24SSimon Glass 	"\n"
5352e192b24SSimon Glass 	"    - Prints information about all images found at sector/block\n"
5362e192b24SSimon Glass 	"      boundaries in nor/nand flash."
5372e192b24SSimon Glass );
5382e192b24SSimon Glass #endif
5392e192b24SSimon Glass 
5402e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTZ
5412e192b24SSimon Glass 
5422e192b24SSimon Glass int __weak bootz_setup(ulong image, ulong *start, ulong *end)
5432e192b24SSimon Glass {
5442e192b24SSimon Glass 	/* Please define bootz_setup() for your platform */
5452e192b24SSimon Glass 
5462e192b24SSimon Glass 	puts("Your platform's zImage format isn't supported yet!\n");
5472e192b24SSimon Glass 	return -1;
5482e192b24SSimon Glass }
5492e192b24SSimon Glass 
5502e192b24SSimon Glass /*
5512e192b24SSimon Glass  * zImage booting support
5522e192b24SSimon Glass  */
5532e192b24SSimon Glass static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
5542e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
5552e192b24SSimon Glass {
5562e192b24SSimon Glass 	int ret;
5572e192b24SSimon Glass 	ulong zi_start, zi_end;
5582e192b24SSimon Glass 
5592e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
5602e192b24SSimon Glass 			      images, 1);
5612e192b24SSimon Glass 
5622e192b24SSimon Glass 	/* Setup Linux kernel zImage entry point */
5632e192b24SSimon Glass 	if (!argc) {
5642e192b24SSimon Glass 		images->ep = load_addr;
5652e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
5662e192b24SSimon Glass 				load_addr);
5672e192b24SSimon Glass 	} else {
5682e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
5692e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
5702e192b24SSimon Glass 			images->ep);
5712e192b24SSimon Glass 	}
5722e192b24SSimon Glass 
5732e192b24SSimon Glass 	ret = bootz_setup(images->ep, &zi_start, &zi_end);
5742e192b24SSimon Glass 	if (ret != 0)
5752e192b24SSimon Glass 		return 1;
5762e192b24SSimon Glass 
5772e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
5782e192b24SSimon Glass 
5792e192b24SSimon Glass 	/*
5802e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
5812e192b24SSimon Glass 	 * have a header that provide this informaiton.
5822e192b24SSimon Glass 	 */
5832e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
5842e192b24SSimon Glass 		return 1;
5852e192b24SSimon Glass 
5862e192b24SSimon Glass 	return 0;
5872e192b24SSimon Glass }
5882e192b24SSimon Glass 
5892e192b24SSimon Glass int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5902e192b24SSimon Glass {
5912e192b24SSimon Glass 	int ret;
5922e192b24SSimon Glass 
5932e192b24SSimon Glass 	/* Consume 'bootz' */
5942e192b24SSimon Glass 	argc--; argv++;
5952e192b24SSimon Glass 
5962e192b24SSimon Glass 	if (bootz_start(cmdtp, flag, argc, argv, &images))
5972e192b24SSimon Glass 		return 1;
5982e192b24SSimon Glass 
5992e192b24SSimon Glass 	/*
6002e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
6012e192b24SSimon Glass 	 * disable interrupts ourselves
6022e192b24SSimon Glass 	 */
6032e192b24SSimon Glass 	bootm_disable_interrupts();
6042e192b24SSimon Glass 
6052e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
6062e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
6072e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
6082e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
6092e192b24SSimon Glass 			      &images, 1);
6102e192b24SSimon Glass 
6112e192b24SSimon Glass 	return ret;
6122e192b24SSimon Glass }
6132e192b24SSimon Glass 
6142e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
6152e192b24SSimon Glass static char bootz_help_text[] =
6162e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
6172e192b24SSimon Glass 	"    - boot Linux zImage stored in memory\n"
6182e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
6192e192b24SSimon Glass 	"\tof the initrd in memory. The optional argument ':size' allows\n"
6202e192b24SSimon Glass 	"\tspecifying the size of RAW initrd.\n"
6212e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
6222e192b24SSimon Glass 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
6232e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
6242e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
6252e192b24SSimon Glass 	"\tuse a '-' for the second argument. If you do not pass a third\n"
6262e192b24SSimon Glass 	"\ta bd_info struct will be passed instead\n"
6272e192b24SSimon Glass #endif
6282e192b24SSimon Glass 	"";
6292e192b24SSimon Glass #endif
6302e192b24SSimon Glass 
6312e192b24SSimon Glass U_BOOT_CMD(
6322e192b24SSimon Glass 	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
6332e192b24SSimon Glass 	"boot Linux zImage image from memory", bootz_help_text
6342e192b24SSimon Glass );
6352e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTZ */
6362e192b24SSimon Glass 
6372e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTI
6382e192b24SSimon Glass /* See Documentation/arm64/booting.txt in the Linux kernel */
6392e192b24SSimon Glass struct Image_header {
6402e192b24SSimon Glass 	uint32_t	code0;		/* Executable code */
6412e192b24SSimon Glass 	uint32_t	code1;		/* Executable code */
6422e192b24SSimon Glass 	uint64_t	text_offset;	/* Image load offset, LE */
6432e192b24SSimon Glass 	uint64_t	image_size;	/* Effective Image size, LE */
6442e192b24SSimon Glass 	uint64_t	res1;		/* reserved */
6452e192b24SSimon Glass 	uint64_t	res2;		/* reserved */
6462e192b24SSimon Glass 	uint64_t	res3;		/* reserved */
6472e192b24SSimon Glass 	uint64_t	res4;		/* reserved */
6482e192b24SSimon Glass 	uint32_t	magic;		/* Magic number */
6492e192b24SSimon Glass 	uint32_t	res5;
6502e192b24SSimon Glass };
6512e192b24SSimon Glass 
6522e192b24SSimon Glass #define LINUX_ARM64_IMAGE_MAGIC	0x644d5241
6532e192b24SSimon Glass 
6542e192b24SSimon Glass static int booti_setup(bootm_headers_t *images)
6552e192b24SSimon Glass {
6562e192b24SSimon Glass 	struct Image_header *ih;
6572e192b24SSimon Glass 	uint64_t dst;
6582e192b24SSimon Glass 
6592e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
6602e192b24SSimon Glass 
6612e192b24SSimon Glass 	if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
6622e192b24SSimon Glass 		puts("Bad Linux ARM64 Image magic!\n");
6632e192b24SSimon Glass 		return 1;
6642e192b24SSimon Glass 	}
6652e192b24SSimon Glass 
6662e192b24SSimon Glass 	if (ih->image_size == 0) {
6672e192b24SSimon Glass 		puts("Image lacks image_size field, assuming 16MiB\n");
6682e192b24SSimon Glass 		ih->image_size = (16 << 20);
6692e192b24SSimon Glass 	}
6702e192b24SSimon Glass 
6712e192b24SSimon Glass 	/*
6722e192b24SSimon Glass 	 * If we are not at the correct run-time location, set the new
6732e192b24SSimon Glass 	 * correct location and then move the image there.
6742e192b24SSimon Glass 	 */
6752e192b24SSimon Glass 	dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset);
6762e192b24SSimon Glass 	if (images->ep != dst) {
6772e192b24SSimon Glass 		void *src;
6782e192b24SSimon Glass 
6792e192b24SSimon Glass 		debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
6802e192b24SSimon Glass 
6812e192b24SSimon Glass 		src = (void *)images->ep;
6822e192b24SSimon Glass 		images->ep = dst;
6832e192b24SSimon Glass 		memmove((void *)dst, src, le32_to_cpu(ih->image_size));
6842e192b24SSimon Glass 	}
6852e192b24SSimon Glass 
6862e192b24SSimon Glass 	return 0;
6872e192b24SSimon Glass }
6882e192b24SSimon Glass 
6892e192b24SSimon Glass /*
6902e192b24SSimon Glass  * Image booting support
6912e192b24SSimon Glass  */
6922e192b24SSimon Glass static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
6932e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
6942e192b24SSimon Glass {
6952e192b24SSimon Glass 	int ret;
6962e192b24SSimon Glass 	struct Image_header *ih;
6972e192b24SSimon Glass 
6982e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
6992e192b24SSimon Glass 			      images, 1);
7002e192b24SSimon Glass 
7012e192b24SSimon Glass 	/* Setup Linux kernel Image entry point */
7022e192b24SSimon Glass 	if (!argc) {
7032e192b24SSimon Glass 		images->ep = load_addr;
7042e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
7052e192b24SSimon Glass 				load_addr);
7062e192b24SSimon Glass 	} else {
7072e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
7082e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
7092e192b24SSimon Glass 			images->ep);
7102e192b24SSimon Glass 	}
7112e192b24SSimon Glass 
7122e192b24SSimon Glass 	ret = booti_setup(images);
7132e192b24SSimon Glass 	if (ret != 0)
7142e192b24SSimon Glass 		return 1;
7152e192b24SSimon Glass 
7162e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
7172e192b24SSimon Glass 
7182e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
7192e192b24SSimon Glass 
7202e192b24SSimon Glass 	/*
7212e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
7222e192b24SSimon Glass 	 * have a header that provide this informaiton.
7232e192b24SSimon Glass 	 */
7242e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
7252e192b24SSimon Glass 		return 1;
7262e192b24SSimon Glass 
7272e192b24SSimon Glass 	return 0;
7282e192b24SSimon Glass }
7292e192b24SSimon Glass 
7302e192b24SSimon Glass int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
7312e192b24SSimon Glass {
7322e192b24SSimon Glass 	int ret;
7332e192b24SSimon Glass 
7342e192b24SSimon Glass 	/* Consume 'booti' */
7352e192b24SSimon Glass 	argc--; argv++;
7362e192b24SSimon Glass 
7372e192b24SSimon Glass 	if (booti_start(cmdtp, flag, argc, argv, &images))
7382e192b24SSimon Glass 		return 1;
7392e192b24SSimon Glass 
7402e192b24SSimon Glass 	/*
7412e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
7422e192b24SSimon Glass 	 * disable interrupts ourselves
7432e192b24SSimon Glass 	 */
7442e192b24SSimon Glass 	bootm_disable_interrupts();
7452e192b24SSimon Glass 
7462e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
7472e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
7482e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
7492e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
7502e192b24SSimon Glass 			      &images, 1);
7512e192b24SSimon Glass 
7522e192b24SSimon Glass 	return ret;
7532e192b24SSimon Glass }
7542e192b24SSimon Glass 
7552e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
7562e192b24SSimon Glass static char booti_help_text[] =
7572e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
758*6f6051faSKarsten Merker 	"    - boot arm64 Linux Image stored in memory\n"
7592e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
760*6f6051faSKarsten Merker 	"\tof an initrd in memory. The optional parameter ':size' allows\n"
761*6f6051faSKarsten Merker 	"\tspecifying the size of a RAW initrd.\n"
7622e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
763*6f6051faSKarsten Merker 	"\tSince booting a Linux kernel requires a flat device-tree, a\n"
764*6f6051faSKarsten Merker 	"\tthird argument providing the address of the device-tree blob\n"
765*6f6051faSKarsten Merker 	"\tis required. To boot a kernel with a device-tree blob but\n"
766*6f6051faSKarsten Merker 	"\twithout an initrd image, use a '-' for the initrd argument.\n"
7672e192b24SSimon Glass #endif
7682e192b24SSimon Glass 	"";
7692e192b24SSimon Glass #endif
7702e192b24SSimon Glass 
7712e192b24SSimon Glass U_BOOT_CMD(
7722e192b24SSimon Glass 	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
7732e192b24SSimon Glass 	"boot arm64 Linux Image image from memory", booti_help_text
7742e192b24SSimon Glass );
7752e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTI */
776