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