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 <malloc.h>
182e192b24SSimon Glass #include <nand.h>
192e192b24SSimon Glass #include <asm/byteorder.h>
202e192b24SSimon Glass #include <linux/ctype.h>
212e192b24SSimon Glass #include <linux/err.h>
222e192b24SSimon Glass #include <u-boot/zlib.h>
232e192b24SSimon Glass
242e192b24SSimon Glass DECLARE_GLOBAL_DATA_PTR;
252e192b24SSimon Glass
262e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
272e192b24SSimon Glass static int image_info(unsigned long addr);
282e192b24SSimon Glass #endif
292e192b24SSimon Glass
302e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
312e192b24SSimon Glass #include <flash.h>
322e192b24SSimon Glass #include <mtd/cfi_flash.h>
332e192b24SSimon Glass extern flash_info_t flash_info[]; /* info for FLASH chips */
342e192b24SSimon Glass #endif
352e192b24SSimon Glass
362e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
372e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
382e192b24SSimon Glass #endif
392e192b24SSimon Glass
402e192b24SSimon Glass /* we overload the cmd field with our state machine info instead of a
412e192b24SSimon Glass * function pointer */
422e192b24SSimon Glass static cmd_tbl_t cmd_bootm_sub[] = {
432e192b24SSimon Glass U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
442e192b24SSimon Glass U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
452e192b24SSimon Glass #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
462e192b24SSimon Glass U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
472e192b24SSimon Glass #endif
482e192b24SSimon Glass #ifdef CONFIG_OF_LIBFDT
492e192b24SSimon Glass U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
502e192b24SSimon Glass #endif
512e192b24SSimon Glass U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
522e192b24SSimon Glass U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
532e192b24SSimon Glass U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
542e192b24SSimon Glass U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
552e192b24SSimon Glass U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
562e192b24SSimon Glass };
572e192b24SSimon Glass
do_bootm_subcommand(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])582e192b24SSimon Glass static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
592e192b24SSimon Glass char * const argv[])
602e192b24SSimon Glass {
612e192b24SSimon Glass int ret = 0;
622e192b24SSimon Glass long state;
632e192b24SSimon Glass cmd_tbl_t *c;
642e192b24SSimon Glass
652e192b24SSimon Glass c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
662e192b24SSimon Glass argc--; argv++;
672e192b24SSimon Glass
682e192b24SSimon Glass if (c) {
692e192b24SSimon Glass state = (long)c->cmd;
702e192b24SSimon Glass if (state == BOOTM_STATE_START)
712e192b24SSimon Glass state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
722e192b24SSimon Glass } else {
732e192b24SSimon Glass /* Unrecognized command */
742e192b24SSimon Glass return CMD_RET_USAGE;
752e192b24SSimon Glass }
762e192b24SSimon Glass
772e192b24SSimon Glass if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
782e192b24SSimon Glass images.state >= state) {
792e192b24SSimon Glass printf("Trying to execute a command out of order\n");
802e192b24SSimon Glass return CMD_RET_USAGE;
812e192b24SSimon Glass }
822e192b24SSimon Glass
832e192b24SSimon Glass ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
842e192b24SSimon Glass
852e192b24SSimon Glass return ret;
862e192b24SSimon Glass }
872e192b24SSimon Glass
882e192b24SSimon Glass /*******************************************************************/
892e192b24SSimon Glass /* bootm - boot application image from image in memory */
902e192b24SSimon Glass /*******************************************************************/
912e192b24SSimon Glass
do_bootm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])922e192b24SSimon Glass int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
932e192b24SSimon Glass {
942e192b24SSimon Glass #ifdef CONFIG_NEEDS_MANUAL_RELOC
952e192b24SSimon Glass static int relocated = 0;
962e192b24SSimon Glass
972e192b24SSimon Glass if (!relocated) {
982e192b24SSimon Glass int i;
992e192b24SSimon Glass
1002e192b24SSimon Glass /* relocate names of sub-command table */
1012e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
1022e192b24SSimon Glass cmd_bootm_sub[i].name += gd->reloc_off;
1032e192b24SSimon Glass
1042e192b24SSimon Glass relocated = 1;
1052e192b24SSimon Glass }
1062e192b24SSimon Glass #endif
107*998aeb5fSJoseph Chen /* board routines */
108*998aeb5fSJoseph Chen if (board_do_bootm(argc, argv))
109*998aeb5fSJoseph Chen return -EPERM;
1102e192b24SSimon Glass
1112e192b24SSimon Glass /* determine if we have a sub command */
1122e192b24SSimon Glass argc--; argv++;
1132e192b24SSimon Glass if (argc > 0) {
1142e192b24SSimon Glass char *endp;
1152e192b24SSimon Glass
1162e192b24SSimon Glass simple_strtoul(argv[0], &endp, 16);
1172e192b24SSimon Glass /* endp pointing to NULL means that argv[0] was just a
1182e192b24SSimon Glass * valid number, pass it along to the normal bootm processing
1192e192b24SSimon Glass *
1202e192b24SSimon Glass * If endp is ':' or '#' assume a FIT identifier so pass
1212e192b24SSimon Glass * along for normal processing.
1222e192b24SSimon Glass *
1232e192b24SSimon Glass * Right now we assume the first arg should never be '-'
1242e192b24SSimon Glass */
1252e192b24SSimon Glass if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
1262e192b24SSimon Glass return do_bootm_subcommand(cmdtp, flag, argc, argv);
1272e192b24SSimon Glass }
1282e192b24SSimon Glass
1292e192b24SSimon Glass return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
1302e192b24SSimon Glass BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
1312e192b24SSimon Glass BOOTM_STATE_LOADOS |
132c2e7e72bSRick Altherr #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
133c2e7e72bSRick Altherr BOOTM_STATE_RAMDISK |
134c2e7e72bSRick Altherr #endif
1352e192b24SSimon Glass #if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
1362e192b24SSimon Glass BOOTM_STATE_OS_CMDLINE |
1372e192b24SSimon Glass #endif
1382e192b24SSimon Glass BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
1392e192b24SSimon Glass BOOTM_STATE_OS_GO, &images, 1);
1402e192b24SSimon Glass }
1412e192b24SSimon Glass
bootm_maybe_autostart(cmd_tbl_t * cmdtp,const char * cmd)1422e192b24SSimon Glass int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
1432e192b24SSimon Glass {
14400caae6dSSimon Glass const char *ep = env_get("autostart");
1452e192b24SSimon Glass
1462e192b24SSimon Glass if (ep && !strcmp(ep, "yes")) {
1472e192b24SSimon Glass char *local_args[2];
1482e192b24SSimon Glass local_args[0] = (char *)cmd;
1492e192b24SSimon Glass local_args[1] = NULL;
1502e192b24SSimon Glass printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
1512e192b24SSimon Glass return do_bootm(cmdtp, 0, 1, local_args);
1522e192b24SSimon Glass }
1532e192b24SSimon Glass
1542e192b24SSimon Glass return 0;
1552e192b24SSimon Glass }
1562e192b24SSimon Glass
1572e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP
1582e192b24SSimon Glass static char bootm_help_text[] =
1592e192b24SSimon Glass "[addr [arg ...]]\n - boot application image stored in memory\n"
1602e192b24SSimon Glass "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
1612e192b24SSimon Glass "\t'arg' can be the address of an initrd image\n"
1622e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
1632e192b24SSimon Glass "\tWhen booting a Linux kernel which requires a flat device-tree\n"
1642e192b24SSimon Glass "\ta third argument is required which is the address of the\n"
1652e192b24SSimon Glass "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
1662e192b24SSimon Glass "\tuse a '-' for the second argument. If you do not pass a third\n"
1672e192b24SSimon Glass "\ta bd_info struct will be passed instead\n"
1682e192b24SSimon Glass #endif
1692e192b24SSimon Glass #if defined(CONFIG_FIT)
1702e192b24SSimon Glass "\t\nFor the new multi component uImage format (FIT) addresses\n"
171da1a3bd4SVagrant Cascadian "\tmust be extended to include component or configuration unit name:\n"
1722e192b24SSimon Glass "\taddr:<subimg_uname> - direct component image specification\n"
1732e192b24SSimon Glass "\taddr#<conf_uname> - configuration specification\n"
1742e192b24SSimon Glass "\tUse iminfo command to get the list of existing component\n"
1752e192b24SSimon Glass "\timages and configurations.\n"
1762e192b24SSimon Glass #endif
1772e192b24SSimon Glass "\nSub-commands to do part of the bootm sequence. The sub-commands "
1782e192b24SSimon Glass "must be\n"
1792e192b24SSimon Glass "issued in the order below (it's ok to not issue all sub-commands):\n"
1802e192b24SSimon Glass "\tstart [addr [arg ...]]\n"
1812e192b24SSimon Glass "\tloados - load OS image\n"
1822e192b24SSimon Glass #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
1832e192b24SSimon Glass "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
1842e192b24SSimon Glass #endif
1852e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT)
1862e192b24SSimon Glass "\tfdt - relocate flat device tree\n"
1872e192b24SSimon Glass #endif
1882e192b24SSimon Glass "\tcmdline - OS specific command line processing/setup\n"
1892e192b24SSimon Glass "\tbdt - OS specific bd_t processing\n"
1902e192b24SSimon Glass "\tprep - OS specific prep before relocation or go\n"
1912e192b24SSimon Glass #if defined(CONFIG_TRACE)
1922e192b24SSimon Glass "\tfake - OS specific fake start without go\n"
1932e192b24SSimon Glass #endif
1942e192b24SSimon Glass "\tgo - start OS";
1952e192b24SSimon Glass #endif
1962e192b24SSimon Glass
1972e192b24SSimon Glass U_BOOT_CMD(
1982e192b24SSimon Glass bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
1992e192b24SSimon Glass "boot application image from memory", bootm_help_text
2002e192b24SSimon Glass );
2012e192b24SSimon Glass
2022e192b24SSimon Glass /*******************************************************************/
2032e192b24SSimon Glass /* bootd - boot default image */
2042e192b24SSimon Glass /*******************************************************************/
2052e192b24SSimon Glass #if defined(CONFIG_CMD_BOOTD)
do_bootd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2062e192b24SSimon Glass int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2072e192b24SSimon Glass {
20800caae6dSSimon Glass return run_command(env_get("bootcmd"), flag);
2092e192b24SSimon Glass }
2102e192b24SSimon Glass
2112e192b24SSimon Glass U_BOOT_CMD(
2122e192b24SSimon Glass boot, 1, 1, do_bootd,
2132e192b24SSimon Glass "boot default, i.e., run 'bootcmd'",
2142e192b24SSimon Glass ""
2152e192b24SSimon Glass );
2162e192b24SSimon Glass
2172e192b24SSimon Glass /* keep old command name "bootd" for backward compatibility */
2182e192b24SSimon Glass U_BOOT_CMD(
2192e192b24SSimon Glass bootd, 1, 1, do_bootd,
2202e192b24SSimon Glass "boot default, i.e., run 'bootcmd'",
2212e192b24SSimon Glass ""
2222e192b24SSimon Glass );
2232e192b24SSimon Glass
2242e192b24SSimon Glass #endif
2252e192b24SSimon Glass
2262e192b24SSimon Glass
2272e192b24SSimon Glass /*******************************************************************/
2282e192b24SSimon Glass /* iminfo - print header info for a requested image */
2292e192b24SSimon Glass /*******************************************************************/
2302e192b24SSimon Glass #if defined(CONFIG_CMD_IMI)
do_iminfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2312e192b24SSimon Glass static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2322e192b24SSimon Glass {
2332e192b24SSimon Glass int arg;
2342e192b24SSimon Glass ulong addr;
2352e192b24SSimon Glass int rcode = 0;
2362e192b24SSimon Glass
2372e192b24SSimon Glass if (argc < 2) {
2382e192b24SSimon Glass return image_info(load_addr);
2392e192b24SSimon Glass }
2402e192b24SSimon Glass
2412e192b24SSimon Glass for (arg = 1; arg < argc; ++arg) {
2422e192b24SSimon Glass addr = simple_strtoul(argv[arg], NULL, 16);
2432e192b24SSimon Glass if (image_info(addr) != 0)
2442e192b24SSimon Glass rcode = 1;
2452e192b24SSimon Glass }
2462e192b24SSimon Glass return rcode;
2472e192b24SSimon Glass }
2482e192b24SSimon Glass
image_info(ulong addr)2492e192b24SSimon Glass static int image_info(ulong addr)
2502e192b24SSimon Glass {
2512e192b24SSimon Glass void *hdr = (void *)addr;
2522e192b24SSimon Glass
2532e192b24SSimon Glass printf("\n## Checking Image at %08lx ...\n", addr);
2542e192b24SSimon Glass
2552e192b24SSimon Glass switch (genimg_get_format(hdr)) {
2562e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
2572e192b24SSimon Glass case IMAGE_FORMAT_LEGACY:
2582e192b24SSimon Glass puts(" Legacy image found\n");
2592e192b24SSimon Glass if (!image_check_magic(hdr)) {
2602e192b24SSimon Glass puts(" Bad Magic Number\n");
2612e192b24SSimon Glass return 1;
2622e192b24SSimon Glass }
2632e192b24SSimon Glass
2642e192b24SSimon Glass if (!image_check_hcrc(hdr)) {
2652e192b24SSimon Glass puts(" Bad Header Checksum\n");
2662e192b24SSimon Glass return 1;
2672e192b24SSimon Glass }
2682e192b24SSimon Glass
2692e192b24SSimon Glass image_print_contents(hdr);
2702e192b24SSimon Glass
2712e192b24SSimon Glass puts(" Verifying Checksum ... ");
2722e192b24SSimon Glass if (!image_check_dcrc(hdr)) {
2732e192b24SSimon Glass puts(" Bad Data CRC\n");
2742e192b24SSimon Glass return 1;
2752e192b24SSimon Glass }
2762e192b24SSimon Glass puts("OK\n");
2772e192b24SSimon Glass return 0;
2782e192b24SSimon Glass #endif
2794f1318b2SMichael Trimarchi #if defined(CONFIG_ANDROID_BOOT_IMAGE)
2804f1318b2SMichael Trimarchi case IMAGE_FORMAT_ANDROID:
2814f1318b2SMichael Trimarchi puts(" Android image found\n");
2824f1318b2SMichael Trimarchi android_print_contents(hdr);
2834f1318b2SMichael Trimarchi return 0;
2844f1318b2SMichael Trimarchi #endif
2852e192b24SSimon Glass #if defined(CONFIG_FIT)
2862e192b24SSimon Glass case IMAGE_FORMAT_FIT:
2872e192b24SSimon Glass puts(" FIT image found\n");
2882e192b24SSimon Glass
2892e192b24SSimon Glass if (!fit_check_format(hdr)) {
2902e192b24SSimon Glass puts("Bad FIT image format!\n");
2912e192b24SSimon Glass return 1;
2922e192b24SSimon Glass }
2932e192b24SSimon Glass
2942e192b24SSimon Glass fit_print_contents(hdr);
2952e192b24SSimon Glass
2962e192b24SSimon Glass if (!fit_all_image_verify(hdr)) {
2972e192b24SSimon Glass puts("Bad hash in FIT image!\n");
2982e192b24SSimon Glass return 1;
2992e192b24SSimon Glass }
3002e192b24SSimon Glass
3012e192b24SSimon Glass return 0;
3022e192b24SSimon Glass #endif
3032e192b24SSimon Glass default:
3042e192b24SSimon Glass puts("Unknown image format!\n");
3052e192b24SSimon Glass break;
3062e192b24SSimon Glass }
3072e192b24SSimon Glass
3082e192b24SSimon Glass return 1;
3092e192b24SSimon Glass }
3102e192b24SSimon Glass
3112e192b24SSimon Glass U_BOOT_CMD(
3122e192b24SSimon Glass iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
3132e192b24SSimon Glass "print header information for application image",
3142e192b24SSimon Glass "addr [addr ...]\n"
3152e192b24SSimon Glass " - print header information for application image starting at\n"
3162e192b24SSimon Glass " address 'addr' in memory; this includes verification of the\n"
3172e192b24SSimon Glass " image contents (magic number, header and payload checksums)"
3182e192b24SSimon Glass );
3192e192b24SSimon Glass #endif
3202e192b24SSimon Glass
3212e192b24SSimon Glass
3222e192b24SSimon Glass /*******************************************************************/
3232e192b24SSimon Glass /* imls - list all images found in flash */
3242e192b24SSimon Glass /*******************************************************************/
3252e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
do_imls_nor(void)3262e192b24SSimon Glass static int do_imls_nor(void)
3272e192b24SSimon Glass {
3282e192b24SSimon Glass flash_info_t *info;
3292e192b24SSimon Glass int i, j;
3302e192b24SSimon Glass void *hdr;
3312e192b24SSimon Glass
3322e192b24SSimon Glass for (i = 0, info = &flash_info[0];
3332e192b24SSimon Glass i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
3342e192b24SSimon Glass
3352e192b24SSimon Glass if (info->flash_id == FLASH_UNKNOWN)
3362e192b24SSimon Glass goto next_bank;
3372e192b24SSimon Glass for (j = 0; j < info->sector_count; ++j) {
3382e192b24SSimon Glass
3392e192b24SSimon Glass hdr = (void *)info->start[j];
3402e192b24SSimon Glass if (!hdr)
3412e192b24SSimon Glass goto next_sector;
3422e192b24SSimon Glass
3432e192b24SSimon Glass switch (genimg_get_format(hdr)) {
3442e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
3452e192b24SSimon Glass case IMAGE_FORMAT_LEGACY:
3462e192b24SSimon Glass if (!image_check_hcrc(hdr))
3472e192b24SSimon Glass goto next_sector;
3482e192b24SSimon Glass
3492e192b24SSimon Glass printf("Legacy Image at %08lX:\n", (ulong)hdr);
3502e192b24SSimon Glass image_print_contents(hdr);
3512e192b24SSimon Glass
3522e192b24SSimon Glass puts(" Verifying Checksum ... ");
3532e192b24SSimon Glass if (!image_check_dcrc(hdr)) {
3542e192b24SSimon Glass puts("Bad Data CRC\n");
3552e192b24SSimon Glass } else {
3562e192b24SSimon Glass puts("OK\n");
3572e192b24SSimon Glass }
3582e192b24SSimon Glass break;
3592e192b24SSimon Glass #endif
3602e192b24SSimon Glass #if defined(CONFIG_FIT)
3612e192b24SSimon Glass case IMAGE_FORMAT_FIT:
3622e192b24SSimon Glass if (!fit_check_format(hdr))
3632e192b24SSimon Glass goto next_sector;
3642e192b24SSimon Glass
3652e192b24SSimon Glass printf("FIT Image at %08lX:\n", (ulong)hdr);
3662e192b24SSimon Glass fit_print_contents(hdr);
3672e192b24SSimon Glass break;
3682e192b24SSimon Glass #endif
3692e192b24SSimon Glass default:
3702e192b24SSimon Glass goto next_sector;
3712e192b24SSimon Glass }
3722e192b24SSimon Glass
3732e192b24SSimon Glass next_sector: ;
3742e192b24SSimon Glass }
3752e192b24SSimon Glass next_bank: ;
3762e192b24SSimon Glass }
3772e192b24SSimon Glass return 0;
3782e192b24SSimon Glass }
3792e192b24SSimon Glass #endif
3802e192b24SSimon Glass
3812e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
nand_imls_legacyimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)382151c06ecSScott Wood static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
383151c06ecSScott Wood loff_t off, size_t len)
3842e192b24SSimon Glass {
3852e192b24SSimon Glass void *imgdata;
3862e192b24SSimon Glass int ret;
3872e192b24SSimon Glass
3882e192b24SSimon Glass imgdata = malloc(len);
3892e192b24SSimon Glass if (!imgdata) {
3902e192b24SSimon Glass printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
3912e192b24SSimon Glass nand_dev, off);
3922e192b24SSimon Glass printf(" Low memory(cannot allocate memory for image)\n");
3932e192b24SSimon Glass return -ENOMEM;
3942e192b24SSimon Glass }
3952e192b24SSimon Glass
396dbe7881dSGrygorii Strashko ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
3972e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) {
3982e192b24SSimon Glass free(imgdata);
3992e192b24SSimon Glass return ret;
4002e192b24SSimon Glass }
4012e192b24SSimon Glass
4022e192b24SSimon Glass if (!image_check_hcrc(imgdata)) {
4032e192b24SSimon Glass free(imgdata);
4042e192b24SSimon Glass return 0;
4052e192b24SSimon Glass }
4062e192b24SSimon Glass
4072e192b24SSimon Glass printf("Legacy Image at NAND device %d offset %08llX:\n",
4082e192b24SSimon Glass nand_dev, off);
4092e192b24SSimon Glass image_print_contents(imgdata);
4102e192b24SSimon Glass
4112e192b24SSimon Glass puts(" Verifying Checksum ... ");
4122e192b24SSimon Glass if (!image_check_dcrc(imgdata))
4132e192b24SSimon Glass puts("Bad Data CRC\n");
4142e192b24SSimon Glass else
4152e192b24SSimon Glass puts("OK\n");
4162e192b24SSimon Glass
4172e192b24SSimon Glass free(imgdata);
4182e192b24SSimon Glass
4192e192b24SSimon Glass return 0;
4202e192b24SSimon Glass }
4212e192b24SSimon Glass
nand_imls_fitimage(struct mtd_info * mtd,int nand_dev,loff_t off,size_t len)422151c06ecSScott Wood static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
4232e192b24SSimon Glass size_t len)
4242e192b24SSimon Glass {
4252e192b24SSimon Glass void *imgdata;
4262e192b24SSimon Glass int ret;
4272e192b24SSimon Glass
4282e192b24SSimon Glass imgdata = malloc(len);
4292e192b24SSimon Glass if (!imgdata) {
4302e192b24SSimon Glass printf("May be a FIT Image at NAND device %d offset %08llX:\n",
4312e192b24SSimon Glass nand_dev, off);
4322e192b24SSimon Glass printf(" Low memory(cannot allocate memory for image)\n");
4332e192b24SSimon Glass return -ENOMEM;
4342e192b24SSimon Glass }
4352e192b24SSimon Glass
436dbe7881dSGrygorii Strashko ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
4372e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) {
4382e192b24SSimon Glass free(imgdata);
4392e192b24SSimon Glass return ret;
4402e192b24SSimon Glass }
4412e192b24SSimon Glass
4422e192b24SSimon Glass if (!fit_check_format(imgdata)) {
4432e192b24SSimon Glass free(imgdata);
4442e192b24SSimon Glass return 0;
4452e192b24SSimon Glass }
4462e192b24SSimon Glass
4472e192b24SSimon Glass printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
4482e192b24SSimon Glass
4492e192b24SSimon Glass fit_print_contents(imgdata);
4502e192b24SSimon Glass free(imgdata);
4512e192b24SSimon Glass
4522e192b24SSimon Glass return 0;
4532e192b24SSimon Glass }
4542e192b24SSimon Glass
do_imls_nand(void)4552e192b24SSimon Glass static int do_imls_nand(void)
4562e192b24SSimon Glass {
457151c06ecSScott Wood struct mtd_info *mtd;
4582e192b24SSimon Glass int nand_dev = nand_curr_device;
4592e192b24SSimon Glass size_t len;
4602e192b24SSimon Glass loff_t off;
4612e192b24SSimon Glass u32 buffer[16];
4622e192b24SSimon Glass
4632e192b24SSimon Glass if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
4642e192b24SSimon Glass puts("\nNo NAND devices available\n");
4652e192b24SSimon Glass return -ENODEV;
4662e192b24SSimon Glass }
4672e192b24SSimon Glass
4682e192b24SSimon Glass printf("\n");
4692e192b24SSimon Glass
4702e192b24SSimon Glass for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
471f370b515SGrygorii Strashko mtd = get_nand_dev_by_index(nand_dev);
472151c06ecSScott Wood if (!mtd->name || !mtd->size)
4732e192b24SSimon Glass continue;
4742e192b24SSimon Glass
475151c06ecSScott Wood for (off = 0; off < mtd->size; off += mtd->erasesize) {
4762e192b24SSimon Glass const image_header_t *header;
4772e192b24SSimon Glass int ret;
4782e192b24SSimon Glass
479151c06ecSScott Wood if (nand_block_isbad(mtd, off))
4802e192b24SSimon Glass continue;
4812e192b24SSimon Glass
4822e192b24SSimon Glass len = sizeof(buffer);
4832e192b24SSimon Glass
484151c06ecSScott Wood ret = nand_read(mtd, off, &len, (u8 *)buffer);
4852e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) {
4862e192b24SSimon Glass printf("NAND read error %d at offset %08llX\n",
4872e192b24SSimon Glass ret, off);
4882e192b24SSimon Glass continue;
4892e192b24SSimon Glass }
4902e192b24SSimon Glass
4912e192b24SSimon Glass switch (genimg_get_format(buffer)) {
4922e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY)
4932e192b24SSimon Glass case IMAGE_FORMAT_LEGACY:
4942e192b24SSimon Glass header = (const image_header_t *)buffer;
4952e192b24SSimon Glass
4962e192b24SSimon Glass len = image_get_image_size(header);
497151c06ecSScott Wood nand_imls_legacyimage(mtd, nand_dev, off, len);
4982e192b24SSimon Glass break;
4992e192b24SSimon Glass #endif
5002e192b24SSimon Glass #if defined(CONFIG_FIT)
5012e192b24SSimon Glass case IMAGE_FORMAT_FIT:
5022e192b24SSimon Glass len = fit_get_size(buffer);
503151c06ecSScott Wood nand_imls_fitimage(mtd, nand_dev, off, len);
5042e192b24SSimon Glass break;
5052e192b24SSimon Glass #endif
5062e192b24SSimon Glass }
5072e192b24SSimon Glass }
5082e192b24SSimon Glass }
5092e192b24SSimon Glass
5102e192b24SSimon Glass return 0;
5112e192b24SSimon Glass }
5122e192b24SSimon Glass #endif
5132e192b24SSimon Glass
5142e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
do_imls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])5152e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5162e192b24SSimon Glass {
5172e192b24SSimon Glass int ret_nor = 0, ret_nand = 0;
5182e192b24SSimon Glass
5192e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS)
5202e192b24SSimon Glass ret_nor = do_imls_nor();
5212e192b24SSimon Glass #endif
5222e192b24SSimon Glass
5232e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND)
5242e192b24SSimon Glass ret_nand = do_imls_nand();
5252e192b24SSimon Glass #endif
5262e192b24SSimon Glass
5272e192b24SSimon Glass if (ret_nor)
5282e192b24SSimon Glass return ret_nor;
5292e192b24SSimon Glass
5302e192b24SSimon Glass if (ret_nand)
5312e192b24SSimon Glass return ret_nand;
5322e192b24SSimon Glass
5332e192b24SSimon Glass return (0);
5342e192b24SSimon Glass }
5352e192b24SSimon Glass
5362e192b24SSimon Glass U_BOOT_CMD(
5372e192b24SSimon Glass imls, 1, 1, do_imls,
5382e192b24SSimon Glass "list all images found in flash",
5392e192b24SSimon Glass "\n"
5402e192b24SSimon Glass " - Prints information about all images found at sector/block\n"
5412e192b24SSimon Glass " boundaries in nor/nand flash."
5422e192b24SSimon Glass );
5432e192b24SSimon Glass #endif
544