xref: /rk3399_rockchip-uboot/cmd/bootm.c (revision 2e192b245ed36a63bab0ef576999a95e23f60ecd)
1*2e192b24SSimon Glass /*
2*2e192b24SSimon Glass  * (C) Copyright 2000-2009
3*2e192b24SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*2e192b24SSimon Glass  *
5*2e192b24SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6*2e192b24SSimon Glass  */
7*2e192b24SSimon Glass 
8*2e192b24SSimon Glass /*
9*2e192b24SSimon Glass  * Boot support
10*2e192b24SSimon Glass  */
11*2e192b24SSimon Glass #include <common.h>
12*2e192b24SSimon Glass #include <bootm.h>
13*2e192b24SSimon Glass #include <command.h>
14*2e192b24SSimon Glass #include <environment.h>
15*2e192b24SSimon Glass #include <errno.h>
16*2e192b24SSimon Glass #include <image.h>
17*2e192b24SSimon Glass #include <lmb.h>
18*2e192b24SSimon Glass #include <malloc.h>
19*2e192b24SSimon Glass #include <mapmem.h>
20*2e192b24SSimon Glass #include <nand.h>
21*2e192b24SSimon Glass #include <asm/byteorder.h>
22*2e192b24SSimon Glass #include <linux/compiler.h>
23*2e192b24SSimon Glass #include <linux/ctype.h>
24*2e192b24SSimon Glass #include <linux/err.h>
25*2e192b24SSimon Glass #include <u-boot/zlib.h>
26*2e192b24SSimon Glass 
27*2e192b24SSimon Glass DECLARE_GLOBAL_DATA_PTR;
28*2e192b24SSimon Glass 
29*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
30*2e192b24SSimon Glass static int image_info(unsigned long addr);
31*2e192b24SSimon Glass #endif
32*2e192b24SSimon Glass 
33*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
34*2e192b24SSimon Glass #include <flash.h>
35*2e192b24SSimon Glass #include <mtd/cfi_flash.h>
36*2e192b24SSimon Glass extern flash_info_t flash_info[]; /* info for FLASH chips */
37*2e192b24SSimon Glass #endif
38*2e192b24SSimon Glass 
39*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
40*2e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
41*2e192b24SSimon Glass #endif
42*2e192b24SSimon Glass 
43*2e192b24SSimon Glass bootm_headers_t images;		/* pointers to os/initrd/fdt images */
44*2e192b24SSimon Glass 
45*2e192b24SSimon Glass /* we overload the cmd field with our state machine info instead of a
46*2e192b24SSimon Glass  * function pointer */
47*2e192b24SSimon Glass static cmd_tbl_t cmd_bootm_sub[] = {
48*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
49*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
50*2e192b24SSimon Glass #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
51*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
52*2e192b24SSimon Glass #endif
53*2e192b24SSimon Glass #ifdef CONFIG_OF_LIBFDT
54*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
55*2e192b24SSimon Glass #endif
56*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
57*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
58*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
59*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
60*2e192b24SSimon Glass 	U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
61*2e192b24SSimon Glass };
62*2e192b24SSimon Glass 
63*2e192b24SSimon Glass static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
64*2e192b24SSimon Glass 			char * const argv[])
65*2e192b24SSimon Glass {
66*2e192b24SSimon Glass 	int ret = 0;
67*2e192b24SSimon Glass 	long state;
68*2e192b24SSimon Glass 	cmd_tbl_t *c;
69*2e192b24SSimon Glass 
70*2e192b24SSimon Glass 	c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
71*2e192b24SSimon Glass 	argc--; argv++;
72*2e192b24SSimon Glass 
73*2e192b24SSimon Glass 	if (c) {
74*2e192b24SSimon Glass 		state = (long)c->cmd;
75*2e192b24SSimon Glass 		if (state == BOOTM_STATE_START)
76*2e192b24SSimon Glass 			state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
77*2e192b24SSimon Glass 	} else {
78*2e192b24SSimon Glass 		/* Unrecognized command */
79*2e192b24SSimon Glass 		return CMD_RET_USAGE;
80*2e192b24SSimon Glass 	}
81*2e192b24SSimon Glass 
82*2e192b24SSimon Glass 	if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
83*2e192b24SSimon Glass 	    images.state >= state) {
84*2e192b24SSimon Glass 		printf("Trying to execute a command out of order\n");
85*2e192b24SSimon Glass 		return CMD_RET_USAGE;
86*2e192b24SSimon Glass 	}
87*2e192b24SSimon Glass 
88*2e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
89*2e192b24SSimon Glass 
90*2e192b24SSimon Glass 	return ret;
91*2e192b24SSimon Glass }
92*2e192b24SSimon Glass 
93*2e192b24SSimon Glass /*******************************************************************/
94*2e192b24SSimon Glass /* bootm - boot application image from image in memory */
95*2e192b24SSimon Glass /*******************************************************************/
96*2e192b24SSimon Glass 
97*2e192b24SSimon Glass int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
98*2e192b24SSimon Glass {
99*2e192b24SSimon Glass #ifdef CONFIG_NEEDS_MANUAL_RELOC
100*2e192b24SSimon Glass 	static int relocated = 0;
101*2e192b24SSimon Glass 
102*2e192b24SSimon Glass 	if (!relocated) {
103*2e192b24SSimon Glass 		int i;
104*2e192b24SSimon Glass 
105*2e192b24SSimon Glass 		/* relocate names of sub-command table */
106*2e192b24SSimon Glass 		for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
107*2e192b24SSimon Glass 			cmd_bootm_sub[i].name += gd->reloc_off;
108*2e192b24SSimon Glass 
109*2e192b24SSimon Glass 		relocated = 1;
110*2e192b24SSimon Glass 	}
111*2e192b24SSimon Glass #endif
112*2e192b24SSimon Glass 
113*2e192b24SSimon Glass 	/* determine if we have a sub command */
114*2e192b24SSimon Glass 	argc--; argv++;
115*2e192b24SSimon Glass 	if (argc > 0) {
116*2e192b24SSimon Glass 		char *endp;
117*2e192b24SSimon Glass 
118*2e192b24SSimon Glass 		simple_strtoul(argv[0], &endp, 16);
119*2e192b24SSimon Glass 		/* endp pointing to NULL means that argv[0] was just a
120*2e192b24SSimon Glass 		 * valid number, pass it along to the normal bootm processing
121*2e192b24SSimon Glass 		 *
122*2e192b24SSimon Glass 		 * If endp is ':' or '#' assume a FIT identifier so pass
123*2e192b24SSimon Glass 		 * along for normal processing.
124*2e192b24SSimon Glass 		 *
125*2e192b24SSimon Glass 		 * Right now we assume the first arg should never be '-'
126*2e192b24SSimon Glass 		 */
127*2e192b24SSimon Glass 		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
128*2e192b24SSimon Glass 			return do_bootm_subcommand(cmdtp, flag, argc, argv);
129*2e192b24SSimon Glass 	}
130*2e192b24SSimon Glass 
131*2e192b24SSimon Glass 	return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
132*2e192b24SSimon Glass 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
133*2e192b24SSimon Glass 		BOOTM_STATE_LOADOS |
134*2e192b24SSimon Glass #if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
135*2e192b24SSimon Glass 		BOOTM_STATE_OS_CMDLINE |
136*2e192b24SSimon Glass #endif
137*2e192b24SSimon Glass 		BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
138*2e192b24SSimon Glass 		BOOTM_STATE_OS_GO, &images, 1);
139*2e192b24SSimon Glass }
140*2e192b24SSimon Glass 
141*2e192b24SSimon Glass int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
142*2e192b24SSimon Glass {
143*2e192b24SSimon Glass 	const char *ep = getenv("autostart");
144*2e192b24SSimon Glass 
145*2e192b24SSimon Glass 	if (ep && !strcmp(ep, "yes")) {
146*2e192b24SSimon Glass 		char *local_args[2];
147*2e192b24SSimon Glass 		local_args[0] = (char *)cmd;
148*2e192b24SSimon Glass 		local_args[1] = NULL;
149*2e192b24SSimon Glass 		printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
150*2e192b24SSimon Glass 		return do_bootm(cmdtp, 0, 1, local_args);
151*2e192b24SSimon Glass 	}
152*2e192b24SSimon Glass 
153*2e192b24SSimon Glass 	return 0;
154*2e192b24SSimon Glass }
155*2e192b24SSimon Glass 
156*2e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
157*2e192b24SSimon Glass static char bootm_help_text[] =
158*2e192b24SSimon Glass 	"[addr [arg ...]]\n    - boot application image stored in memory\n"
159*2e192b24SSimon Glass 	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
160*2e192b24SSimon Glass 	"\t'arg' can be the address of an initrd image\n"
161*2e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
162*2e192b24SSimon Glass 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
163*2e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
164*2e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
165*2e192b24SSimon Glass 	"\tuse a '-' for the second argument. If you do not pass a third\n"
166*2e192b24SSimon Glass 	"\ta bd_info struct will be passed instead\n"
167*2e192b24SSimon Glass #endif
168*2e192b24SSimon Glass #if defined(CONFIG_FIT)
169*2e192b24SSimon Glass 	"\t\nFor the new multi component uImage format (FIT) addresses\n"
170*2e192b24SSimon Glass 	"\tmust be extened to include component or configuration unit name:\n"
171*2e192b24SSimon Glass 	"\taddr:<subimg_uname> - direct component image specification\n"
172*2e192b24SSimon Glass 	"\taddr#<conf_uname>   - configuration specification\n"
173*2e192b24SSimon Glass 	"\tUse iminfo command to get the list of existing component\n"
174*2e192b24SSimon Glass 	"\timages and configurations.\n"
175*2e192b24SSimon Glass #endif
176*2e192b24SSimon Glass 	"\nSub-commands to do part of the bootm sequence.  The sub-commands "
177*2e192b24SSimon Glass 	"must be\n"
178*2e192b24SSimon Glass 	"issued in the order below (it's ok to not issue all sub-commands):\n"
179*2e192b24SSimon Glass 	"\tstart [addr [arg ...]]\n"
180*2e192b24SSimon Glass 	"\tloados  - load OS image\n"
181*2e192b24SSimon Glass #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
182*2e192b24SSimon Glass 	"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
183*2e192b24SSimon Glass #endif
184*2e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
185*2e192b24SSimon Glass 	"\tfdt     - relocate flat device tree\n"
186*2e192b24SSimon Glass #endif
187*2e192b24SSimon Glass 	"\tcmdline - OS specific command line processing/setup\n"
188*2e192b24SSimon Glass 	"\tbdt     - OS specific bd_t processing\n"
189*2e192b24SSimon Glass 	"\tprep    - OS specific prep before relocation or go\n"
190*2e192b24SSimon Glass #if defined(CONFIG_TRACE)
191*2e192b24SSimon Glass 	"\tfake    - OS specific fake start without go\n"
192*2e192b24SSimon Glass #endif
193*2e192b24SSimon Glass 	"\tgo      - start OS";
194*2e192b24SSimon Glass #endif
195*2e192b24SSimon Glass 
196*2e192b24SSimon Glass U_BOOT_CMD(
197*2e192b24SSimon Glass 	bootm,	CONFIG_SYS_MAXARGS,	1,	do_bootm,
198*2e192b24SSimon Glass 	"boot application image from memory", bootm_help_text
199*2e192b24SSimon Glass );
200*2e192b24SSimon Glass 
201*2e192b24SSimon Glass /*******************************************************************/
202*2e192b24SSimon Glass /* bootd - boot default image */
203*2e192b24SSimon Glass /*******************************************************************/
204*2e192b24SSimon Glass #if defined(CONFIG_CMD_BOOTD)
205*2e192b24SSimon Glass int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
206*2e192b24SSimon Glass {
207*2e192b24SSimon Glass 	return run_command(getenv("bootcmd"), flag);
208*2e192b24SSimon Glass }
209*2e192b24SSimon Glass 
210*2e192b24SSimon Glass U_BOOT_CMD(
211*2e192b24SSimon Glass 	boot,	1,	1,	do_bootd,
212*2e192b24SSimon Glass 	"boot default, i.e., run 'bootcmd'",
213*2e192b24SSimon Glass 	""
214*2e192b24SSimon Glass );
215*2e192b24SSimon Glass 
216*2e192b24SSimon Glass /* keep old command name "bootd" for backward compatibility */
217*2e192b24SSimon Glass U_BOOT_CMD(
218*2e192b24SSimon Glass 	bootd, 1,	1,	do_bootd,
219*2e192b24SSimon Glass 	"boot default, i.e., run 'bootcmd'",
220*2e192b24SSimon Glass 	""
221*2e192b24SSimon Glass );
222*2e192b24SSimon Glass 
223*2e192b24SSimon Glass #endif
224*2e192b24SSimon Glass 
225*2e192b24SSimon Glass 
226*2e192b24SSimon Glass /*******************************************************************/
227*2e192b24SSimon Glass /* iminfo - print header info for a requested image */
228*2e192b24SSimon Glass /*******************************************************************/
229*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
230*2e192b24SSimon Glass static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
231*2e192b24SSimon Glass {
232*2e192b24SSimon Glass 	int	arg;
233*2e192b24SSimon Glass 	ulong	addr;
234*2e192b24SSimon Glass 	int	rcode = 0;
235*2e192b24SSimon Glass 
236*2e192b24SSimon Glass 	if (argc < 2) {
237*2e192b24SSimon Glass 		return image_info(load_addr);
238*2e192b24SSimon Glass 	}
239*2e192b24SSimon Glass 
240*2e192b24SSimon Glass 	for (arg = 1; arg < argc; ++arg) {
241*2e192b24SSimon Glass 		addr = simple_strtoul(argv[arg], NULL, 16);
242*2e192b24SSimon Glass 		if (image_info(addr) != 0)
243*2e192b24SSimon Glass 			rcode = 1;
244*2e192b24SSimon Glass 	}
245*2e192b24SSimon Glass 	return rcode;
246*2e192b24SSimon Glass }
247*2e192b24SSimon Glass 
248*2e192b24SSimon Glass static int image_info(ulong addr)
249*2e192b24SSimon Glass {
250*2e192b24SSimon Glass 	void *hdr = (void *)addr;
251*2e192b24SSimon Glass 
252*2e192b24SSimon Glass 	printf("\n## Checking Image at %08lx ...\n", addr);
253*2e192b24SSimon Glass 
254*2e192b24SSimon Glass 	switch (genimg_get_format(hdr)) {
255*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
256*2e192b24SSimon Glass 	case IMAGE_FORMAT_LEGACY:
257*2e192b24SSimon Glass 		puts("   Legacy image found\n");
258*2e192b24SSimon Glass 		if (!image_check_magic(hdr)) {
259*2e192b24SSimon Glass 			puts("   Bad Magic Number\n");
260*2e192b24SSimon Glass 			return 1;
261*2e192b24SSimon Glass 		}
262*2e192b24SSimon Glass 
263*2e192b24SSimon Glass 		if (!image_check_hcrc(hdr)) {
264*2e192b24SSimon Glass 			puts("   Bad Header Checksum\n");
265*2e192b24SSimon Glass 			return 1;
266*2e192b24SSimon Glass 		}
267*2e192b24SSimon Glass 
268*2e192b24SSimon Glass 		image_print_contents(hdr);
269*2e192b24SSimon Glass 
270*2e192b24SSimon Glass 		puts("   Verifying Checksum ... ");
271*2e192b24SSimon Glass 		if (!image_check_dcrc(hdr)) {
272*2e192b24SSimon Glass 			puts("   Bad Data CRC\n");
273*2e192b24SSimon Glass 			return 1;
274*2e192b24SSimon Glass 		}
275*2e192b24SSimon Glass 		puts("OK\n");
276*2e192b24SSimon Glass 		return 0;
277*2e192b24SSimon Glass #endif
278*2e192b24SSimon Glass #if defined(CONFIG_FIT)
279*2e192b24SSimon Glass 	case IMAGE_FORMAT_FIT:
280*2e192b24SSimon Glass 		puts("   FIT image found\n");
281*2e192b24SSimon Glass 
282*2e192b24SSimon Glass 		if (!fit_check_format(hdr)) {
283*2e192b24SSimon Glass 			puts("Bad FIT image format!\n");
284*2e192b24SSimon Glass 			return 1;
285*2e192b24SSimon Glass 		}
286*2e192b24SSimon Glass 
287*2e192b24SSimon Glass 		fit_print_contents(hdr);
288*2e192b24SSimon Glass 
289*2e192b24SSimon Glass 		if (!fit_all_image_verify(hdr)) {
290*2e192b24SSimon Glass 			puts("Bad hash in FIT image!\n");
291*2e192b24SSimon Glass 			return 1;
292*2e192b24SSimon Glass 		}
293*2e192b24SSimon Glass 
294*2e192b24SSimon Glass 		return 0;
295*2e192b24SSimon Glass #endif
296*2e192b24SSimon Glass 	default:
297*2e192b24SSimon Glass 		puts("Unknown image format!\n");
298*2e192b24SSimon Glass 		break;
299*2e192b24SSimon Glass 	}
300*2e192b24SSimon Glass 
301*2e192b24SSimon Glass 	return 1;
302*2e192b24SSimon Glass }
303*2e192b24SSimon Glass 
304*2e192b24SSimon Glass U_BOOT_CMD(
305*2e192b24SSimon Glass 	iminfo,	CONFIG_SYS_MAXARGS,	1,	do_iminfo,
306*2e192b24SSimon Glass 	"print header information for application image",
307*2e192b24SSimon Glass 	"addr [addr ...]\n"
308*2e192b24SSimon Glass 	"    - print header information for application image starting at\n"
309*2e192b24SSimon Glass 	"      address 'addr' in memory; this includes verification of the\n"
310*2e192b24SSimon Glass 	"      image contents (magic number, header and payload checksums)"
311*2e192b24SSimon Glass );
312*2e192b24SSimon Glass #endif
313*2e192b24SSimon Glass 
314*2e192b24SSimon Glass 
315*2e192b24SSimon Glass /*******************************************************************/
316*2e192b24SSimon Glass /* imls - list all images found in flash */
317*2e192b24SSimon Glass /*******************************************************************/
318*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
319*2e192b24SSimon Glass static int do_imls_nor(void)
320*2e192b24SSimon Glass {
321*2e192b24SSimon Glass 	flash_info_t *info;
322*2e192b24SSimon Glass 	int i, j;
323*2e192b24SSimon Glass 	void *hdr;
324*2e192b24SSimon Glass 
325*2e192b24SSimon Glass 	for (i = 0, info = &flash_info[0];
326*2e192b24SSimon Glass 		i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
327*2e192b24SSimon Glass 
328*2e192b24SSimon Glass 		if (info->flash_id == FLASH_UNKNOWN)
329*2e192b24SSimon Glass 			goto next_bank;
330*2e192b24SSimon Glass 		for (j = 0; j < info->sector_count; ++j) {
331*2e192b24SSimon Glass 
332*2e192b24SSimon Glass 			hdr = (void *)info->start[j];
333*2e192b24SSimon Glass 			if (!hdr)
334*2e192b24SSimon Glass 				goto next_sector;
335*2e192b24SSimon Glass 
336*2e192b24SSimon Glass 			switch (genimg_get_format(hdr)) {
337*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
338*2e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
339*2e192b24SSimon Glass 				if (!image_check_hcrc(hdr))
340*2e192b24SSimon Glass 					goto next_sector;
341*2e192b24SSimon Glass 
342*2e192b24SSimon Glass 				printf("Legacy Image at %08lX:\n", (ulong)hdr);
343*2e192b24SSimon Glass 				image_print_contents(hdr);
344*2e192b24SSimon Glass 
345*2e192b24SSimon Glass 				puts("   Verifying Checksum ... ");
346*2e192b24SSimon Glass 				if (!image_check_dcrc(hdr)) {
347*2e192b24SSimon Glass 					puts("Bad Data CRC\n");
348*2e192b24SSimon Glass 				} else {
349*2e192b24SSimon Glass 					puts("OK\n");
350*2e192b24SSimon Glass 				}
351*2e192b24SSimon Glass 				break;
352*2e192b24SSimon Glass #endif
353*2e192b24SSimon Glass #if defined(CONFIG_FIT)
354*2e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
355*2e192b24SSimon Glass 				if (!fit_check_format(hdr))
356*2e192b24SSimon Glass 					goto next_sector;
357*2e192b24SSimon Glass 
358*2e192b24SSimon Glass 				printf("FIT Image at %08lX:\n", (ulong)hdr);
359*2e192b24SSimon Glass 				fit_print_contents(hdr);
360*2e192b24SSimon Glass 				break;
361*2e192b24SSimon Glass #endif
362*2e192b24SSimon Glass 			default:
363*2e192b24SSimon Glass 				goto next_sector;
364*2e192b24SSimon Glass 			}
365*2e192b24SSimon Glass 
366*2e192b24SSimon Glass next_sector:		;
367*2e192b24SSimon Glass 		}
368*2e192b24SSimon Glass next_bank:	;
369*2e192b24SSimon Glass 	}
370*2e192b24SSimon Glass 	return 0;
371*2e192b24SSimon Glass }
372*2e192b24SSimon Glass #endif
373*2e192b24SSimon Glass 
374*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
375*2e192b24SSimon Glass static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
376*2e192b24SSimon Glass 		size_t len)
377*2e192b24SSimon Glass {
378*2e192b24SSimon Glass 	void *imgdata;
379*2e192b24SSimon Glass 	int ret;
380*2e192b24SSimon Glass 
381*2e192b24SSimon Glass 	imgdata = malloc(len);
382*2e192b24SSimon Glass 	if (!imgdata) {
383*2e192b24SSimon Glass 		printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
384*2e192b24SSimon Glass 				nand_dev, off);
385*2e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
386*2e192b24SSimon Glass 		return -ENOMEM;
387*2e192b24SSimon Glass 	}
388*2e192b24SSimon Glass 
389*2e192b24SSimon Glass 	ret = nand_read_skip_bad(nand, off, &len,
390*2e192b24SSimon Glass 			imgdata);
391*2e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
392*2e192b24SSimon Glass 		free(imgdata);
393*2e192b24SSimon Glass 		return ret;
394*2e192b24SSimon Glass 	}
395*2e192b24SSimon Glass 
396*2e192b24SSimon Glass 	if (!image_check_hcrc(imgdata)) {
397*2e192b24SSimon Glass 		free(imgdata);
398*2e192b24SSimon Glass 		return 0;
399*2e192b24SSimon Glass 	}
400*2e192b24SSimon Glass 
401*2e192b24SSimon Glass 	printf("Legacy Image at NAND device %d offset %08llX:\n",
402*2e192b24SSimon Glass 			nand_dev, off);
403*2e192b24SSimon Glass 	image_print_contents(imgdata);
404*2e192b24SSimon Glass 
405*2e192b24SSimon Glass 	puts("   Verifying Checksum ... ");
406*2e192b24SSimon Glass 	if (!image_check_dcrc(imgdata))
407*2e192b24SSimon Glass 		puts("Bad Data CRC\n");
408*2e192b24SSimon Glass 	else
409*2e192b24SSimon Glass 		puts("OK\n");
410*2e192b24SSimon Glass 
411*2e192b24SSimon Glass 	free(imgdata);
412*2e192b24SSimon Glass 
413*2e192b24SSimon Glass 	return 0;
414*2e192b24SSimon Glass }
415*2e192b24SSimon Glass 
416*2e192b24SSimon Glass static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
417*2e192b24SSimon Glass 		size_t len)
418*2e192b24SSimon Glass {
419*2e192b24SSimon Glass 	void *imgdata;
420*2e192b24SSimon Glass 	int ret;
421*2e192b24SSimon Glass 
422*2e192b24SSimon Glass 	imgdata = malloc(len);
423*2e192b24SSimon Glass 	if (!imgdata) {
424*2e192b24SSimon Glass 		printf("May be a FIT Image at NAND device %d offset %08llX:\n",
425*2e192b24SSimon Glass 				nand_dev, off);
426*2e192b24SSimon Glass 		printf("   Low memory(cannot allocate memory for image)\n");
427*2e192b24SSimon Glass 		return -ENOMEM;
428*2e192b24SSimon Glass 	}
429*2e192b24SSimon Glass 
430*2e192b24SSimon Glass 	ret = nand_read_skip_bad(nand, off, &len,
431*2e192b24SSimon Glass 			imgdata);
432*2e192b24SSimon Glass 	if (ret < 0 && ret != -EUCLEAN) {
433*2e192b24SSimon Glass 		free(imgdata);
434*2e192b24SSimon Glass 		return ret;
435*2e192b24SSimon Glass 	}
436*2e192b24SSimon Glass 
437*2e192b24SSimon Glass 	if (!fit_check_format(imgdata)) {
438*2e192b24SSimon Glass 		free(imgdata);
439*2e192b24SSimon Glass 		return 0;
440*2e192b24SSimon Glass 	}
441*2e192b24SSimon Glass 
442*2e192b24SSimon Glass 	printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
443*2e192b24SSimon Glass 
444*2e192b24SSimon Glass 	fit_print_contents(imgdata);
445*2e192b24SSimon Glass 	free(imgdata);
446*2e192b24SSimon Glass 
447*2e192b24SSimon Glass 	return 0;
448*2e192b24SSimon Glass }
449*2e192b24SSimon Glass 
450*2e192b24SSimon Glass static int do_imls_nand(void)
451*2e192b24SSimon Glass {
452*2e192b24SSimon Glass 	nand_info_t *nand;
453*2e192b24SSimon Glass 	int nand_dev = nand_curr_device;
454*2e192b24SSimon Glass 	size_t len;
455*2e192b24SSimon Glass 	loff_t off;
456*2e192b24SSimon Glass 	u32 buffer[16];
457*2e192b24SSimon Glass 
458*2e192b24SSimon Glass 	if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
459*2e192b24SSimon Glass 		puts("\nNo NAND devices available\n");
460*2e192b24SSimon Glass 		return -ENODEV;
461*2e192b24SSimon Glass 	}
462*2e192b24SSimon Glass 
463*2e192b24SSimon Glass 	printf("\n");
464*2e192b24SSimon Glass 
465*2e192b24SSimon Glass 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
466*2e192b24SSimon Glass 		nand = &nand_info[nand_dev];
467*2e192b24SSimon Glass 		if (!nand->name || !nand->size)
468*2e192b24SSimon Glass 			continue;
469*2e192b24SSimon Glass 
470*2e192b24SSimon Glass 		for (off = 0; off < nand->size; off += nand->erasesize) {
471*2e192b24SSimon Glass 			const image_header_t *header;
472*2e192b24SSimon Glass 			int ret;
473*2e192b24SSimon Glass 
474*2e192b24SSimon Glass 			if (nand_block_isbad(nand, off))
475*2e192b24SSimon Glass 				continue;
476*2e192b24SSimon Glass 
477*2e192b24SSimon Glass 			len = sizeof(buffer);
478*2e192b24SSimon Glass 
479*2e192b24SSimon Glass 			ret = nand_read(nand, off, &len, (u8 *)buffer);
480*2e192b24SSimon Glass 			if (ret < 0 && ret != -EUCLEAN) {
481*2e192b24SSimon Glass 				printf("NAND read error %d at offset %08llX\n",
482*2e192b24SSimon Glass 						ret, off);
483*2e192b24SSimon Glass 				continue;
484*2e192b24SSimon Glass 			}
485*2e192b24SSimon Glass 
486*2e192b24SSimon Glass 			switch (genimg_get_format(buffer)) {
487*2e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
488*2e192b24SSimon Glass 			case IMAGE_FORMAT_LEGACY:
489*2e192b24SSimon Glass 				header = (const image_header_t *)buffer;
490*2e192b24SSimon Glass 
491*2e192b24SSimon Glass 				len = image_get_image_size(header);
492*2e192b24SSimon Glass 				nand_imls_legacyimage(nand, nand_dev, off, len);
493*2e192b24SSimon Glass 				break;
494*2e192b24SSimon Glass #endif
495*2e192b24SSimon Glass #if defined(CONFIG_FIT)
496*2e192b24SSimon Glass 			case IMAGE_FORMAT_FIT:
497*2e192b24SSimon Glass 				len = fit_get_size(buffer);
498*2e192b24SSimon Glass 				nand_imls_fitimage(nand, nand_dev, off, len);
499*2e192b24SSimon Glass 				break;
500*2e192b24SSimon Glass #endif
501*2e192b24SSimon Glass 			}
502*2e192b24SSimon Glass 		}
503*2e192b24SSimon Glass 	}
504*2e192b24SSimon Glass 
505*2e192b24SSimon Glass 	return 0;
506*2e192b24SSimon Glass }
507*2e192b24SSimon Glass #endif
508*2e192b24SSimon Glass 
509*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
510*2e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
511*2e192b24SSimon Glass {
512*2e192b24SSimon Glass 	int ret_nor = 0, ret_nand = 0;
513*2e192b24SSimon Glass 
514*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
515*2e192b24SSimon Glass 	ret_nor = do_imls_nor();
516*2e192b24SSimon Glass #endif
517*2e192b24SSimon Glass 
518*2e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
519*2e192b24SSimon Glass 	ret_nand = do_imls_nand();
520*2e192b24SSimon Glass #endif
521*2e192b24SSimon Glass 
522*2e192b24SSimon Glass 	if (ret_nor)
523*2e192b24SSimon Glass 		return ret_nor;
524*2e192b24SSimon Glass 
525*2e192b24SSimon Glass 	if (ret_nand)
526*2e192b24SSimon Glass 		return ret_nand;
527*2e192b24SSimon Glass 
528*2e192b24SSimon Glass 	return (0);
529*2e192b24SSimon Glass }
530*2e192b24SSimon Glass 
531*2e192b24SSimon Glass U_BOOT_CMD(
532*2e192b24SSimon Glass 	imls,	1,		1,	do_imls,
533*2e192b24SSimon Glass 	"list all images found in flash",
534*2e192b24SSimon Glass 	"\n"
535*2e192b24SSimon Glass 	"    - Prints information about all images found at sector/block\n"
536*2e192b24SSimon Glass 	"      boundaries in nor/nand flash."
537*2e192b24SSimon Glass );
538*2e192b24SSimon Glass #endif
539*2e192b24SSimon Glass 
540*2e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTZ
541*2e192b24SSimon Glass 
542*2e192b24SSimon Glass int __weak bootz_setup(ulong image, ulong *start, ulong *end)
543*2e192b24SSimon Glass {
544*2e192b24SSimon Glass 	/* Please define bootz_setup() for your platform */
545*2e192b24SSimon Glass 
546*2e192b24SSimon Glass 	puts("Your platform's zImage format isn't supported yet!\n");
547*2e192b24SSimon Glass 	return -1;
548*2e192b24SSimon Glass }
549*2e192b24SSimon Glass 
550*2e192b24SSimon Glass /*
551*2e192b24SSimon Glass  * zImage booting support
552*2e192b24SSimon Glass  */
553*2e192b24SSimon Glass static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
554*2e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
555*2e192b24SSimon Glass {
556*2e192b24SSimon Glass 	int ret;
557*2e192b24SSimon Glass 	ulong zi_start, zi_end;
558*2e192b24SSimon Glass 
559*2e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
560*2e192b24SSimon Glass 			      images, 1);
561*2e192b24SSimon Glass 
562*2e192b24SSimon Glass 	/* Setup Linux kernel zImage entry point */
563*2e192b24SSimon Glass 	if (!argc) {
564*2e192b24SSimon Glass 		images->ep = load_addr;
565*2e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
566*2e192b24SSimon Glass 				load_addr);
567*2e192b24SSimon Glass 	} else {
568*2e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
569*2e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
570*2e192b24SSimon Glass 			images->ep);
571*2e192b24SSimon Glass 	}
572*2e192b24SSimon Glass 
573*2e192b24SSimon Glass 	ret = bootz_setup(images->ep, &zi_start, &zi_end);
574*2e192b24SSimon Glass 	if (ret != 0)
575*2e192b24SSimon Glass 		return 1;
576*2e192b24SSimon Glass 
577*2e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
578*2e192b24SSimon Glass 
579*2e192b24SSimon Glass 	/*
580*2e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
581*2e192b24SSimon Glass 	 * have a header that provide this informaiton.
582*2e192b24SSimon Glass 	 */
583*2e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
584*2e192b24SSimon Glass 		return 1;
585*2e192b24SSimon Glass 
586*2e192b24SSimon Glass 	return 0;
587*2e192b24SSimon Glass }
588*2e192b24SSimon Glass 
589*2e192b24SSimon Glass int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
590*2e192b24SSimon Glass {
591*2e192b24SSimon Glass 	int ret;
592*2e192b24SSimon Glass 
593*2e192b24SSimon Glass 	/* Consume 'bootz' */
594*2e192b24SSimon Glass 	argc--; argv++;
595*2e192b24SSimon Glass 
596*2e192b24SSimon Glass 	if (bootz_start(cmdtp, flag, argc, argv, &images))
597*2e192b24SSimon Glass 		return 1;
598*2e192b24SSimon Glass 
599*2e192b24SSimon Glass 	/*
600*2e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
601*2e192b24SSimon Glass 	 * disable interrupts ourselves
602*2e192b24SSimon Glass 	 */
603*2e192b24SSimon Glass 	bootm_disable_interrupts();
604*2e192b24SSimon Glass 
605*2e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
606*2e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
607*2e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
608*2e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
609*2e192b24SSimon Glass 			      &images, 1);
610*2e192b24SSimon Glass 
611*2e192b24SSimon Glass 	return ret;
612*2e192b24SSimon Glass }
613*2e192b24SSimon Glass 
614*2e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
615*2e192b24SSimon Glass static char bootz_help_text[] =
616*2e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
617*2e192b24SSimon Glass 	"    - boot Linux zImage stored in memory\n"
618*2e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
619*2e192b24SSimon Glass 	"\tof the initrd in memory. The optional argument ':size' allows\n"
620*2e192b24SSimon Glass 	"\tspecifying the size of RAW initrd.\n"
621*2e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
622*2e192b24SSimon Glass 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
623*2e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
624*2e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
625*2e192b24SSimon Glass 	"\tuse a '-' for the second argument. If you do not pass a third\n"
626*2e192b24SSimon Glass 	"\ta bd_info struct will be passed instead\n"
627*2e192b24SSimon Glass #endif
628*2e192b24SSimon Glass 	"";
629*2e192b24SSimon Glass #endif
630*2e192b24SSimon Glass 
631*2e192b24SSimon Glass U_BOOT_CMD(
632*2e192b24SSimon Glass 	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
633*2e192b24SSimon Glass 	"boot Linux zImage image from memory", bootz_help_text
634*2e192b24SSimon Glass );
635*2e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTZ */
636*2e192b24SSimon Glass 
637*2e192b24SSimon Glass #ifdef CONFIG_CMD_BOOTI
638*2e192b24SSimon Glass /* See Documentation/arm64/booting.txt in the Linux kernel */
639*2e192b24SSimon Glass struct Image_header {
640*2e192b24SSimon Glass 	uint32_t	code0;		/* Executable code */
641*2e192b24SSimon Glass 	uint32_t	code1;		/* Executable code */
642*2e192b24SSimon Glass 	uint64_t	text_offset;	/* Image load offset, LE */
643*2e192b24SSimon Glass 	uint64_t	image_size;	/* Effective Image size, LE */
644*2e192b24SSimon Glass 	uint64_t	res1;		/* reserved */
645*2e192b24SSimon Glass 	uint64_t	res2;		/* reserved */
646*2e192b24SSimon Glass 	uint64_t	res3;		/* reserved */
647*2e192b24SSimon Glass 	uint64_t	res4;		/* reserved */
648*2e192b24SSimon Glass 	uint32_t	magic;		/* Magic number */
649*2e192b24SSimon Glass 	uint32_t	res5;
650*2e192b24SSimon Glass };
651*2e192b24SSimon Glass 
652*2e192b24SSimon Glass #define LINUX_ARM64_IMAGE_MAGIC	0x644d5241
653*2e192b24SSimon Glass 
654*2e192b24SSimon Glass static int booti_setup(bootm_headers_t *images)
655*2e192b24SSimon Glass {
656*2e192b24SSimon Glass 	struct Image_header *ih;
657*2e192b24SSimon Glass 	uint64_t dst;
658*2e192b24SSimon Glass 
659*2e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
660*2e192b24SSimon Glass 
661*2e192b24SSimon Glass 	if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
662*2e192b24SSimon Glass 		puts("Bad Linux ARM64 Image magic!\n");
663*2e192b24SSimon Glass 		return 1;
664*2e192b24SSimon Glass 	}
665*2e192b24SSimon Glass 
666*2e192b24SSimon Glass 	if (ih->image_size == 0) {
667*2e192b24SSimon Glass 		puts("Image lacks image_size field, assuming 16MiB\n");
668*2e192b24SSimon Glass 		ih->image_size = (16 << 20);
669*2e192b24SSimon Glass 	}
670*2e192b24SSimon Glass 
671*2e192b24SSimon Glass 	/*
672*2e192b24SSimon Glass 	 * If we are not at the correct run-time location, set the new
673*2e192b24SSimon Glass 	 * correct location and then move the image there.
674*2e192b24SSimon Glass 	 */
675*2e192b24SSimon Glass 	dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset);
676*2e192b24SSimon Glass 	if (images->ep != dst) {
677*2e192b24SSimon Glass 		void *src;
678*2e192b24SSimon Glass 
679*2e192b24SSimon Glass 		debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
680*2e192b24SSimon Glass 
681*2e192b24SSimon Glass 		src = (void *)images->ep;
682*2e192b24SSimon Glass 		images->ep = dst;
683*2e192b24SSimon Glass 		memmove((void *)dst, src, le32_to_cpu(ih->image_size));
684*2e192b24SSimon Glass 	}
685*2e192b24SSimon Glass 
686*2e192b24SSimon Glass 	return 0;
687*2e192b24SSimon Glass }
688*2e192b24SSimon Glass 
689*2e192b24SSimon Glass /*
690*2e192b24SSimon Glass  * Image booting support
691*2e192b24SSimon Glass  */
692*2e192b24SSimon Glass static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
693*2e192b24SSimon Glass 			char * const argv[], bootm_headers_t *images)
694*2e192b24SSimon Glass {
695*2e192b24SSimon Glass 	int ret;
696*2e192b24SSimon Glass 	struct Image_header *ih;
697*2e192b24SSimon Glass 
698*2e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
699*2e192b24SSimon Glass 			      images, 1);
700*2e192b24SSimon Glass 
701*2e192b24SSimon Glass 	/* Setup Linux kernel Image entry point */
702*2e192b24SSimon Glass 	if (!argc) {
703*2e192b24SSimon Glass 		images->ep = load_addr;
704*2e192b24SSimon Glass 		debug("*  kernel: default image load address = 0x%08lx\n",
705*2e192b24SSimon Glass 				load_addr);
706*2e192b24SSimon Glass 	} else {
707*2e192b24SSimon Glass 		images->ep = simple_strtoul(argv[0], NULL, 16);
708*2e192b24SSimon Glass 		debug("*  kernel: cmdline image address = 0x%08lx\n",
709*2e192b24SSimon Glass 			images->ep);
710*2e192b24SSimon Glass 	}
711*2e192b24SSimon Glass 
712*2e192b24SSimon Glass 	ret = booti_setup(images);
713*2e192b24SSimon Glass 	if (ret != 0)
714*2e192b24SSimon Glass 		return 1;
715*2e192b24SSimon Glass 
716*2e192b24SSimon Glass 	ih = (struct Image_header *)map_sysmem(images->ep, 0);
717*2e192b24SSimon Glass 
718*2e192b24SSimon Glass 	lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
719*2e192b24SSimon Glass 
720*2e192b24SSimon Glass 	/*
721*2e192b24SSimon Glass 	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
722*2e192b24SSimon Glass 	 * have a header that provide this informaiton.
723*2e192b24SSimon Glass 	 */
724*2e192b24SSimon Glass 	if (bootm_find_images(flag, argc, argv))
725*2e192b24SSimon Glass 		return 1;
726*2e192b24SSimon Glass 
727*2e192b24SSimon Glass 	return 0;
728*2e192b24SSimon Glass }
729*2e192b24SSimon Glass 
730*2e192b24SSimon Glass int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
731*2e192b24SSimon Glass {
732*2e192b24SSimon Glass 	int ret;
733*2e192b24SSimon Glass 
734*2e192b24SSimon Glass 	/* Consume 'booti' */
735*2e192b24SSimon Glass 	argc--; argv++;
736*2e192b24SSimon Glass 
737*2e192b24SSimon Glass 	if (booti_start(cmdtp, flag, argc, argv, &images))
738*2e192b24SSimon Glass 		return 1;
739*2e192b24SSimon Glass 
740*2e192b24SSimon Glass 	/*
741*2e192b24SSimon Glass 	 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
742*2e192b24SSimon Glass 	 * disable interrupts ourselves
743*2e192b24SSimon Glass 	 */
744*2e192b24SSimon Glass 	bootm_disable_interrupts();
745*2e192b24SSimon Glass 
746*2e192b24SSimon Glass 	images.os.os = IH_OS_LINUX;
747*2e192b24SSimon Glass 	ret = do_bootm_states(cmdtp, flag, argc, argv,
748*2e192b24SSimon Glass 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
749*2e192b24SSimon Glass 			      BOOTM_STATE_OS_GO,
750*2e192b24SSimon Glass 			      &images, 1);
751*2e192b24SSimon Glass 
752*2e192b24SSimon Glass 	return ret;
753*2e192b24SSimon Glass }
754*2e192b24SSimon Glass 
755*2e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
756*2e192b24SSimon Glass static char booti_help_text[] =
757*2e192b24SSimon Glass 	"[addr [initrd[:size]] [fdt]]\n"
758*2e192b24SSimon Glass 	"    - boot Linux Image stored in memory\n"
759*2e192b24SSimon Glass 	"\tThe argument 'initrd' is optional and specifies the address\n"
760*2e192b24SSimon Glass 	"\tof the initrd in memory. The optional argument ':size' allows\n"
761*2e192b24SSimon Glass 	"\tspecifying the size of RAW initrd.\n"
762*2e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
763*2e192b24SSimon Glass 	"\tSince booting a Linux kernelrequires a flat device-tree\n"
764*2e192b24SSimon Glass 	"\ta third argument is required which is the address of the\n"
765*2e192b24SSimon Glass 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
766*2e192b24SSimon Glass 	"\tuse a '-' for the second argument.\n"
767*2e192b24SSimon Glass #endif
768*2e192b24SSimon Glass 	"";
769*2e192b24SSimon Glass #endif
770*2e192b24SSimon Glass 
771*2e192b24SSimon Glass U_BOOT_CMD(
772*2e192b24SSimon Glass 	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
773*2e192b24SSimon Glass 	"boot arm64 Linux Image image from memory", booti_help_text
774*2e192b24SSimon Glass );
775*2e192b24SSimon Glass #endif	/* CONFIG_CMD_BOOTI */
776