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