1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 22e192b24SSimon Glass /* 32e192b24SSimon Glass * (C) Copyright 2002 42e192b24SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 52e192b24SSimon Glass * 62e192b24SSimon Glass * (C) Copyright 2002 72e192b24SSimon Glass * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de> 82e192b24SSimon Glass * 92e192b24SSimon Glass * (C) Copyright 2003 102e192b24SSimon Glass * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de> 112e192b24SSimon Glass * 122e192b24SSimon Glass * (C) Copyright 2005 132e192b24SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 142e192b24SSimon Glass * 152e192b24SSimon Glass * Added support for reading flash partition table from environment. 162e192b24SSimon Glass * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4 172e192b24SSimon Glass * kernel tree. 182e192b24SSimon Glass * 192e192b24SSimon Glass * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ 202e192b24SSimon Glass * Copyright 2002 SYSGO Real-Time Solutions GmbH 212e192b24SSimon Glass */ 222e192b24SSimon Glass 232e192b24SSimon Glass /* 242e192b24SSimon Glass * Three environment variables are used by the parsing routines: 252e192b24SSimon Glass * 262e192b24SSimon Glass * 'partition' - keeps current partition identifier 272e192b24SSimon Glass * 282e192b24SSimon Glass * partition := <part-id> 292e192b24SSimon Glass * <part-id> := <dev-id>,part_num 302e192b24SSimon Glass * 312e192b24SSimon Glass * 322e192b24SSimon Glass * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping 332e192b24SSimon Glass * 342e192b24SSimon Glass * mtdids=<idmap>[,<idmap>,...] 352e192b24SSimon Glass * 362e192b24SSimon Glass * <idmap> := <dev-id>=<mtd-id> 372e192b24SSimon Glass * <dev-id> := 'nand'|'nor'|'onenand'<dev-num> 382e192b24SSimon Glass * <dev-num> := mtd device number, 0... 392e192b24SSimon Glass * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name) 402e192b24SSimon Glass * 412e192b24SSimon Glass * 422e192b24SSimon Glass * 'mtdparts' - partition list 432e192b24SSimon Glass * 442e192b24SSimon Glass * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...] 452e192b24SSimon Glass * 462e192b24SSimon Glass * <mtd-def> := <mtd-id>:<part-def>[,<part-def>...] 472e192b24SSimon Glass * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name) 482e192b24SSimon Glass * <part-def> := <size>[@<offset>][<name>][<ro-flag>] 492e192b24SSimon Glass * <size> := standard linux memsize OR '-' to denote all remaining space 502e192b24SSimon Glass * <offset> := partition start offset within the device 512e192b24SSimon Glass * <name> := '(' NAME ')' 522e192b24SSimon Glass * <ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel) 532e192b24SSimon Glass * 542e192b24SSimon Glass * Notes: 552e192b24SSimon Glass * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping 562e192b24SSimon Glass * - if the above variables are not set defaults for a given target are used 572e192b24SSimon Glass * 582e192b24SSimon Glass * Examples: 592e192b24SSimon Glass * 602e192b24SSimon Glass * 1 NOR Flash, with 1 single writable partition: 612e192b24SSimon Glass * mtdids=nor0=edb7312-nor 622e192b24SSimon Glass * mtdparts=mtdparts=edb7312-nor:- 632e192b24SSimon Glass * 642e192b24SSimon Glass * 1 NOR Flash with 2 partitions, 1 NAND with one 652e192b24SSimon Glass * mtdids=nor0=edb7312-nor,nand0=edb7312-nand 662e192b24SSimon Glass * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home) 672e192b24SSimon Glass * 682e192b24SSimon Glass */ 692e192b24SSimon Glass 702e192b24SSimon Glass /* 712e192b24SSimon Glass * JFFS2/CRAMFS support 722e192b24SSimon Glass */ 732e192b24SSimon Glass #include <common.h> 742e192b24SSimon Glass #include <command.h> 752e192b24SSimon Glass #include <malloc.h> 762e192b24SSimon Glass #include <jffs2/jffs2.h> 772e192b24SSimon Glass #include <linux/list.h> 782e192b24SSimon Glass #include <linux/ctype.h> 792e192b24SSimon Glass #include <cramfs/cramfs_fs.h> 802e192b24SSimon Glass 812e192b24SSimon Glass #if defined(CONFIG_CMD_NAND) 826ae3900aSMasahiro Yamada #include <linux/mtd/rawnand.h> 832e192b24SSimon Glass #include <nand.h> 842e192b24SSimon Glass #endif 852e192b24SSimon Glass 862e192b24SSimon Glass #if defined(CONFIG_CMD_ONENAND) 872e192b24SSimon Glass #include <linux/mtd/mtd.h> 882e192b24SSimon Glass #include <linux/mtd/onenand.h> 892e192b24SSimon Glass #include <onenand_uboot.h> 902e192b24SSimon Glass #endif 912e192b24SSimon Glass 922e192b24SSimon Glass /* enable/disable debugging messages */ 932e192b24SSimon Glass #define DEBUG_JFFS 942e192b24SSimon Glass #undef DEBUG_JFFS 952e192b24SSimon Glass 962e192b24SSimon Glass #ifdef DEBUG_JFFS 972e192b24SSimon Glass # define DEBUGF(fmt, args...) printf(fmt ,##args) 982e192b24SSimon Glass #else 992e192b24SSimon Glass # define DEBUGF(fmt, args...) 1002e192b24SSimon Glass #endif 1012e192b24SSimon Glass 1022e192b24SSimon Glass /* special size referring to all the remaining space in a partition */ 1032e192b24SSimon Glass #define SIZE_REMAINING 0xFFFFFFFF 1042e192b24SSimon Glass 1052e192b24SSimon Glass /* special offset value, it is used when not provided by user 1062e192b24SSimon Glass * 1072e192b24SSimon Glass * this value is used temporarily during parsing, later such offests 1082e192b24SSimon Glass * are recalculated */ 1092e192b24SSimon Glass #define OFFSET_NOT_SPECIFIED 0xFFFFFFFF 1102e192b24SSimon Glass 1112e192b24SSimon Glass /* minimum partition size */ 1122e192b24SSimon Glass #define MIN_PART_SIZE 4096 1132e192b24SSimon Glass 1142e192b24SSimon Glass /* this flag needs to be set in part_info struct mask_flags 1152e192b24SSimon Glass * field for read-only partitions */ 1162e192b24SSimon Glass #define MTD_WRITEABLE_CMD 1 1172e192b24SSimon Glass 1182e192b24SSimon Glass /* current active device and partition number */ 1192e192b24SSimon Glass #ifdef CONFIG_CMD_MTDPARTS 1202e192b24SSimon Glass /* Use the ones declared in cmd_mtdparts.c */ 1212e192b24SSimon Glass extern struct mtd_device *current_mtd_dev; 1222e192b24SSimon Glass extern u8 current_mtd_partnum; 1232e192b24SSimon Glass #else 1242e192b24SSimon Glass /* Use local ones */ 1252e192b24SSimon Glass struct mtd_device *current_mtd_dev = NULL; 1262e192b24SSimon Glass u8 current_mtd_partnum = 0; 1272e192b24SSimon Glass #endif 1282e192b24SSimon Glass 1292e192b24SSimon Glass #if defined(CONFIG_CMD_CRAMFS) 1302e192b24SSimon Glass extern int cramfs_check (struct part_info *info); 1312e192b24SSimon Glass extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename); 1322e192b24SSimon Glass extern int cramfs_ls (struct part_info *info, char *filename); 1332e192b24SSimon Glass extern int cramfs_info (struct part_info *info); 1342e192b24SSimon Glass #else 1352e192b24SSimon Glass /* defining empty macros for function names is ugly but avoids ifdef clutter 1362e192b24SSimon Glass * all over the code */ 1372e192b24SSimon Glass #define cramfs_check(x) (0) 1382e192b24SSimon Glass #define cramfs_load(x,y,z) (-1) 1392e192b24SSimon Glass #define cramfs_ls(x,y) (0) 1402e192b24SSimon Glass #define cramfs_info(x) (0) 1412e192b24SSimon Glass #endif 1422e192b24SSimon Glass 1432e192b24SSimon Glass #ifndef CONFIG_CMD_MTDPARTS 1442e192b24SSimon Glass /** 1452e192b24SSimon Glass * Check device number to be within valid range for given device type. 1462e192b24SSimon Glass * 1472e192b24SSimon Glass * @param dev device to validate 1482e192b24SSimon Glass * @return 0 if device is valid, 1 otherwise 1492e192b24SSimon Glass */ 1502e192b24SSimon Glass static int mtd_device_validate(u8 type, u8 num, u32 *size) 1512e192b24SSimon Glass { 1522e192b24SSimon Glass if (type == MTD_DEV_TYPE_NOR) { 1532e192b24SSimon Glass #if defined(CONFIG_CMD_FLASH) 1542e192b24SSimon Glass if (num < CONFIG_SYS_MAX_FLASH_BANKS) { 1552e192b24SSimon Glass extern flash_info_t flash_info[]; 1562e192b24SSimon Glass *size = flash_info[num].size; 1572e192b24SSimon Glass 1582e192b24SSimon Glass return 0; 1592e192b24SSimon Glass } 1602e192b24SSimon Glass 1612e192b24SSimon Glass printf("no such FLASH device: %s%d (valid range 0 ... %d\n", 1622e192b24SSimon Glass MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1); 1632e192b24SSimon Glass #else 1642e192b24SSimon Glass printf("support for FLASH devices not present\n"); 1652e192b24SSimon Glass #endif 1662e192b24SSimon Glass } else if (type == MTD_DEV_TYPE_NAND) { 1672e192b24SSimon Glass #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) 168bfdba68eSGrygorii Strashko struct mtd_info *mtd = get_nand_dev_by_index(num); 169bfdba68eSGrygorii Strashko if (mtd) { 170bfdba68eSGrygorii Strashko *size = mtd->size; 1712e192b24SSimon Glass return 0; 1722e192b24SSimon Glass } 1732e192b24SSimon Glass 1742e192b24SSimon Glass printf("no such NAND device: %s%d (valid range 0 ... %d)\n", 1752e192b24SSimon Glass MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1); 1762e192b24SSimon Glass #else 1772e192b24SSimon Glass printf("support for NAND devices not present\n"); 1782e192b24SSimon Glass #endif 1792e192b24SSimon Glass } else if (type == MTD_DEV_TYPE_ONENAND) { 1802e192b24SSimon Glass #if defined(CONFIG_CMD_ONENAND) 1812e192b24SSimon Glass *size = onenand_mtd.size; 1822e192b24SSimon Glass return 0; 1832e192b24SSimon Glass #else 1842e192b24SSimon Glass printf("support for OneNAND devices not present\n"); 1852e192b24SSimon Glass #endif 1862e192b24SSimon Glass } else 1872e192b24SSimon Glass printf("Unknown defice type %d\n", type); 1882e192b24SSimon Glass 1892e192b24SSimon Glass return 1; 1902e192b24SSimon Glass } 1912e192b24SSimon Glass 1922e192b24SSimon Glass /** 1932e192b24SSimon Glass * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'<dev-num>, 1942e192b24SSimon Glass * return device type and number. 1952e192b24SSimon Glass * 1962e192b24SSimon Glass * @param id string describing device id 1972e192b24SSimon Glass * @param ret_id output pointer to next char after parse completes (output) 1982e192b24SSimon Glass * @param dev_type parsed device type (output) 1992e192b24SSimon Glass * @param dev_num parsed device number (output) 2002e192b24SSimon Glass * @return 0 on success, 1 otherwise 2012e192b24SSimon Glass */ 2022e192b24SSimon Glass static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num) 2032e192b24SSimon Glass { 2042e192b24SSimon Glass const char *p = id; 2052e192b24SSimon Glass 2062e192b24SSimon Glass *dev_type = 0; 2072e192b24SSimon Glass if (strncmp(p, "nand", 4) == 0) { 2082e192b24SSimon Glass *dev_type = MTD_DEV_TYPE_NAND; 2092e192b24SSimon Glass p += 4; 2102e192b24SSimon Glass } else if (strncmp(p, "nor", 3) == 0) { 2112e192b24SSimon Glass *dev_type = MTD_DEV_TYPE_NOR; 2122e192b24SSimon Glass p += 3; 2132e192b24SSimon Glass } else if (strncmp(p, "onenand", 7) == 0) { 2142e192b24SSimon Glass *dev_type = MTD_DEV_TYPE_ONENAND; 2152e192b24SSimon Glass p += 7; 2162e192b24SSimon Glass } else { 2172e192b24SSimon Glass printf("incorrect device type in %s\n", id); 2182e192b24SSimon Glass return 1; 2192e192b24SSimon Glass } 2202e192b24SSimon Glass 2212e192b24SSimon Glass if (!isdigit(*p)) { 2222e192b24SSimon Glass printf("incorrect device number in %s\n", id); 2232e192b24SSimon Glass return 1; 2242e192b24SSimon Glass } 2252e192b24SSimon Glass 2262e192b24SSimon Glass *dev_num = simple_strtoul(p, (char **)&p, 0); 2272e192b24SSimon Glass if (ret_id) 2282e192b24SSimon Glass *ret_id = p; 2292e192b24SSimon Glass return 0; 2302e192b24SSimon Glass } 2312e192b24SSimon Glass 2322e192b24SSimon Glass /* 2332e192b24SSimon Glass * 'Static' version of command line mtdparts_init() routine. Single partition on 2342e192b24SSimon Glass * a single device configuration. 2352e192b24SSimon Glass */ 2362e192b24SSimon Glass 2372e192b24SSimon Glass /** 2382e192b24SSimon Glass * Calculate sector size. 2392e192b24SSimon Glass * 2402e192b24SSimon Glass * @return sector size 2412e192b24SSimon Glass */ 2422e192b24SSimon Glass static inline u32 get_part_sector_size_nand(struct mtdids *id) 2432e192b24SSimon Glass { 2442e192b24SSimon Glass #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) 245151c06ecSScott Wood struct mtd_info *mtd; 2462e192b24SSimon Glass 247bfdba68eSGrygorii Strashko mtd = get_nand_dev_by_index(id->num); 2482e192b24SSimon Glass 249151c06ecSScott Wood return mtd->erasesize; 2502e192b24SSimon Glass #else 2512e192b24SSimon Glass BUG(); 2522e192b24SSimon Glass return 0; 2532e192b24SSimon Glass #endif 2542e192b24SSimon Glass } 2552e192b24SSimon Glass 2562e192b24SSimon Glass static inline u32 get_part_sector_size_nor(struct mtdids *id, struct part_info *part) 2572e192b24SSimon Glass { 2582e192b24SSimon Glass #if defined(CONFIG_CMD_FLASH) 2592e192b24SSimon Glass extern flash_info_t flash_info[]; 2602e192b24SSimon Glass 2612e192b24SSimon Glass u32 end_phys, start_phys, sector_size = 0, size = 0; 2622e192b24SSimon Glass int i; 2632e192b24SSimon Glass flash_info_t *flash; 2642e192b24SSimon Glass 2652e192b24SSimon Glass flash = &flash_info[id->num]; 2662e192b24SSimon Glass 2672e192b24SSimon Glass start_phys = flash->start[0] + part->offset; 2682e192b24SSimon Glass end_phys = start_phys + part->size - 1; 2692e192b24SSimon Glass 2702e192b24SSimon Glass for (i = 0; i < flash->sector_count; i++) { 2712e192b24SSimon Glass if (flash->start[i] >= end_phys) 2722e192b24SSimon Glass break; 2732e192b24SSimon Glass 2742e192b24SSimon Glass if (flash->start[i] >= start_phys) { 2752e192b24SSimon Glass if (i == flash->sector_count - 1) { 2762e192b24SSimon Glass size = flash->start[0] + flash->size - flash->start[i]; 2772e192b24SSimon Glass } else { 2782e192b24SSimon Glass size = flash->start[i+1] - flash->start[i]; 2792e192b24SSimon Glass } 2802e192b24SSimon Glass 2812e192b24SSimon Glass if (sector_size < size) 2822e192b24SSimon Glass sector_size = size; 2832e192b24SSimon Glass } 2842e192b24SSimon Glass } 2852e192b24SSimon Glass 2862e192b24SSimon Glass return sector_size; 2872e192b24SSimon Glass #else 2882e192b24SSimon Glass BUG(); 2892e192b24SSimon Glass return 0; 2902e192b24SSimon Glass #endif 2912e192b24SSimon Glass } 2922e192b24SSimon Glass 2932e192b24SSimon Glass static inline u32 get_part_sector_size_onenand(void) 2942e192b24SSimon Glass { 2952e192b24SSimon Glass #if defined(CONFIG_CMD_ONENAND) 2962e192b24SSimon Glass struct mtd_info *mtd; 2972e192b24SSimon Glass 2982e192b24SSimon Glass mtd = &onenand_mtd; 2992e192b24SSimon Glass 3002e192b24SSimon Glass return mtd->erasesize; 3012e192b24SSimon Glass #else 3022e192b24SSimon Glass BUG(); 3032e192b24SSimon Glass return 0; 3042e192b24SSimon Glass #endif 3052e192b24SSimon Glass } 3062e192b24SSimon Glass 3072e192b24SSimon Glass static inline u32 get_part_sector_size(struct mtdids *id, struct part_info *part) 3082e192b24SSimon Glass { 3092e192b24SSimon Glass if (id->type == MTD_DEV_TYPE_NAND) 3102e192b24SSimon Glass return get_part_sector_size_nand(id); 3112e192b24SSimon Glass else if (id->type == MTD_DEV_TYPE_NOR) 3122e192b24SSimon Glass return get_part_sector_size_nor(id, part); 3132e192b24SSimon Glass else if (id->type == MTD_DEV_TYPE_ONENAND) 3142e192b24SSimon Glass return get_part_sector_size_onenand(); 3152e192b24SSimon Glass else 3162e192b24SSimon Glass DEBUGF("Error: Unknown device type.\n"); 3172e192b24SSimon Glass 3182e192b24SSimon Glass return 0; 3192e192b24SSimon Glass } 3202e192b24SSimon Glass 3212e192b24SSimon Glass /** 3222e192b24SSimon Glass * Parse and initialize global mtdids mapping and create global 3232e192b24SSimon Glass * device/partition list. 3242e192b24SSimon Glass * 3252e192b24SSimon Glass * 'Static' version of command line mtdparts_init() routine. Single partition on 3262e192b24SSimon Glass * a single device configuration. 3272e192b24SSimon Glass * 3282e192b24SSimon Glass * @return 0 on success, 1 otherwise 3292e192b24SSimon Glass */ 3302e192b24SSimon Glass int mtdparts_init(void) 3312e192b24SSimon Glass { 3322e192b24SSimon Glass static int initialized = 0; 3332e192b24SSimon Glass u32 size; 3342e192b24SSimon Glass char *dev_name; 3352e192b24SSimon Glass 3362e192b24SSimon Glass DEBUGF("\n---mtdparts_init---\n"); 3372e192b24SSimon Glass if (!initialized) { 3382e192b24SSimon Glass struct mtdids *id; 3392e192b24SSimon Glass struct part_info *part; 3402e192b24SSimon Glass 3412e192b24SSimon Glass initialized = 1; 3422e192b24SSimon Glass current_mtd_dev = (struct mtd_device *) 3432e192b24SSimon Glass malloc(sizeof(struct mtd_device) + 3442e192b24SSimon Glass sizeof(struct part_info) + 3452e192b24SSimon Glass sizeof(struct mtdids)); 3462e192b24SSimon Glass if (!current_mtd_dev) { 3472e192b24SSimon Glass printf("out of memory\n"); 3482e192b24SSimon Glass return 1; 3492e192b24SSimon Glass } 3502e192b24SSimon Glass memset(current_mtd_dev, 0, sizeof(struct mtd_device) + 3512e192b24SSimon Glass sizeof(struct part_info) + sizeof(struct mtdids)); 3522e192b24SSimon Glass 3532e192b24SSimon Glass id = (struct mtdids *)(current_mtd_dev + 1); 3542e192b24SSimon Glass part = (struct part_info *)(id + 1); 3552e192b24SSimon Glass 3562e192b24SSimon Glass /* id */ 3572e192b24SSimon Glass id->mtd_id = "single part"; 3582e192b24SSimon Glass 3592e192b24SSimon Glass #if defined(CONFIG_JFFS2_DEV) 3602e192b24SSimon Glass dev_name = CONFIG_JFFS2_DEV; 3612e192b24SSimon Glass #else 3622e192b24SSimon Glass dev_name = "nor0"; 3632e192b24SSimon Glass #endif 3642e192b24SSimon Glass 3652e192b24SSimon Glass if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num) != 0) || 3662e192b24SSimon Glass (mtd_device_validate(id->type, id->num, &size) != 0)) { 3672e192b24SSimon Glass printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num); 3682e192b24SSimon Glass free(current_mtd_dev); 3692e192b24SSimon Glass return 1; 3702e192b24SSimon Glass } 3712e192b24SSimon Glass id->size = size; 3722e192b24SSimon Glass INIT_LIST_HEAD(&id->link); 3732e192b24SSimon Glass 3742e192b24SSimon Glass DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n", 3752e192b24SSimon Glass id->type, id->num, id->size, id->mtd_id); 3762e192b24SSimon Glass 3772e192b24SSimon Glass /* partition */ 3782e192b24SSimon Glass part->name = "static"; 3792e192b24SSimon Glass part->auto_name = 0; 3802e192b24SSimon Glass 3812e192b24SSimon Glass #if defined(CONFIG_JFFS2_PART_SIZE) 3822e192b24SSimon Glass part->size = CONFIG_JFFS2_PART_SIZE; 3832e192b24SSimon Glass #else 3842e192b24SSimon Glass part->size = SIZE_REMAINING; 3852e192b24SSimon Glass #endif 3862e192b24SSimon Glass 3872e192b24SSimon Glass #if defined(CONFIG_JFFS2_PART_OFFSET) 3882e192b24SSimon Glass part->offset = CONFIG_JFFS2_PART_OFFSET; 3892e192b24SSimon Glass #else 3902e192b24SSimon Glass part->offset = 0x00000000; 3912e192b24SSimon Glass #endif 3922e192b24SSimon Glass 3932e192b24SSimon Glass part->dev = current_mtd_dev; 3942e192b24SSimon Glass INIT_LIST_HEAD(&part->link); 3952e192b24SSimon Glass 3962e192b24SSimon Glass /* recalculate size if needed */ 3972e192b24SSimon Glass if (part->size == SIZE_REMAINING) 3982e192b24SSimon Glass part->size = id->size - part->offset; 3992e192b24SSimon Glass 4002e192b24SSimon Glass part->sector_size = get_part_sector_size(id, part); 4012e192b24SSimon Glass 4022e192b24SSimon Glass DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n", 4032e192b24SSimon Glass part->name, part->size, part->offset); 4042e192b24SSimon Glass 4052e192b24SSimon Glass /* device */ 4062e192b24SSimon Glass current_mtd_dev->id = id; 4072e192b24SSimon Glass INIT_LIST_HEAD(¤t_mtd_dev->link); 4082e192b24SSimon Glass current_mtd_dev->num_parts = 1; 4092e192b24SSimon Glass INIT_LIST_HEAD(¤t_mtd_dev->parts); 4102e192b24SSimon Glass list_add(&part->link, ¤t_mtd_dev->parts); 4112e192b24SSimon Glass } 4122e192b24SSimon Glass 4132e192b24SSimon Glass return 0; 4142e192b24SSimon Glass } 4152e192b24SSimon Glass #endif /* #ifndef CONFIG_CMD_MTDPARTS */ 4162e192b24SSimon Glass 4172e192b24SSimon Glass /** 4182e192b24SSimon Glass * Return pointer to the partition of a requested number from a requested 4192e192b24SSimon Glass * device. 4202e192b24SSimon Glass * 4212e192b24SSimon Glass * @param dev device that is to be searched for a partition 4222e192b24SSimon Glass * @param part_num requested partition number 4232e192b24SSimon Glass * @return pointer to the part_info, NULL otherwise 4242e192b24SSimon Glass */ 4252e192b24SSimon Glass static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num) 4262e192b24SSimon Glass { 4272e192b24SSimon Glass struct list_head *entry; 4282e192b24SSimon Glass struct part_info *part; 4292e192b24SSimon Glass int num; 4302e192b24SSimon Glass 4312e192b24SSimon Glass if (!dev) 4322e192b24SSimon Glass return NULL; 4332e192b24SSimon Glass 4342e192b24SSimon Glass DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n", 4352e192b24SSimon Glass part_num, MTD_DEV_TYPE(dev->id->type), 4362e192b24SSimon Glass dev->id->num, dev->id->mtd_id); 4372e192b24SSimon Glass 4382e192b24SSimon Glass if (part_num >= dev->num_parts) { 4392e192b24SSimon Glass printf("invalid partition number %d for device %s%d (%s)\n", 4402e192b24SSimon Glass part_num, MTD_DEV_TYPE(dev->id->type), 4412e192b24SSimon Glass dev->id->num, dev->id->mtd_id); 4422e192b24SSimon Glass return NULL; 4432e192b24SSimon Glass } 4442e192b24SSimon Glass 4452e192b24SSimon Glass /* locate partition number, return it */ 4462e192b24SSimon Glass num = 0; 4472e192b24SSimon Glass list_for_each(entry, &dev->parts) { 4482e192b24SSimon Glass part = list_entry(entry, struct part_info, link); 4492e192b24SSimon Glass 4502e192b24SSimon Glass if (part_num == num++) { 4512e192b24SSimon Glass return part; 4522e192b24SSimon Glass } 4532e192b24SSimon Glass } 4542e192b24SSimon Glass 4552e192b24SSimon Glass return NULL; 4562e192b24SSimon Glass } 4572e192b24SSimon Glass 4582e192b24SSimon Glass /***************************************************/ 459a187559eSBin Meng /* U-Boot commands */ 4602e192b24SSimon Glass /***************************************************/ 4612e192b24SSimon Glass 4622e192b24SSimon Glass /** 4632e192b24SSimon Glass * Routine implementing fsload u-boot command. This routine tries to load 4642e192b24SSimon Glass * a requested file from jffs2/cramfs filesystem on a current partition. 4652e192b24SSimon Glass * 4662e192b24SSimon Glass * @param cmdtp command internal data 4672e192b24SSimon Glass * @param flag command flag 4682e192b24SSimon Glass * @param argc number of arguments supplied to the command 4692e192b24SSimon Glass * @param argv arguments list 4702e192b24SSimon Glass * @return 0 on success, 1 otherwise 4712e192b24SSimon Glass */ 4722e192b24SSimon Glass int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 4732e192b24SSimon Glass { 4742e192b24SSimon Glass char *fsname; 4752e192b24SSimon Glass char *filename; 4762e192b24SSimon Glass int size; 4772e192b24SSimon Glass struct part_info *part; 4782e192b24SSimon Glass ulong offset = load_addr; 4792e192b24SSimon Glass 4802e192b24SSimon Glass /* pre-set Boot file name */ 48100caae6dSSimon Glass filename = env_get("bootfile"); 48200caae6dSSimon Glass if (!filename) 4832e192b24SSimon Glass filename = "uImage"; 4842e192b24SSimon Glass 4852e192b24SSimon Glass if (argc == 2) { 4862e192b24SSimon Glass filename = argv[1]; 4872e192b24SSimon Glass } 4882e192b24SSimon Glass if (argc == 3) { 4892e192b24SSimon Glass offset = simple_strtoul(argv[1], NULL, 16); 4902e192b24SSimon Glass load_addr = offset; 4912e192b24SSimon Glass filename = argv[2]; 4922e192b24SSimon Glass } 4932e192b24SSimon Glass 4942e192b24SSimon Glass /* make sure we are in sync with env variables */ 4952e192b24SSimon Glass if (mtdparts_init() !=0) 4962e192b24SSimon Glass return 1; 4972e192b24SSimon Glass 4982e192b24SSimon Glass if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){ 4992e192b24SSimon Glass 5002e192b24SSimon Glass /* check partition type for cramfs */ 5012e192b24SSimon Glass fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2"); 5022e192b24SSimon Glass printf("### %s loading '%s' to 0x%lx\n", fsname, filename, offset); 5032e192b24SSimon Glass 5042e192b24SSimon Glass if (cramfs_check(part)) { 5052e192b24SSimon Glass size = cramfs_load ((char *) offset, part, filename); 5062e192b24SSimon Glass } else { 5072e192b24SSimon Glass /* if this is not cramfs assume jffs2 */ 5082e192b24SSimon Glass size = jffs2_1pass_load((char *)offset, part, filename); 5092e192b24SSimon Glass } 5102e192b24SSimon Glass 5112e192b24SSimon Glass if (size > 0) { 5122e192b24SSimon Glass printf("### %s load complete: %d bytes loaded to 0x%lx\n", 5132e192b24SSimon Glass fsname, size, offset); 514018f5303SSimon Glass env_set_hex("filesize", size); 5152e192b24SSimon Glass } else { 5162e192b24SSimon Glass printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename); 5172e192b24SSimon Glass } 5182e192b24SSimon Glass 5192e192b24SSimon Glass return !(size > 0); 5202e192b24SSimon Glass } 5212e192b24SSimon Glass return 1; 5222e192b24SSimon Glass } 5232e192b24SSimon Glass 5242e192b24SSimon Glass /** 5252e192b24SSimon Glass * Routine implementing u-boot ls command which lists content of a given 5262e192b24SSimon Glass * directory on a current partition. 5272e192b24SSimon Glass * 5282e192b24SSimon Glass * @param cmdtp command internal data 5292e192b24SSimon Glass * @param flag command flag 5302e192b24SSimon Glass * @param argc number of arguments supplied to the command 5312e192b24SSimon Glass * @param argv arguments list 5322e192b24SSimon Glass * @return 0 on success, 1 otherwise 5332e192b24SSimon Glass */ 5342e192b24SSimon Glass int do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5352e192b24SSimon Glass { 5362e192b24SSimon Glass char *filename = "/"; 5372e192b24SSimon Glass int ret; 5382e192b24SSimon Glass struct part_info *part; 5392e192b24SSimon Glass 5402e192b24SSimon Glass if (argc == 2) 5412e192b24SSimon Glass filename = argv[1]; 5422e192b24SSimon Glass 5432e192b24SSimon Glass /* make sure we are in sync with env variables */ 5442e192b24SSimon Glass if (mtdparts_init() !=0) 5452e192b24SSimon Glass return 1; 5462e192b24SSimon Glass 5472e192b24SSimon Glass if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){ 5482e192b24SSimon Glass 5492e192b24SSimon Glass /* check partition type for cramfs */ 5502e192b24SSimon Glass if (cramfs_check(part)) { 5512e192b24SSimon Glass ret = cramfs_ls (part, filename); 5522e192b24SSimon Glass } else { 5532e192b24SSimon Glass /* if this is not cramfs assume jffs2 */ 5542e192b24SSimon Glass ret = jffs2_1pass_ls(part, filename); 5552e192b24SSimon Glass } 5562e192b24SSimon Glass 5572e192b24SSimon Glass return ret ? 0 : 1; 5582e192b24SSimon Glass } 5592e192b24SSimon Glass return 1; 5602e192b24SSimon Glass } 5612e192b24SSimon Glass 5622e192b24SSimon Glass /** 5632e192b24SSimon Glass * Routine implementing u-boot fsinfo command. This routine prints out 5642e192b24SSimon Glass * miscellaneous filesystem informations/statistics. 5652e192b24SSimon Glass * 5662e192b24SSimon Glass * @param cmdtp command internal data 5672e192b24SSimon Glass * @param flag command flag 5682e192b24SSimon Glass * @param argc number of arguments supplied to the command 5692e192b24SSimon Glass * @param argv arguments list 5702e192b24SSimon Glass * @return 0 on success, 1 otherwise 5712e192b24SSimon Glass */ 5722e192b24SSimon Glass int do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5732e192b24SSimon Glass { 5742e192b24SSimon Glass struct part_info *part; 5752e192b24SSimon Glass char *fsname; 5762e192b24SSimon Glass int ret; 5772e192b24SSimon Glass 5782e192b24SSimon Glass /* make sure we are in sync with env variables */ 5792e192b24SSimon Glass if (mtdparts_init() !=0) 5802e192b24SSimon Glass return 1; 5812e192b24SSimon Glass 5822e192b24SSimon Glass if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){ 5832e192b24SSimon Glass 5842e192b24SSimon Glass /* check partition type for cramfs */ 5852e192b24SSimon Glass fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2"); 5862e192b24SSimon Glass printf("### filesystem type is %s\n", fsname); 5872e192b24SSimon Glass 5882e192b24SSimon Glass if (cramfs_check(part)) { 5892e192b24SSimon Glass ret = cramfs_info (part); 5902e192b24SSimon Glass } else { 5912e192b24SSimon Glass /* if this is not cramfs assume jffs2 */ 5922e192b24SSimon Glass ret = jffs2_1pass_info(part); 5932e192b24SSimon Glass } 5942e192b24SSimon Glass 5952e192b24SSimon Glass return ret ? 0 : 1; 5962e192b24SSimon Glass } 5972e192b24SSimon Glass return 1; 5982e192b24SSimon Glass } 5992e192b24SSimon Glass 6002e192b24SSimon Glass /***************************************************/ 6012e192b24SSimon Glass U_BOOT_CMD( 6022e192b24SSimon Glass fsload, 3, 0, do_jffs2_fsload, 6032e192b24SSimon Glass "load binary file from a filesystem image", 6042e192b24SSimon Glass "[ off ] [ filename ]\n" 6052e192b24SSimon Glass " - load binary file from flash bank\n" 6062e192b24SSimon Glass " with offset 'off'" 6072e192b24SSimon Glass ); 6082e192b24SSimon Glass U_BOOT_CMD( 609314f6362SSiva Durga Prasad Paladugu fsls, 2, 1, do_jffs2_ls, 6102e192b24SSimon Glass "list files in a directory (default /)", 6112e192b24SSimon Glass "[ directory ]" 6122e192b24SSimon Glass ); 6132e192b24SSimon Glass 6142e192b24SSimon Glass U_BOOT_CMD( 6152e192b24SSimon Glass fsinfo, 1, 1, do_jffs2_fsinfo, 6162e192b24SSimon Glass "print information about filesystems", 6172e192b24SSimon Glass "" 6182e192b24SSimon Glass ); 6192e192b24SSimon Glass /***************************************************/ 620