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 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 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 1072e192b24SSimon Glass 1082e192b24SSimon Glass /* determine if we have a sub command */ 1092e192b24SSimon Glass argc--; argv++; 1102e192b24SSimon Glass if (argc > 0) { 1112e192b24SSimon Glass char *endp; 1122e192b24SSimon Glass 1132e192b24SSimon Glass simple_strtoul(argv[0], &endp, 16); 1142e192b24SSimon Glass /* endp pointing to NULL means that argv[0] was just a 1152e192b24SSimon Glass * valid number, pass it along to the normal bootm processing 1162e192b24SSimon Glass * 1172e192b24SSimon Glass * If endp is ':' or '#' assume a FIT identifier so pass 1182e192b24SSimon Glass * along for normal processing. 1192e192b24SSimon Glass * 1202e192b24SSimon Glass * Right now we assume the first arg should never be '-' 1212e192b24SSimon Glass */ 1222e192b24SSimon Glass if ((*endp != 0) && (*endp != ':') && (*endp != '#')) 1232e192b24SSimon Glass return do_bootm_subcommand(cmdtp, flag, argc, argv); 1242e192b24SSimon Glass } 1252e192b24SSimon Glass 1262e192b24SSimon Glass return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START | 1272e192b24SSimon Glass BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER | 1282e192b24SSimon Glass BOOTM_STATE_LOADOS | 129*c2e7e72bSRick Altherr #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 130*c2e7e72bSRick Altherr BOOTM_STATE_RAMDISK | 131*c2e7e72bSRick Altherr #endif 1322e192b24SSimon Glass #if defined(CONFIG_PPC) || defined(CONFIG_MIPS) 1332e192b24SSimon Glass BOOTM_STATE_OS_CMDLINE | 1342e192b24SSimon Glass #endif 1352e192b24SSimon Glass BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | 1362e192b24SSimon Glass BOOTM_STATE_OS_GO, &images, 1); 1372e192b24SSimon Glass } 1382e192b24SSimon Glass 1392e192b24SSimon Glass int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd) 1402e192b24SSimon Glass { 1412e192b24SSimon Glass const char *ep = getenv("autostart"); 1422e192b24SSimon Glass 1432e192b24SSimon Glass if (ep && !strcmp(ep, "yes")) { 1442e192b24SSimon Glass char *local_args[2]; 1452e192b24SSimon Glass local_args[0] = (char *)cmd; 1462e192b24SSimon Glass local_args[1] = NULL; 1472e192b24SSimon Glass printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr); 1482e192b24SSimon Glass return do_bootm(cmdtp, 0, 1, local_args); 1492e192b24SSimon Glass } 1502e192b24SSimon Glass 1512e192b24SSimon Glass return 0; 1522e192b24SSimon Glass } 1532e192b24SSimon Glass 1542e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP 1552e192b24SSimon Glass static char bootm_help_text[] = 1562e192b24SSimon Glass "[addr [arg ...]]\n - boot application image stored in memory\n" 1572e192b24SSimon Glass "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" 1582e192b24SSimon Glass "\t'arg' can be the address of an initrd image\n" 1592e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT) 1602e192b24SSimon Glass "\tWhen booting a Linux kernel which requires a flat device-tree\n" 1612e192b24SSimon Glass "\ta third argument is required which is the address of the\n" 1622e192b24SSimon Glass "\tdevice-tree blob. To boot that kernel without an initrd image,\n" 1632e192b24SSimon Glass "\tuse a '-' for the second argument. If you do not pass a third\n" 1642e192b24SSimon Glass "\ta bd_info struct will be passed instead\n" 1652e192b24SSimon Glass #endif 1662e192b24SSimon Glass #if defined(CONFIG_FIT) 1672e192b24SSimon Glass "\t\nFor the new multi component uImage format (FIT) addresses\n" 168da1a3bd4SVagrant Cascadian "\tmust be extended to include component or configuration unit name:\n" 1692e192b24SSimon Glass "\taddr:<subimg_uname> - direct component image specification\n" 1702e192b24SSimon Glass "\taddr#<conf_uname> - configuration specification\n" 1712e192b24SSimon Glass "\tUse iminfo command to get the list of existing component\n" 1722e192b24SSimon Glass "\timages and configurations.\n" 1732e192b24SSimon Glass #endif 1742e192b24SSimon Glass "\nSub-commands to do part of the bootm sequence. The sub-commands " 1752e192b24SSimon Glass "must be\n" 1762e192b24SSimon Glass "issued in the order below (it's ok to not issue all sub-commands):\n" 1772e192b24SSimon Glass "\tstart [addr [arg ...]]\n" 1782e192b24SSimon Glass "\tloados - load OS image\n" 1792e192b24SSimon Glass #if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH) 1802e192b24SSimon Glass "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n" 1812e192b24SSimon Glass #endif 1822e192b24SSimon Glass #if defined(CONFIG_OF_LIBFDT) 1832e192b24SSimon Glass "\tfdt - relocate flat device tree\n" 1842e192b24SSimon Glass #endif 1852e192b24SSimon Glass "\tcmdline - OS specific command line processing/setup\n" 1862e192b24SSimon Glass "\tbdt - OS specific bd_t processing\n" 1872e192b24SSimon Glass "\tprep - OS specific prep before relocation or go\n" 1882e192b24SSimon Glass #if defined(CONFIG_TRACE) 1892e192b24SSimon Glass "\tfake - OS specific fake start without go\n" 1902e192b24SSimon Glass #endif 1912e192b24SSimon Glass "\tgo - start OS"; 1922e192b24SSimon Glass #endif 1932e192b24SSimon Glass 1942e192b24SSimon Glass U_BOOT_CMD( 1952e192b24SSimon Glass bootm, CONFIG_SYS_MAXARGS, 1, do_bootm, 1962e192b24SSimon Glass "boot application image from memory", bootm_help_text 1972e192b24SSimon Glass ); 1982e192b24SSimon Glass 1992e192b24SSimon Glass /*******************************************************************/ 2002e192b24SSimon Glass /* bootd - boot default image */ 2012e192b24SSimon Glass /*******************************************************************/ 2022e192b24SSimon Glass #if defined(CONFIG_CMD_BOOTD) 2032e192b24SSimon Glass int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 2042e192b24SSimon Glass { 2052e192b24SSimon Glass return run_command(getenv("bootcmd"), flag); 2062e192b24SSimon Glass } 2072e192b24SSimon Glass 2082e192b24SSimon Glass U_BOOT_CMD( 2092e192b24SSimon Glass boot, 1, 1, do_bootd, 2102e192b24SSimon Glass "boot default, i.e., run 'bootcmd'", 2112e192b24SSimon Glass "" 2122e192b24SSimon Glass ); 2132e192b24SSimon Glass 2142e192b24SSimon Glass /* keep old command name "bootd" for backward compatibility */ 2152e192b24SSimon Glass U_BOOT_CMD( 2162e192b24SSimon Glass bootd, 1, 1, do_bootd, 2172e192b24SSimon Glass "boot default, i.e., run 'bootcmd'", 2182e192b24SSimon Glass "" 2192e192b24SSimon Glass ); 2202e192b24SSimon Glass 2212e192b24SSimon Glass #endif 2222e192b24SSimon Glass 2232e192b24SSimon Glass 2242e192b24SSimon Glass /*******************************************************************/ 2252e192b24SSimon Glass /* iminfo - print header info for a requested image */ 2262e192b24SSimon Glass /*******************************************************************/ 2272e192b24SSimon Glass #if defined(CONFIG_CMD_IMI) 2282e192b24SSimon Glass static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 2292e192b24SSimon Glass { 2302e192b24SSimon Glass int arg; 2312e192b24SSimon Glass ulong addr; 2322e192b24SSimon Glass int rcode = 0; 2332e192b24SSimon Glass 2342e192b24SSimon Glass if (argc < 2) { 2352e192b24SSimon Glass return image_info(load_addr); 2362e192b24SSimon Glass } 2372e192b24SSimon Glass 2382e192b24SSimon Glass for (arg = 1; arg < argc; ++arg) { 2392e192b24SSimon Glass addr = simple_strtoul(argv[arg], NULL, 16); 2402e192b24SSimon Glass if (image_info(addr) != 0) 2412e192b24SSimon Glass rcode = 1; 2422e192b24SSimon Glass } 2432e192b24SSimon Glass return rcode; 2442e192b24SSimon Glass } 2452e192b24SSimon Glass 2462e192b24SSimon Glass static int image_info(ulong addr) 2472e192b24SSimon Glass { 2482e192b24SSimon Glass void *hdr = (void *)addr; 2492e192b24SSimon Glass 2502e192b24SSimon Glass printf("\n## Checking Image at %08lx ...\n", addr); 2512e192b24SSimon Glass 2522e192b24SSimon Glass switch (genimg_get_format(hdr)) { 2532e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 2542e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 2552e192b24SSimon Glass puts(" Legacy image found\n"); 2562e192b24SSimon Glass if (!image_check_magic(hdr)) { 2572e192b24SSimon Glass puts(" Bad Magic Number\n"); 2582e192b24SSimon Glass return 1; 2592e192b24SSimon Glass } 2602e192b24SSimon Glass 2612e192b24SSimon Glass if (!image_check_hcrc(hdr)) { 2622e192b24SSimon Glass puts(" Bad Header Checksum\n"); 2632e192b24SSimon Glass return 1; 2642e192b24SSimon Glass } 2652e192b24SSimon Glass 2662e192b24SSimon Glass image_print_contents(hdr); 2672e192b24SSimon Glass 2682e192b24SSimon Glass puts(" Verifying Checksum ... "); 2692e192b24SSimon Glass if (!image_check_dcrc(hdr)) { 2702e192b24SSimon Glass puts(" Bad Data CRC\n"); 2712e192b24SSimon Glass return 1; 2722e192b24SSimon Glass } 2732e192b24SSimon Glass puts("OK\n"); 2742e192b24SSimon Glass return 0; 2752e192b24SSimon Glass #endif 2764f1318b2SMichael Trimarchi #if defined(CONFIG_ANDROID_BOOT_IMAGE) 2774f1318b2SMichael Trimarchi case IMAGE_FORMAT_ANDROID: 2784f1318b2SMichael Trimarchi puts(" Android image found\n"); 2794f1318b2SMichael Trimarchi android_print_contents(hdr); 2804f1318b2SMichael Trimarchi return 0; 2814f1318b2SMichael Trimarchi #endif 2822e192b24SSimon Glass #if defined(CONFIG_FIT) 2832e192b24SSimon Glass case IMAGE_FORMAT_FIT: 2842e192b24SSimon Glass puts(" FIT image found\n"); 2852e192b24SSimon Glass 2862e192b24SSimon Glass if (!fit_check_format(hdr)) { 2872e192b24SSimon Glass puts("Bad FIT image format!\n"); 2882e192b24SSimon Glass return 1; 2892e192b24SSimon Glass } 2902e192b24SSimon Glass 2912e192b24SSimon Glass fit_print_contents(hdr); 2922e192b24SSimon Glass 2932e192b24SSimon Glass if (!fit_all_image_verify(hdr)) { 2942e192b24SSimon Glass puts("Bad hash in FIT image!\n"); 2952e192b24SSimon Glass return 1; 2962e192b24SSimon Glass } 2972e192b24SSimon Glass 2982e192b24SSimon Glass return 0; 2992e192b24SSimon Glass #endif 3002e192b24SSimon Glass default: 3012e192b24SSimon Glass puts("Unknown image format!\n"); 3022e192b24SSimon Glass break; 3032e192b24SSimon Glass } 3042e192b24SSimon Glass 3052e192b24SSimon Glass return 1; 3062e192b24SSimon Glass } 3072e192b24SSimon Glass 3082e192b24SSimon Glass U_BOOT_CMD( 3092e192b24SSimon Glass iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo, 3102e192b24SSimon Glass "print header information for application image", 3112e192b24SSimon Glass "addr [addr ...]\n" 3122e192b24SSimon Glass " - print header information for application image starting at\n" 3132e192b24SSimon Glass " address 'addr' in memory; this includes verification of the\n" 3142e192b24SSimon Glass " image contents (magic number, header and payload checksums)" 3152e192b24SSimon Glass ); 3162e192b24SSimon Glass #endif 3172e192b24SSimon Glass 3182e192b24SSimon Glass 3192e192b24SSimon Glass /*******************************************************************/ 3202e192b24SSimon Glass /* imls - list all images found in flash */ 3212e192b24SSimon Glass /*******************************************************************/ 3222e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) 3232e192b24SSimon Glass static int do_imls_nor(void) 3242e192b24SSimon Glass { 3252e192b24SSimon Glass flash_info_t *info; 3262e192b24SSimon Glass int i, j; 3272e192b24SSimon Glass void *hdr; 3282e192b24SSimon Glass 3292e192b24SSimon Glass for (i = 0, info = &flash_info[0]; 3302e192b24SSimon Glass i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) { 3312e192b24SSimon Glass 3322e192b24SSimon Glass if (info->flash_id == FLASH_UNKNOWN) 3332e192b24SSimon Glass goto next_bank; 3342e192b24SSimon Glass for (j = 0; j < info->sector_count; ++j) { 3352e192b24SSimon Glass 3362e192b24SSimon Glass hdr = (void *)info->start[j]; 3372e192b24SSimon Glass if (!hdr) 3382e192b24SSimon Glass goto next_sector; 3392e192b24SSimon Glass 3402e192b24SSimon Glass switch (genimg_get_format(hdr)) { 3412e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 3422e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 3432e192b24SSimon Glass if (!image_check_hcrc(hdr)) 3442e192b24SSimon Glass goto next_sector; 3452e192b24SSimon Glass 3462e192b24SSimon Glass printf("Legacy Image at %08lX:\n", (ulong)hdr); 3472e192b24SSimon Glass image_print_contents(hdr); 3482e192b24SSimon Glass 3492e192b24SSimon Glass puts(" Verifying Checksum ... "); 3502e192b24SSimon Glass if (!image_check_dcrc(hdr)) { 3512e192b24SSimon Glass puts("Bad Data CRC\n"); 3522e192b24SSimon Glass } else { 3532e192b24SSimon Glass puts("OK\n"); 3542e192b24SSimon Glass } 3552e192b24SSimon Glass break; 3562e192b24SSimon Glass #endif 3572e192b24SSimon Glass #if defined(CONFIG_FIT) 3582e192b24SSimon Glass case IMAGE_FORMAT_FIT: 3592e192b24SSimon Glass if (!fit_check_format(hdr)) 3602e192b24SSimon Glass goto next_sector; 3612e192b24SSimon Glass 3622e192b24SSimon Glass printf("FIT Image at %08lX:\n", (ulong)hdr); 3632e192b24SSimon Glass fit_print_contents(hdr); 3642e192b24SSimon Glass break; 3652e192b24SSimon Glass #endif 3662e192b24SSimon Glass default: 3672e192b24SSimon Glass goto next_sector; 3682e192b24SSimon Glass } 3692e192b24SSimon Glass 3702e192b24SSimon Glass next_sector: ; 3712e192b24SSimon Glass } 3722e192b24SSimon Glass next_bank: ; 3732e192b24SSimon Glass } 3742e192b24SSimon Glass return 0; 3752e192b24SSimon Glass } 3762e192b24SSimon Glass #endif 3772e192b24SSimon Glass 3782e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND) 379151c06ecSScott Wood static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev, 380151c06ecSScott Wood loff_t off, size_t len) 3812e192b24SSimon Glass { 3822e192b24SSimon Glass void *imgdata; 3832e192b24SSimon Glass int ret; 3842e192b24SSimon Glass 3852e192b24SSimon Glass imgdata = malloc(len); 3862e192b24SSimon Glass if (!imgdata) { 3872e192b24SSimon Glass printf("May be a Legacy Image at NAND device %d offset %08llX:\n", 3882e192b24SSimon Glass nand_dev, off); 3892e192b24SSimon Glass printf(" Low memory(cannot allocate memory for image)\n"); 3902e192b24SSimon Glass return -ENOMEM; 3912e192b24SSimon Glass } 3922e192b24SSimon Glass 393151c06ecSScott Wood ret = nand_read_skip_bad(mtd, off, &len, imgdata); 3942e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) { 3952e192b24SSimon Glass free(imgdata); 3962e192b24SSimon Glass return ret; 3972e192b24SSimon Glass } 3982e192b24SSimon Glass 3992e192b24SSimon Glass if (!image_check_hcrc(imgdata)) { 4002e192b24SSimon Glass free(imgdata); 4012e192b24SSimon Glass return 0; 4022e192b24SSimon Glass } 4032e192b24SSimon Glass 4042e192b24SSimon Glass printf("Legacy Image at NAND device %d offset %08llX:\n", 4052e192b24SSimon Glass nand_dev, off); 4062e192b24SSimon Glass image_print_contents(imgdata); 4072e192b24SSimon Glass 4082e192b24SSimon Glass puts(" Verifying Checksum ... "); 4092e192b24SSimon Glass if (!image_check_dcrc(imgdata)) 4102e192b24SSimon Glass puts("Bad Data CRC\n"); 4112e192b24SSimon Glass else 4122e192b24SSimon Glass puts("OK\n"); 4132e192b24SSimon Glass 4142e192b24SSimon Glass free(imgdata); 4152e192b24SSimon Glass 4162e192b24SSimon Glass return 0; 4172e192b24SSimon Glass } 4182e192b24SSimon Glass 419151c06ecSScott Wood static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off, 4202e192b24SSimon Glass size_t len) 4212e192b24SSimon Glass { 4222e192b24SSimon Glass void *imgdata; 4232e192b24SSimon Glass int ret; 4242e192b24SSimon Glass 4252e192b24SSimon Glass imgdata = malloc(len); 4262e192b24SSimon Glass if (!imgdata) { 4272e192b24SSimon Glass printf("May be a FIT Image at NAND device %d offset %08llX:\n", 4282e192b24SSimon Glass nand_dev, off); 4292e192b24SSimon Glass printf(" Low memory(cannot allocate memory for image)\n"); 4302e192b24SSimon Glass return -ENOMEM; 4312e192b24SSimon Glass } 4322e192b24SSimon Glass 433151c06ecSScott Wood ret = nand_read_skip_bad(mtd, off, &len, imgdata); 4342e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) { 4352e192b24SSimon Glass free(imgdata); 4362e192b24SSimon Glass return ret; 4372e192b24SSimon Glass } 4382e192b24SSimon Glass 4392e192b24SSimon Glass if (!fit_check_format(imgdata)) { 4402e192b24SSimon Glass free(imgdata); 4412e192b24SSimon Glass return 0; 4422e192b24SSimon Glass } 4432e192b24SSimon Glass 4442e192b24SSimon Glass printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off); 4452e192b24SSimon Glass 4462e192b24SSimon Glass fit_print_contents(imgdata); 4472e192b24SSimon Glass free(imgdata); 4482e192b24SSimon Glass 4492e192b24SSimon Glass return 0; 4502e192b24SSimon Glass } 4512e192b24SSimon Glass 4522e192b24SSimon Glass static int do_imls_nand(void) 4532e192b24SSimon Glass { 454151c06ecSScott Wood struct mtd_info *mtd; 4552e192b24SSimon Glass int nand_dev = nand_curr_device; 4562e192b24SSimon Glass size_t len; 4572e192b24SSimon Glass loff_t off; 4582e192b24SSimon Glass u32 buffer[16]; 4592e192b24SSimon Glass 4602e192b24SSimon Glass if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { 4612e192b24SSimon Glass puts("\nNo NAND devices available\n"); 4622e192b24SSimon Glass return -ENODEV; 4632e192b24SSimon Glass } 4642e192b24SSimon Glass 4652e192b24SSimon Glass printf("\n"); 4662e192b24SSimon Glass 4672e192b24SSimon Glass for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { 468b616d9b0SScott Wood mtd = nand_info[nand_dev]; 469151c06ecSScott Wood if (!mtd->name || !mtd->size) 4702e192b24SSimon Glass continue; 4712e192b24SSimon Glass 472151c06ecSScott Wood for (off = 0; off < mtd->size; off += mtd->erasesize) { 4732e192b24SSimon Glass const image_header_t *header; 4742e192b24SSimon Glass int ret; 4752e192b24SSimon Glass 476151c06ecSScott Wood if (nand_block_isbad(mtd, off)) 4772e192b24SSimon Glass continue; 4782e192b24SSimon Glass 4792e192b24SSimon Glass len = sizeof(buffer); 4802e192b24SSimon Glass 481151c06ecSScott Wood ret = nand_read(mtd, off, &len, (u8 *)buffer); 4822e192b24SSimon Glass if (ret < 0 && ret != -EUCLEAN) { 4832e192b24SSimon Glass printf("NAND read error %d at offset %08llX\n", 4842e192b24SSimon Glass ret, off); 4852e192b24SSimon Glass continue; 4862e192b24SSimon Glass } 4872e192b24SSimon Glass 4882e192b24SSimon Glass switch (genimg_get_format(buffer)) { 4892e192b24SSimon Glass #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 4902e192b24SSimon Glass case IMAGE_FORMAT_LEGACY: 4912e192b24SSimon Glass header = (const image_header_t *)buffer; 4922e192b24SSimon Glass 4932e192b24SSimon Glass len = image_get_image_size(header); 494151c06ecSScott Wood nand_imls_legacyimage(mtd, nand_dev, off, len); 4952e192b24SSimon Glass break; 4962e192b24SSimon Glass #endif 4972e192b24SSimon Glass #if defined(CONFIG_FIT) 4982e192b24SSimon Glass case IMAGE_FORMAT_FIT: 4992e192b24SSimon Glass len = fit_get_size(buffer); 500151c06ecSScott Wood nand_imls_fitimage(mtd, nand_dev, off, len); 5012e192b24SSimon Glass break; 5022e192b24SSimon Glass #endif 5032e192b24SSimon Glass } 5042e192b24SSimon Glass } 5052e192b24SSimon Glass } 5062e192b24SSimon Glass 5072e192b24SSimon Glass return 0; 5082e192b24SSimon Glass } 5092e192b24SSimon Glass #endif 5102e192b24SSimon Glass 5112e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) 5122e192b24SSimon Glass static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5132e192b24SSimon Glass { 5142e192b24SSimon Glass int ret_nor = 0, ret_nand = 0; 5152e192b24SSimon Glass 5162e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS) 5172e192b24SSimon Glass ret_nor = do_imls_nor(); 5182e192b24SSimon Glass #endif 5192e192b24SSimon Glass 5202e192b24SSimon Glass #if defined(CONFIG_CMD_IMLS_NAND) 5212e192b24SSimon Glass ret_nand = do_imls_nand(); 5222e192b24SSimon Glass #endif 5232e192b24SSimon Glass 5242e192b24SSimon Glass if (ret_nor) 5252e192b24SSimon Glass return ret_nor; 5262e192b24SSimon Glass 5272e192b24SSimon Glass if (ret_nand) 5282e192b24SSimon Glass return ret_nand; 5292e192b24SSimon Glass 5302e192b24SSimon Glass return (0); 5312e192b24SSimon Glass } 5322e192b24SSimon Glass 5332e192b24SSimon Glass U_BOOT_CMD( 5342e192b24SSimon Glass imls, 1, 1, do_imls, 5352e192b24SSimon Glass "list all images found in flash", 5362e192b24SSimon Glass "\n" 5372e192b24SSimon Glass " - Prints information about all images found at sector/block\n" 5382e192b24SSimon Glass " boundaries in nor/nand flash." 5392e192b24SSimon Glass ); 5402e192b24SSimon Glass #endif 541