xref: /OK3568_Linux_fs/u-boot/cmd/bootm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2009
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * Boot support
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <bootm.h>
13*4882a593Smuzhiyun #include <command.h>
14*4882a593Smuzhiyun #include <environment.h>
15*4882a593Smuzhiyun #include <errno.h>
16*4882a593Smuzhiyun #include <image.h>
17*4882a593Smuzhiyun #include <malloc.h>
18*4882a593Smuzhiyun #include <nand.h>
19*4882a593Smuzhiyun #include <asm/byteorder.h>
20*4882a593Smuzhiyun #include <linux/ctype.h>
21*4882a593Smuzhiyun #include <linux/err.h>
22*4882a593Smuzhiyun #include <u-boot/zlib.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMI)
27*4882a593Smuzhiyun static int image_info(unsigned long addr);
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS)
31*4882a593Smuzhiyun #include <flash.h>
32*4882a593Smuzhiyun #include <mtd/cfi_flash.h>
33*4882a593Smuzhiyun extern flash_info_t flash_info[]; /* info for FLASH chips */
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
37*4882a593Smuzhiyun static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* we overload the cmd field with our state machine info instead of a
41*4882a593Smuzhiyun  * function pointer */
42*4882a593Smuzhiyun static cmd_tbl_t cmd_bootm_sub[] = {
43*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
44*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
45*4882a593Smuzhiyun #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
46*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
47*4882a593Smuzhiyun #endif
48*4882a593Smuzhiyun #ifdef CONFIG_OF_LIBFDT
49*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
52*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
53*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
54*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
55*4882a593Smuzhiyun 	U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun 
do_bootm_subcommand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])58*4882a593Smuzhiyun static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
59*4882a593Smuzhiyun 			char * const argv[])
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	int ret = 0;
62*4882a593Smuzhiyun 	long state;
63*4882a593Smuzhiyun 	cmd_tbl_t *c;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
66*4882a593Smuzhiyun 	argc--; argv++;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	if (c) {
69*4882a593Smuzhiyun 		state = (long)c->cmd;
70*4882a593Smuzhiyun 		if (state == BOOTM_STATE_START)
71*4882a593Smuzhiyun 			state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
72*4882a593Smuzhiyun 	} else {
73*4882a593Smuzhiyun 		/* Unrecognized command */
74*4882a593Smuzhiyun 		return CMD_RET_USAGE;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
78*4882a593Smuzhiyun 	    images.state >= state) {
79*4882a593Smuzhiyun 		printf("Trying to execute a command out of order\n");
80*4882a593Smuzhiyun 		return CMD_RET_USAGE;
81*4882a593Smuzhiyun 	}
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	return ret;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /*******************************************************************/
89*4882a593Smuzhiyun /* bootm - boot application image from image in memory */
90*4882a593Smuzhiyun /*******************************************************************/
91*4882a593Smuzhiyun 
do_bootm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])92*4882a593Smuzhiyun int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun #ifdef CONFIG_NEEDS_MANUAL_RELOC
95*4882a593Smuzhiyun 	static int relocated = 0;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (!relocated) {
98*4882a593Smuzhiyun 		int i;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 		/* relocate names of sub-command table */
101*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
102*4882a593Smuzhiyun 			cmd_bootm_sub[i].name += gd->reloc_off;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 		relocated = 1;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun #endif
107*4882a593Smuzhiyun 	/* board routines */
108*4882a593Smuzhiyun 	if (board_do_bootm(argc, argv))
109*4882a593Smuzhiyun 		return -EPERM;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* determine if we have a sub command */
112*4882a593Smuzhiyun 	argc--; argv++;
113*4882a593Smuzhiyun 	if (argc > 0) {
114*4882a593Smuzhiyun 		char *endp;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 		simple_strtoul(argv[0], &endp, 16);
117*4882a593Smuzhiyun 		/* endp pointing to NULL means that argv[0] was just a
118*4882a593Smuzhiyun 		 * valid number, pass it along to the normal bootm processing
119*4882a593Smuzhiyun 		 *
120*4882a593Smuzhiyun 		 * If endp is ':' or '#' assume a FIT identifier so pass
121*4882a593Smuzhiyun 		 * along for normal processing.
122*4882a593Smuzhiyun 		 *
123*4882a593Smuzhiyun 		 * Right now we assume the first arg should never be '-'
124*4882a593Smuzhiyun 		 */
125*4882a593Smuzhiyun 		if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
126*4882a593Smuzhiyun 			return do_bootm_subcommand(cmdtp, flag, argc, argv);
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
130*4882a593Smuzhiyun 		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
131*4882a593Smuzhiyun 		BOOTM_STATE_LOADOS |
132*4882a593Smuzhiyun #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
133*4882a593Smuzhiyun 		BOOTM_STATE_RAMDISK |
134*4882a593Smuzhiyun #endif
135*4882a593Smuzhiyun #if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
136*4882a593Smuzhiyun 		BOOTM_STATE_OS_CMDLINE |
137*4882a593Smuzhiyun #endif
138*4882a593Smuzhiyun 		BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
139*4882a593Smuzhiyun 		BOOTM_STATE_OS_GO, &images, 1);
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
bootm_maybe_autostart(cmd_tbl_t * cmdtp,const char * cmd)142*4882a593Smuzhiyun int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	const char *ep = env_get("autostart");
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (ep && !strcmp(ep, "yes")) {
147*4882a593Smuzhiyun 		char *local_args[2];
148*4882a593Smuzhiyun 		local_args[0] = (char *)cmd;
149*4882a593Smuzhiyun 		local_args[1] = NULL;
150*4882a593Smuzhiyun 		printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
151*4882a593Smuzhiyun 		return do_bootm(cmdtp, 0, 1, local_args);
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	return 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #ifdef CONFIG_SYS_LONGHELP
158*4882a593Smuzhiyun static char bootm_help_text[] =
159*4882a593Smuzhiyun 	"[addr [arg ...]]\n    - boot application image stored in memory\n"
160*4882a593Smuzhiyun 	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
161*4882a593Smuzhiyun 	"\t'arg' can be the address of an initrd image\n"
162*4882a593Smuzhiyun #if defined(CONFIG_OF_LIBFDT)
163*4882a593Smuzhiyun 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
164*4882a593Smuzhiyun 	"\ta third argument is required which is the address of the\n"
165*4882a593Smuzhiyun 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
166*4882a593Smuzhiyun 	"\tuse a '-' for the second argument. If you do not pass a third\n"
167*4882a593Smuzhiyun 	"\ta bd_info struct will be passed instead\n"
168*4882a593Smuzhiyun #endif
169*4882a593Smuzhiyun #if defined(CONFIG_FIT)
170*4882a593Smuzhiyun 	"\t\nFor the new multi component uImage format (FIT) addresses\n"
171*4882a593Smuzhiyun 	"\tmust be extended to include component or configuration unit name:\n"
172*4882a593Smuzhiyun 	"\taddr:<subimg_uname> - direct component image specification\n"
173*4882a593Smuzhiyun 	"\taddr#<conf_uname>   - configuration specification\n"
174*4882a593Smuzhiyun 	"\tUse iminfo command to get the list of existing component\n"
175*4882a593Smuzhiyun 	"\timages and configurations.\n"
176*4882a593Smuzhiyun #endif
177*4882a593Smuzhiyun 	"\nSub-commands to do part of the bootm sequence.  The sub-commands "
178*4882a593Smuzhiyun 	"must be\n"
179*4882a593Smuzhiyun 	"issued in the order below (it's ok to not issue all sub-commands):\n"
180*4882a593Smuzhiyun 	"\tstart [addr [arg ...]]\n"
181*4882a593Smuzhiyun 	"\tloados  - load OS image\n"
182*4882a593Smuzhiyun #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
183*4882a593Smuzhiyun 	"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
184*4882a593Smuzhiyun #endif
185*4882a593Smuzhiyun #if defined(CONFIG_OF_LIBFDT)
186*4882a593Smuzhiyun 	"\tfdt     - relocate flat device tree\n"
187*4882a593Smuzhiyun #endif
188*4882a593Smuzhiyun 	"\tcmdline - OS specific command line processing/setup\n"
189*4882a593Smuzhiyun 	"\tbdt     - OS specific bd_t processing\n"
190*4882a593Smuzhiyun 	"\tprep    - OS specific prep before relocation or go\n"
191*4882a593Smuzhiyun #if defined(CONFIG_TRACE)
192*4882a593Smuzhiyun 	"\tfake    - OS specific fake start without go\n"
193*4882a593Smuzhiyun #endif
194*4882a593Smuzhiyun 	"\tgo      - start OS";
195*4882a593Smuzhiyun #endif
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun U_BOOT_CMD(
198*4882a593Smuzhiyun 	bootm,	CONFIG_SYS_MAXARGS,	1,	do_bootm,
199*4882a593Smuzhiyun 	"boot application image from memory", bootm_help_text
200*4882a593Smuzhiyun );
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun /*******************************************************************/
203*4882a593Smuzhiyun /* bootd - boot default image */
204*4882a593Smuzhiyun /*******************************************************************/
205*4882a593Smuzhiyun #if defined(CONFIG_CMD_BOOTD)
do_bootd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])206*4882a593Smuzhiyun int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	return run_command(env_get("bootcmd"), flag);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun U_BOOT_CMD(
212*4882a593Smuzhiyun 	boot,	1,	1,	do_bootd,
213*4882a593Smuzhiyun 	"boot default, i.e., run 'bootcmd'",
214*4882a593Smuzhiyun 	""
215*4882a593Smuzhiyun );
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun /* keep old command name "bootd" for backward compatibility */
218*4882a593Smuzhiyun U_BOOT_CMD(
219*4882a593Smuzhiyun 	bootd, 1,	1,	do_bootd,
220*4882a593Smuzhiyun 	"boot default, i.e., run 'bootcmd'",
221*4882a593Smuzhiyun 	""
222*4882a593Smuzhiyun );
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #endif
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun /*******************************************************************/
228*4882a593Smuzhiyun /* iminfo - print header info for a requested image */
229*4882a593Smuzhiyun /*******************************************************************/
230*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMI)
do_iminfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])231*4882a593Smuzhiyun static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	int	arg;
234*4882a593Smuzhiyun 	ulong	addr;
235*4882a593Smuzhiyun 	int	rcode = 0;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	if (argc < 2) {
238*4882a593Smuzhiyun 		return image_info(load_addr);
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	for (arg = 1; arg < argc; ++arg) {
242*4882a593Smuzhiyun 		addr = simple_strtoul(argv[arg], NULL, 16);
243*4882a593Smuzhiyun 		if (image_info(addr) != 0)
244*4882a593Smuzhiyun 			rcode = 1;
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun 	return rcode;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
image_info(ulong addr)249*4882a593Smuzhiyun static int image_info(ulong addr)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	void *hdr = (void *)addr;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	printf("\n## Checking Image at %08lx ...\n", addr);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	switch (genimg_get_format(hdr)) {
256*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
257*4882a593Smuzhiyun 	case IMAGE_FORMAT_LEGACY:
258*4882a593Smuzhiyun 		puts("   Legacy image found\n");
259*4882a593Smuzhiyun 		if (!image_check_magic(hdr)) {
260*4882a593Smuzhiyun 			puts("   Bad Magic Number\n");
261*4882a593Smuzhiyun 			return 1;
262*4882a593Smuzhiyun 		}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		if (!image_check_hcrc(hdr)) {
265*4882a593Smuzhiyun 			puts("   Bad Header Checksum\n");
266*4882a593Smuzhiyun 			return 1;
267*4882a593Smuzhiyun 		}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		image_print_contents(hdr);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 		puts("   Verifying Checksum ... ");
272*4882a593Smuzhiyun 		if (!image_check_dcrc(hdr)) {
273*4882a593Smuzhiyun 			puts("   Bad Data CRC\n");
274*4882a593Smuzhiyun 			return 1;
275*4882a593Smuzhiyun 		}
276*4882a593Smuzhiyun 		puts("OK\n");
277*4882a593Smuzhiyun 		return 0;
278*4882a593Smuzhiyun #endif
279*4882a593Smuzhiyun #if defined(CONFIG_ANDROID_BOOT_IMAGE)
280*4882a593Smuzhiyun 	case IMAGE_FORMAT_ANDROID:
281*4882a593Smuzhiyun 		puts("   Android image found\n");
282*4882a593Smuzhiyun 		android_print_contents(hdr);
283*4882a593Smuzhiyun 		return 0;
284*4882a593Smuzhiyun #endif
285*4882a593Smuzhiyun #if defined(CONFIG_FIT)
286*4882a593Smuzhiyun 	case IMAGE_FORMAT_FIT:
287*4882a593Smuzhiyun 		puts("   FIT image found\n");
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 		if (!fit_check_format(hdr)) {
290*4882a593Smuzhiyun 			puts("Bad FIT image format!\n");
291*4882a593Smuzhiyun 			return 1;
292*4882a593Smuzhiyun 		}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 		fit_print_contents(hdr);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 		if (!fit_all_image_verify(hdr)) {
297*4882a593Smuzhiyun 			puts("Bad hash in FIT image!\n");
298*4882a593Smuzhiyun 			return 1;
299*4882a593Smuzhiyun 		}
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 		return 0;
302*4882a593Smuzhiyun #endif
303*4882a593Smuzhiyun 	default:
304*4882a593Smuzhiyun 		puts("Unknown image format!\n");
305*4882a593Smuzhiyun 		break;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return 1;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun U_BOOT_CMD(
312*4882a593Smuzhiyun 	iminfo,	CONFIG_SYS_MAXARGS,	1,	do_iminfo,
313*4882a593Smuzhiyun 	"print header information for application image",
314*4882a593Smuzhiyun 	"addr [addr ...]\n"
315*4882a593Smuzhiyun 	"    - print header information for application image starting at\n"
316*4882a593Smuzhiyun 	"      address 'addr' in memory; this includes verification of the\n"
317*4882a593Smuzhiyun 	"      image contents (magic number, header and payload checksums)"
318*4882a593Smuzhiyun );
319*4882a593Smuzhiyun #endif
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun /*******************************************************************/
323*4882a593Smuzhiyun /* imls - list all images found in flash */
324*4882a593Smuzhiyun /*******************************************************************/
325*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS)
do_imls_nor(void)326*4882a593Smuzhiyun static int do_imls_nor(void)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	flash_info_t *info;
329*4882a593Smuzhiyun 	int i, j;
330*4882a593Smuzhiyun 	void *hdr;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	for (i = 0, info = &flash_info[0];
333*4882a593Smuzhiyun 		i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 		if (info->flash_id == FLASH_UNKNOWN)
336*4882a593Smuzhiyun 			goto next_bank;
337*4882a593Smuzhiyun 		for (j = 0; j < info->sector_count; ++j) {
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 			hdr = (void *)info->start[j];
340*4882a593Smuzhiyun 			if (!hdr)
341*4882a593Smuzhiyun 				goto next_sector;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 			switch (genimg_get_format(hdr)) {
344*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
345*4882a593Smuzhiyun 			case IMAGE_FORMAT_LEGACY:
346*4882a593Smuzhiyun 				if (!image_check_hcrc(hdr))
347*4882a593Smuzhiyun 					goto next_sector;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 				printf("Legacy Image at %08lX:\n", (ulong)hdr);
350*4882a593Smuzhiyun 				image_print_contents(hdr);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 				puts("   Verifying Checksum ... ");
353*4882a593Smuzhiyun 				if (!image_check_dcrc(hdr)) {
354*4882a593Smuzhiyun 					puts("Bad Data CRC\n");
355*4882a593Smuzhiyun 				} else {
356*4882a593Smuzhiyun 					puts("OK\n");
357*4882a593Smuzhiyun 				}
358*4882a593Smuzhiyun 				break;
359*4882a593Smuzhiyun #endif
360*4882a593Smuzhiyun #if defined(CONFIG_FIT)
361*4882a593Smuzhiyun 			case IMAGE_FORMAT_FIT:
362*4882a593Smuzhiyun 				if (!fit_check_format(hdr))
363*4882a593Smuzhiyun 					goto next_sector;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 				printf("FIT Image at %08lX:\n", (ulong)hdr);
366*4882a593Smuzhiyun 				fit_print_contents(hdr);
367*4882a593Smuzhiyun 				break;
368*4882a593Smuzhiyun #endif
369*4882a593Smuzhiyun 			default:
370*4882a593Smuzhiyun 				goto next_sector;
371*4882a593Smuzhiyun 			}
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun next_sector:		;
374*4882a593Smuzhiyun 		}
375*4882a593Smuzhiyun next_bank:	;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 	return 0;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun #endif
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS_NAND)
nand_imls_legacyimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)382*4882a593Smuzhiyun static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
383*4882a593Smuzhiyun 				 loff_t off, size_t len)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	void *imgdata;
386*4882a593Smuzhiyun 	int ret;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	imgdata = malloc(len);
389*4882a593Smuzhiyun 	if (!imgdata) {
390*4882a593Smuzhiyun 		printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
391*4882a593Smuzhiyun 				nand_dev, off);
392*4882a593Smuzhiyun 		printf("   Low memory(cannot allocate memory for image)\n");
393*4882a593Smuzhiyun 		return -ENOMEM;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
397*4882a593Smuzhiyun 	if (ret < 0 && ret != -EUCLEAN) {
398*4882a593Smuzhiyun 		free(imgdata);
399*4882a593Smuzhiyun 		return ret;
400*4882a593Smuzhiyun 	}
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	if (!image_check_hcrc(imgdata)) {
403*4882a593Smuzhiyun 		free(imgdata);
404*4882a593Smuzhiyun 		return 0;
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	printf("Legacy Image at NAND device %d offset %08llX:\n",
408*4882a593Smuzhiyun 			nand_dev, off);
409*4882a593Smuzhiyun 	image_print_contents(imgdata);
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	puts("   Verifying Checksum ... ");
412*4882a593Smuzhiyun 	if (!image_check_dcrc(imgdata))
413*4882a593Smuzhiyun 		puts("Bad Data CRC\n");
414*4882a593Smuzhiyun 	else
415*4882a593Smuzhiyun 		puts("OK\n");
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	free(imgdata);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
nand_imls_fitimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)422*4882a593Smuzhiyun static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
423*4882a593Smuzhiyun 			      size_t len)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	void *imgdata;
426*4882a593Smuzhiyun 	int ret;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	imgdata = malloc(len);
429*4882a593Smuzhiyun 	if (!imgdata) {
430*4882a593Smuzhiyun 		printf("May be a FIT Image at NAND device %d offset %08llX:\n",
431*4882a593Smuzhiyun 				nand_dev, off);
432*4882a593Smuzhiyun 		printf("   Low memory(cannot allocate memory for image)\n");
433*4882a593Smuzhiyun 		return -ENOMEM;
434*4882a593Smuzhiyun 	}
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
437*4882a593Smuzhiyun 	if (ret < 0 && ret != -EUCLEAN) {
438*4882a593Smuzhiyun 		free(imgdata);
439*4882a593Smuzhiyun 		return ret;
440*4882a593Smuzhiyun 	}
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (!fit_check_format(imgdata)) {
443*4882a593Smuzhiyun 		free(imgdata);
444*4882a593Smuzhiyun 		return 0;
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	fit_print_contents(imgdata);
450*4882a593Smuzhiyun 	free(imgdata);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
do_imls_nand(void)455*4882a593Smuzhiyun static int do_imls_nand(void)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	struct mtd_info *mtd;
458*4882a593Smuzhiyun 	int nand_dev = nand_curr_device;
459*4882a593Smuzhiyun 	size_t len;
460*4882a593Smuzhiyun 	loff_t off;
461*4882a593Smuzhiyun 	u32 buffer[16];
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
464*4882a593Smuzhiyun 		puts("\nNo NAND devices available\n");
465*4882a593Smuzhiyun 		return -ENODEV;
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	printf("\n");
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
471*4882a593Smuzhiyun 		mtd = get_nand_dev_by_index(nand_dev);
472*4882a593Smuzhiyun 		if (!mtd->name || !mtd->size)
473*4882a593Smuzhiyun 			continue;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 		for (off = 0; off < mtd->size; off += mtd->erasesize) {
476*4882a593Smuzhiyun 			const image_header_t *header;
477*4882a593Smuzhiyun 			int ret;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 			if (nand_block_isbad(mtd, off))
480*4882a593Smuzhiyun 				continue;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 			len = sizeof(buffer);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 			ret = nand_read(mtd, off, &len, (u8 *)buffer);
485*4882a593Smuzhiyun 			if (ret < 0 && ret != -EUCLEAN) {
486*4882a593Smuzhiyun 				printf("NAND read error %d at offset %08llX\n",
487*4882a593Smuzhiyun 						ret, off);
488*4882a593Smuzhiyun 				continue;
489*4882a593Smuzhiyun 			}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 			switch (genimg_get_format(buffer)) {
492*4882a593Smuzhiyun #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
493*4882a593Smuzhiyun 			case IMAGE_FORMAT_LEGACY:
494*4882a593Smuzhiyun 				header = (const image_header_t *)buffer;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 				len = image_get_image_size(header);
497*4882a593Smuzhiyun 				nand_imls_legacyimage(mtd, nand_dev, off, len);
498*4882a593Smuzhiyun 				break;
499*4882a593Smuzhiyun #endif
500*4882a593Smuzhiyun #if defined(CONFIG_FIT)
501*4882a593Smuzhiyun 			case IMAGE_FORMAT_FIT:
502*4882a593Smuzhiyun 				len = fit_get_size(buffer);
503*4882a593Smuzhiyun 				nand_imls_fitimage(mtd, nand_dev, off, len);
504*4882a593Smuzhiyun 				break;
505*4882a593Smuzhiyun #endif
506*4882a593Smuzhiyun 			}
507*4882a593Smuzhiyun 		}
508*4882a593Smuzhiyun 	}
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	return 0;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun #endif
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
do_imls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])515*4882a593Smuzhiyun static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun 	int ret_nor = 0, ret_nand = 0;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS)
520*4882a593Smuzhiyun 	ret_nor = do_imls_nor();
521*4882a593Smuzhiyun #endif
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun #if defined(CONFIG_CMD_IMLS_NAND)
524*4882a593Smuzhiyun 	ret_nand = do_imls_nand();
525*4882a593Smuzhiyun #endif
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	if (ret_nor)
528*4882a593Smuzhiyun 		return ret_nor;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	if (ret_nand)
531*4882a593Smuzhiyun 		return ret_nand;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	return (0);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun U_BOOT_CMD(
537*4882a593Smuzhiyun 	imls,	1,		1,	do_imls,
538*4882a593Smuzhiyun 	"list all images found in flash",
539*4882a593Smuzhiyun 	"\n"
540*4882a593Smuzhiyun 	"    - Prints information about all images found at sector/block\n"
541*4882a593Smuzhiyun 	"      boundaries in nor/nand flash."
542*4882a593Smuzhiyun );
543*4882a593Smuzhiyun #endif
544