diff --git a/CHANGELOG b/CHANGELOG index 7a5ab58ea..c3b6848d3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,30 @@ Changes for U-Boot 1.1.3: ====================================================================== +* Add common (with Linux) MTD partition scheme and "mtdparts" command + + Old, obsolete and duplicated code was cleaned up and replace by the + new partitioning method. There are two possible approaches now: + + The first one is to define a single, static partition: + + #undef CONFIG_JFFS2_CMDLINE + #define CONFIG_JFFS2_DEV "nor0" + #define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF /* use whole device */ + #define CONFIG_JFFS2_PART_SIZE 0x00100000 /* use 1MB */ + #define CONFIG_JFFS2_PART_OFFSET 0x00000000 + + The second method uses the mtdparts command line option and dynamic + partitioning: + + /* mtdparts command line support */ + #define CONFIG_JFFS2_CMDLINE + #define MTDIDS_DEFAULT "nor1=zuma-1,nor2=zuma-2" + #define MTDPARTS_DEFAULT "mtdparts=zuma-1:-(jffs2),zuma-2:-(user)" + + Command line of course produces bigger images, and may be inappropriate + for some targets, so by default it's off. + * Fix build problems for PM856 Board * Fix sign extension bug in 'fpga loadb' command; diff --git a/board/dave/PPChameleonEVB/config.mk b/board/dave/PPChameleonEVB/config.mk index 1bdf5e4fc..5856aec0c 100644 --- a/board/dave/PPChameleonEVB/config.mk +++ b/board/dave/PPChameleonEVB/config.mk @@ -21,4 +21,8 @@ # MA 02111-1307 USA # +# Reserve 256 kB for Monitor TEXT_BASE = 0xFFFC0000 + +# Reserve 320 kB for Monitor +#TEXT_BASE = 0xFFFB0000 diff --git a/board/eltec/bab7xx/asm_init.S b/board/eltec/bab7xx/asm_init.S index 3f88bc2b4..2a9b33e12 100644 --- a/board/eltec/bab7xx/asm_init.S +++ b/board/eltec/bab7xx/asm_init.S @@ -24,6 +24,7 @@ */ #include +#include #include <74xx_7xx.h> #include #include diff --git a/board/eltec/bab7xx/l2cache.c b/board/eltec/bab7xx/l2cache.c index 077f2c919..1e7537745 100644 --- a/board/eltec/bab7xx/l2cache.c +++ b/board/eltec/bab7xx/l2cache.c @@ -27,6 +27,7 @@ #include #include +#include /* defines L2CR register for MPC750 */ diff --git a/board/eltec/elppc/asm_init.S b/board/eltec/elppc/asm_init.S index a5605b703..1b8d399ed 100644 --- a/board/eltec/elppc/asm_init.S +++ b/board/eltec/elppc/asm_init.S @@ -24,6 +24,7 @@ */ #include +#include #include #include diff --git a/board/fads/fads.h b/board/fads/fads.h index 9aed226b1..aff1b7efe 100644 --- a/board/fads/fads.h +++ b/board/fads/fads.h @@ -197,9 +197,25 @@ #define CFG_DIRECT_FLASH_TFTP #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_NUM_BANKS CFG_MAX_FLASH_BANKS -#define CFG_JFFS2_FIRST_SECTOR 4 + +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=fads0,nor1=fads-1,nor2=fads-2,nor3=fads-3" +#define MTDPARTS_DEFAULT "mtdparts=fads-0:-@1m(user1),fads-1:-(user2),fads-2:-(user3),fads-3:-(user4)" +*/ + #define CFG_JFFS2_SORT_FRAGMENTS #endif /* CFG_CMD_JFFS2 */ diff --git a/board/funkwerk/vovpn-gw/flash.c b/board/funkwerk/vovpn-gw/flash.c index 4073453ad..7dd0d3f23 100644 --- a/board/funkwerk/vovpn-gw/flash.c +++ b/board/funkwerk/vovpn-gw/flash.c @@ -447,60 +447,3 @@ flash_real_protect(flash_info_t *info, long sector, int prot) *addr = FLASH_CMD_RESET; return (0); } - -/*----------------------------------------------------------------------- - * Support for flash file system (JFFS2) - * - * We use custom partition info function because we have to fit the - * file system image between first sector (containing hard reset - * configuration word) and the sector containing U-Boot image. Standard - * partition info function does not allow for last sector specification - * and assumes that the file system occupies flash bank up to and - * including bank's last sector. - */ -#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CFG_JFFS_CUSTOM_PART) -#error TODO - -#ifndef CFG_JFFS2_FIRST_SECTOR -#define CFG_JFFS2_FIRST_SECTOR 0 -#endif -#ifndef CFG_JFFS2_FIRST_BANK -#define CFG_JFFS2_FIRST_BANK 0 -#endif -#ifndef CFG_JFFS2_NUM_BANKS -#define CFG_JFFS2_NUM_BANKS 1 -#endif -#define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1) - -#include - -static struct part_info partition; - -struct part_info *jffs2_part_info(int part_num) -{ - int i; - - if (part_num == 0) { - if (partition.usr_priv == 0) { - partition.offset = - (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; - for (i = CFG_JFFS2_FIRST_BANK; i <= CFG_JFFS2_LAST_BANK; i++) - partition.size += flash_info[i].size; - partition.size -= - flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - - flash_info[CFG_JFFS2_FIRST_BANK].start[0]; -#ifdef CFG_JFFS2_LAST_SECTOR - i = flash_info[CFG_JFFS2_LAST_BANK].sector_count - 1; - partition.size -= - flash_info[CFG_JFFS2_LAST_BANK].start[i] - - flash_info[CFG_JFFS2_LAST_BANK].start[CFG_JFFS2_LAST_SECTOR]; -#endif - - partition.usr_priv = (void *)1; - } - return &partition; - } - return 0; -} - -#endif /* JFFS2 */ diff --git a/board/innokom/flash.c b/board/innokom/flash.c index 29c916648..298acc86a 100644 --- a/board/innokom/flash.c +++ b/board/innokom/flash.c @@ -35,10 +35,6 @@ #include #include -#if defined CFG_JFFS_CUSTOM_PART -#include -#endif - /* Debugging macros ------------------------------------------------------ */ #undef FLASH_DEBUG @@ -78,179 +74,6 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; - -#if defined CFG_JFFS_CUSTOM_PART - -/** - * jffs2_part_info - get information about a JFFS2 partition - * - * @part_num: number of the partition you want to get info about - * @return: struct part_info* in case of success, 0 if failure - */ - -static struct part_info part; -static int current_part = -1; - -#ifdef CONFIG_MTD_INNOKOM_16MB -#ifdef CONFIG_MTD_INNOKOM_64MB -#error Please define only one CONFIG_MTD_INNOKOM_XXMB option. -#endif -struct part_info* jffs2_part_info(int part_num) { - void *jffs2_priv_saved = part.jffs2_priv; - - PRINTK2("jffs2_part_info: part_num=%i\n",part_num); - - if (current_part == part_num) - return ∂ - - /* u-boot partition */ - if(part_num==0){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00000000; - part.size=256*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* primary OS+firmware partition */ - if(part_num==1){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00040000; - part.size=768*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* secondary OS+firmware partition */ - if(part_num==2){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00100000; - part.size=8*1024*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* data partition */ - if(part_num==3){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00900000; - part.size=7*1024*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - if (current_part == part_num) { - part.usr_priv = ¤t_part; - part.jffs2_priv = jffs2_priv_saved; - return ∂ - } - - PRINTK("jffs2_part_info: end of partition table\n"); - return 0; -} -#endif /* CONFIG_MTD_INNOKOM_16MB */ - -#ifdef CONFIG_MTD_INNOKOM_64MB -#ifdef CONFIG_MTD_INNOKOM_16MB -#error Please define only one CONFIG_MTD_INNOKOM_XXMB option. -#endif -struct part_info* jffs2_part_info(int part_num) { - void *jffs2_priv_saved = part.jffs2_priv; - - PRINTK2("jffs2_part_info: part_num=%i\n",part_num); - - if (current_part == part_num) - return ∂ - - /* u-boot partition */ - if(part_num==0){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00000000; - part.size=256*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* primary OS+firmware partition */ - if(part_num==1){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00040000; - part.size=16*1024*1024-128*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* secondary OS+firmware partition */ - if(part_num==2){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x01020000; - part.size=16*1024*1024-128*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* data partition */ - if(part_num==3){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x02000000; - part.size=32*1024*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - PRINTK("part.offset = 0x%08x\n",(unsigned int)part.offset); - PRINTK("part.size = 0x%08x\n",(unsigned int)part.size); - } - - if (current_part == part_num) { - part.usr_priv = ¤t_part; - part.jffs2_priv = jffs2_priv_saved; - return ∂ - } - - PRINTK("jffs2_part_info: end of partition table\n"); - return 0; -} -#endif /* CONFIG_MTD_INNOKOM_64MB */ -#endif /* defined CFG_JFFS_CUSTOM_PART */ - - /** * flash_init: - initialize data structures for flash chips * diff --git a/board/mpc8260ads/flash.c b/board/mpc8260ads/flash.c index b2e9df243..59997aac4 100644 --- a/board/mpc8260ads/flash.c +++ b/board/mpc8260ads/flash.c @@ -490,59 +490,3 @@ int flash_real_protect(flash_info_t *info, long sector, int prot) return rc; } - -/*----------------------------------------------------------------------- - * Support for flash file system (JFFS2) - * - * We use custom partition info function because we have to fit the - * file system image between first sector (containing hard reset - * configuration word) and the sector containing U-Boot image. Standard - * partition info function does not allow for last sector specification - * and assumes that the file system occupies flash bank up to and - * including bank's last sector. - */ -#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CFG_JFFS_CUSTOM_PART) - -#ifndef CFG_JFFS2_FIRST_SECTOR -#define CFG_JFFS2_FIRST_SECTOR 0 -#endif -#ifndef CFG_JFFS2_FIRST_BANK -#define CFG_JFFS2_FIRST_BANK 0 -#endif -#ifndef CFG_JFFS2_NUM_BANKS -#define CFG_JFFS2_NUM_BANKS 1 -#endif -#define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1) - -#include - -static struct part_info partition; - -struct part_info *jffs2_part_info(int part_num) -{ - int i; - - if (part_num == 0) { - if (partition.usr_priv == 0) { - partition.offset = - (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; - for (i = CFG_JFFS2_FIRST_BANK; i <= CFG_JFFS2_LAST_BANK; i++) - partition.size += flash_info[i].size; - partition.size -= - flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - - flash_info[CFG_JFFS2_FIRST_BANK].start[0]; -#ifdef CFG_JFFS2_LAST_SECTOR - i = flash_info[CFG_JFFS2_LAST_BANK].sector_count - 1; - partition.size -= - flash_info[CFG_JFFS2_LAST_BANK].start[i] - - flash_info[CFG_JFFS2_LAST_BANK].start[CFG_JFFS2_LAST_SECTOR]; -#endif - - partition.usr_priv = (void *)1; - } - return &partition; - } - return 0; -} - -#endif /* JFFS2 */ diff --git a/board/mx1fs2/flash.c b/board/mx1fs2/flash.c index 3a79a9eb4..38063106e 100644 --- a/board/mx1fs2/flash.c +++ b/board/mx1fs2/flash.c @@ -25,10 +25,6 @@ #include -#if defined CFG_JFFS_CUSTOM_PART -#include -#endif - #define FLASH_BANK_SIZE MX1FS2_FLASH_BANK_SIZE #define MAIN_SECT_SIZE MX1FS2_FLASH_SECT_SIZE @@ -70,67 +66,6 @@ static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data); static void flash_sync_real_protect(flash_info_t * info); #endif -#if defined CFG_JFFS_CUSTOM_PART - -/** - * jffs2_part_info - get information about a JFFS2 partition - * - * @part_num: number of the partition you want to get info about - * @return: struct part_info* in case of success, 0 if failure - */ - -static struct part_info part; -static int current_part = -1; - -struct part_info * -jffs2_part_info(int part_num) -{ - void *jffs2_priv_saved = part.jffs2_priv; - - printf("jffs2_part_info: part_num=%i\n", part_num); - - if (current_part == part_num) - return ∂ - - /* rootfs */ - if (part_num == 0) { - memset(&part, 0, sizeof (part)); - - part.offset = (char *) MX1FS2_JFFS2_PART0_START; - part.size = MX1FS2_JFFS2_PART0_SIZE; - - /* Mark the struct as ready */ - current_part = part_num; - - printf("part.offset = 0x%08x\n", (unsigned int) part.offset); - printf("part.size = 0x%08x\n", (unsigned int) part.size); - } - - /* userfs */ - if (part_num == 1) { - memset(&part, 0, sizeof (part)); - - part.offset = (char *) MX1FS2_JFFS2_PART1_START; - part.size = MX1FS2_JFFS2_PART1_SIZE; - - /* Mark the struct as ready */ - current_part = part_num; - - printf("part.offset = 0x%08x\n", (unsigned int) part.offset); - printf("part.size = 0x%08x\n", (unsigned int) part.size); - } - - if (current_part == part_num) { - part.usr_priv = ¤t_part; - part.jffs2_priv = jffs2_priv_saved; - return ∂ - } - - printf("jffs2_part_info: end of partition table\n"); - return 0; -} -#endif /* CFG_JFFS_CUSTOM_PART */ - /*----------------------------------------------------------------------- * flash_init() * diff --git a/board/sixnet/sixnet.c b/board/sixnet/sixnet.c index 42d149704..c31ea539e 100644 --- a/board/sixnet/sixnet.c +++ b/board/sixnet/sixnet.c @@ -601,70 +601,3 @@ long int initdram(int board_type) return (size_sdram); } - -#ifdef CFG_JFFS_CUSTOM_PART - -static struct part_info part; - -#define jffs2_block(i) \ - ((struct jffs2_unknown_node*)(CFG_JFFS2_BASE + (i) * 65536)) - -struct part_info* jffs2_part_info(int part_num) -{ - DECLARE_GLOBAL_DATA_PTR; - bd_t *bd = gd->bd; - char* s; - int i; - int bootnor = 0; /* assume booting from NAND flash */ - - if (part_num != 0) - return 0; /* only support one partition */ - - if (part.usr_priv == (void*)1) - return ∂ /* already have part info */ - - memset(&part, 0, sizeof(part)); - - if (nand_dev_desc[0].ChipID == NAND_ChipID_UNKNOWN) - bootnor = 1; - else if (bd->bi_flashsize < 0x800000) - bootnor = 0; - else for (i = 0; !bootnor && i < 4; ++i) { - /* boot from NOR if JFFS2 info in any of - * first 4 erase blocks - */ - - if (jffs2_block(i)->magic == JFFS2_MAGIC_BITMASK) - bootnor = 1; - } - - if (bootnor) { - /* no NAND flash or boot in NOR, use NOR flash */ - part.offset = (unsigned char *)CFG_JFFS2_BASE; - part.size = CFG_JFFS2_SIZE; - } - else { - char readcmd[60]; - - /* boot info in NAND flash, get and use copy in RAM */ - - /* override info from environment if present */ - s = getenv("fsaddr"); - part.offset = s ? (void *)simple_strtoul(s, NULL, 16) - : (void *)CFG_JFFS2_RAMBASE; - s = getenv("fssize"); - part.size = s ? simple_strtoul(s, NULL, 16) - : CFG_JFFS2_RAMSIZE; - - /* read from nand flash */ - sprintf(readcmd, "nand read.jffs2 %x 0 %x", - (uint32_t)part.offset, part.size); - run_command(readcmd, 0); - } - - part.erasesize = 0; /* unused */ - part.usr_priv=(void*)1; /* ready */ - - return ∂ -} -#endif /* ifdef CFG_JFFS_CUSTOM_PART */ diff --git a/board/voiceblue/voiceblue.c b/board/voiceblue/voiceblue.c index 969110658..7a2d243ef 100644 --- a/board/voiceblue/voiceblue.c +++ b/board/voiceblue/voiceblue.c @@ -56,90 +56,10 @@ int dram_init(void) return 0; } -#ifndef VOICEBLUE_SMALL_FLASH - -#include - -extern flash_info_t flash_info[]; -static struct part_info partinfo; -static int current_part = -1; - -/* Partition table (Linux MTD see it this way) - * - * 0 - U-Boot - * 1 - env - * 2 - redundant env - * 3 - data1 (jffs2) - * 4 - data2 (jffs2) - */ - -static struct { - ulong offset; - ulong size; -} part[5]; - -static void partition_flash(flash_info_t *info) -{ - char mtdparts[128]; - int i, n, size, psize; - const ulong plen[3] = { CFG_MONITOR_LEN, CFG_ENV_SIZE, CFG_ENV_SIZE }; - - size = n = 0; - for (i = 0; i < 4; i++) { - part[i].offset = info->start[n]; - psize = i < 3 ? plen[i] : (info->size - size) / 2; - while (part[i].size < psize) { - if (++n > info->sector_count) { - printf("Partitioning error. System halted.\n"); - while (1) ; - } - part[i].size += info->start[n] - info->start[n - 1]; - } - size += part[i].size; - } - part[4].offset = info->start[n]; - part[4].size = info->start[info->sector_count - 1] - info->start[n]; - - sprintf(mtdparts, "omapflash.0:" - "%dk(U-Boot)ro,%dk(env),%dk(r_env),%dk(data1),-(data2)", - part[0].size >> 10, part[1].size >> 10, - part[2].size >> 10, part[3].size >> 10); - setenv ("mtdparts", mtdparts); -} - -struct part_info* jffs2_part_info(int part_num) -{ - void *jffs2_priv_saved = partinfo.jffs2_priv; - - if (part_num != 3 && part_num != 4) - return NULL; - - if (current_part != part_num) { - memset(&partinfo, 0, sizeof(partinfo)); - current_part = part_num; - partinfo.offset = (char*) part[part_num].offset; - partinfo.size = part[part_num].size; - partinfo.usr_priv = ¤t_part; - partinfo.jffs2_priv = jffs2_priv_saved; - } - - return &partinfo; -} - -#endif - int misc_init_r(void) { *((volatile unsigned short *) VOICEBLUE_LED_REG) = 0x55; -#ifndef VOICEBLUE_SMALL_FLASH - if (flash_info[0].flash_id == FLASH_UNKNOWN) { - printf("Unknown flash. System halted.\n"); - while (1) ; - } - partition_flash(&flash_info[0]); -#endif - return 0; } diff --git a/board/xsengine/flash.c b/board/xsengine/flash.c index bfa287b00..3f93700d6 100644 --- a/board/xsengine/flash.c +++ b/board/xsengine/flash.c @@ -27,10 +27,6 @@ #include #include -#if defined CFG_JFFS_CUSTOM_PART -#include -#endif - #define SWAP(x) __swab32(x) flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ @@ -40,80 +36,6 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info); static int write_word (flash_info_t *info, ulong dest, ulong data); static void flash_get_offsets (ulong base, flash_info_t *info); -#if defined CFG_JFFS_CUSTOM_PART - -/* - * jffs2_part_info - get information about a JFFS2 partition - * - * @part_num: number of the partition you want to get info about - * @return: struct part_info* in case of success, 0 if failure - */ - -static struct part_info part; -static int current_part = -1; - -struct part_info* jffs2_part_info(int part_num) { - void *jffs2_priv_saved = part.jffs2_priv; - - printf("jffs2_part_info: part_num=%i\n",part_num); - - if (current_part == part_num) - return ∂ - - /* u-boot partition */ - if(part_num==0){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00000000; - part.size=256*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - printf("part.offset = 0x%08x\n",(unsigned int)part.offset); - printf("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* primary OS+firmware partition */ - if(part_num==1){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00040000; - part.size=1024*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - printf("part.offset = 0x%08x\n",(unsigned int)part.offset); - printf("part.size = 0x%08x\n",(unsigned int)part.size); - } - - /* secondary OS+firmware partition */ - if(part_num==2){ - memset(&part, 0, sizeof(part)); - - part.offset=(char*)0x00140000; - part.size=8*1024*1024; - - /* Mark the struct as ready */ - current_part = part_num; - - printf("part.offset = 0x%08x\n",(unsigned int)part.offset); - printf("part.size = 0x%08x\n",(unsigned int)part.size); - } - - if (current_part == part_num) { - part.usr_priv = ¤t_part; - part.jffs2_priv = jffs2_priv_saved; - return ∂ - } - - printf("jffs2_part_info: end of partition table\n"); - return 0; -} -#endif - - /*----------------------------------------------------------------------- */ unsigned long flash_init (void) diff --git a/common/cmd_flash.c b/common/cmd_flash.c index 39720826d..0fb4dbb7c 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -27,13 +27,22 @@ #include #include - #ifdef CONFIG_HAS_DATAFLASH #include #endif #if (CONFIG_COMMANDS & CFG_CMD_FLASH) +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) +#include + +/* parition handling routines */ +int mtdparts_init(void); +int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); +int find_dev_and_part(const char *id, struct mtd_device **dev, + u8 *part_num, struct part_info **part); +#endif + extern flash_info_t flash_info[]; /* info for FLASH chips */ /* @@ -295,11 +304,17 @@ int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) flash_print_info (&flash_info[bank-1]); return 0; } + int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { flash_info_t *info; ulong bank, addr_first, addr_last; int n, sect_first, sect_last; +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 dev_type, dev_num, pnum; +#endif int rcode = 0; if (argc < 2) { @@ -327,6 +342,32 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return rcode; } +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + /* erase - erase partition */ + if ((argc == 2) && (id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) { + mtdparts_init(); + if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) { + if (dev->id->type == MTD_DEV_TYPE_NOR) { + bank = dev->id->num; + info = &flash_info[bank]; + addr_first = part->offset + info->start[0]; + addr_last = addr_first + part->size - 1; + + printf ("Erase Flash Parition %s, " + "bank %d, 0x%08lx - 0x%08lx ", + argv[1], bank, addr_first, + addr_last); + + rcode = flash_sect_erase(addr_first, addr_last); + return rcode; + } + + printf("cannot erase, not a NOR device\n"); + return 1; + } + } +#endif + if (argc != 3) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; @@ -401,6 +442,11 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) flash_info_t *info; ulong bank, addr_first, addr_last; int i, p, n, sect_first, sect_last; +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 dev_type, dev_num, pnum; +#endif int rcode = 0; #ifdef CONFIG_HAS_DATAFLASH int status; @@ -488,6 +534,33 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return rcode; } + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + /* protect on/off */ + if ((argc == 3) && (id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) { + mtdparts_init(); + if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) { + if (dev->id->type == MTD_DEV_TYPE_NOR) { + bank = dev->id->num; + info = &flash_info[bank]; + addr_first = part->offset + info->start[0]; + addr_last = addr_first + part->size - 1; + + printf ("%sProtect Flash Parition %s, " + "bank %d, 0x%08lx - 0x%08lx\n", + p ? "" : "Un", argv[1], + bank, addr_first, addr_last); + + rcode = flash_sect_protect (p, addr_first, addr_last); + return rcode; + } + + printf("cannot %sprotect, not a NOR device\n", + p ? "" : "un"); + return 1; + } + } +#endif if (argc != 4) { printf ("Usage:\n%s\n", cmdtp->usage); @@ -609,6 +682,9 @@ U_BOOT_CMD( "w/addr 'start'+'len'-1\n" "erase N:SF[-SL]\n - erase sectors SF-SL in FLASH bank # N\n" "erase bank N\n - erase FLASH bank # N\n" +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + "erase \n - erase partition\n" +#endif "erase all\n - erase all FLASH banks\n" ); @@ -623,6 +699,9 @@ U_BOOT_CMD( "protect on N:SF[-SL]\n" " - protect sectors SF-SL in FLASH bank # N\n" "protect on bank N\n - protect FLASH bank # N\n" +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + "protect on \n - protect partition\n" +#endif "protect on all\n - protect all FLASH banks\n" "protect off start end\n" " - make FLASH from addr 'start' to addr 'end' writable\n" @@ -632,6 +711,9 @@ U_BOOT_CMD( "protect off N:SF[-SL]\n" " - make sectors SF-SL writable in FLASH bank # N\n" "protect off bank N\n - make FLASH bank # N writable\n" +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + "protect off \n - make partition writable\n" +#endif "protect off all\n - make all FLASH banks writable\n" ); diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 45713a38b..21eacc2f1 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -1,11 +1,23 @@ /* * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * * (C) Copyright 2002 * Robert Schwebel, Pengutronix, + * * (C) Copyright 2003 * Kai-Uwe Bloem, Auerswald GmbH & Co KG, * + * (C) Copyright 2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Added support for reading flash partition table from environment. + * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4 + * kernel tree. + * + * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ + * Copyright 2002 SYSGO Real-Time Solutions GmbH + * * See file CREDITS for list of people who contributed to this * project. * @@ -26,103 +38,1726 @@ */ /* - * Boot support + * Three environment variables are used by the parsing routines: + * + * 'partition' - keeps current partition identifier + * + * partition := + * := ,part_num + * + * + * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping + * + * mtdids=[,,...] + * + * := = + * := 'nand'|'nor' + * := mtd device number, 0... + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * + * + * 'mtdparts' - partition list + * + * mtdparts=mtdparts=[;...] + * + * := :[,...] + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * := [@][][] + * := standard linux memsize OR '-' to denote all remaining space + * := partition start offset within the device + * := '(' NAME ')' + * := when set to 'ro' makes partition read-only (not used, passed to kernel) + * + * Notes: + * - each used in mtdparts must albo exist in 'mtddis' mapping + * - if the above variables are not set defaults for a given target are used + * + * Examples: + * + * 1 NOR Flash, with 1 single writable partition: + * mtdids=nor0=edb7312-nor + * mtdparts=mtdparts=edb7312-nor:- + * + * 1 NOR Flash with 2 partitions, 1 NAND with one + * mtdids=nor0=edb7312-nor,nand0=edb7312-nand + * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home) + * + */ + +/* + * JFFS2/CRAMFS support */ #include #include -#include -#include -#include +#include +#include +#include +#include +#include #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) #include +/* enable/disable debugging messages */ +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +# define DEBUGF(fmt, args...) printf(fmt ,##args) +#else +# define DEBUGF(fmt, args...) +#endif + +/* special size referring to all the remaining space in a partition */ +#define SIZE_REMAINING 0xFFFFFFFF + +/* special offset value, it is used when not provided by user + * + * this value is used temporarily during parsing, later such offests + * are recalculated */ +#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF + +/* minimum partition size */ +#define MIN_PART_SIZE 4096 + +/* this flag needs to be set in part_info struct mask_flags + * field for read-only partitions */ +#define MTD_WRITEABLE 1 + +#ifdef CONFIG_JFFS2_CMDLINE +/* default values for mtdids and mtdparts variables */ +#if defined(MTDIDS_DEFAULT) +static const char *const mtdids_default = MTDIDS_DEFAULT; +#else +#warning "MTDIDS_DEFAULT not defined!" +static const char *const mtdids_default = NULL; +#endif + +#if defined(MTDPARTS_DEFAULT) +static const char *const mtdparts_default = MTDPARTS_DEFAULT; +#else +#warning "MTDPARTS_DEFAULT not defined!" +static const char *const mtdparts_default = NULL; +#endif + +/* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */ +#define MTDIDS_MAXLEN 128 +#define MTDPARTS_MAXLEN 512 +#define PARTITION_MAXLEN 16 +static char last_ids[MTDIDS_MAXLEN]; +static char last_parts[MTDPARTS_MAXLEN]; +static char last_partition[PARTITION_MAXLEN]; + +/* low level jffs2 cache cleaning routine */ +extern void jffs2_free_cache(struct part_info *part); + +/* mtdids mapping list, filled by parse_ids() */ +struct list_head mtdids; + +/* device/partition list, parse_cmdline() parses into here */ +struct list_head devices; +#endif /* #ifdef CONFIG_JFFS2_CMDLINE */ + +/* current active device and partition number */ +static struct mtd_device *current_dev = NULL; +static u8 current_partnum = 0; + extern int cramfs_check (struct part_info *info); extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename); extern int cramfs_ls (struct part_info *info, char *filename); extern int cramfs_info (struct part_info *info); -static int part_num=0; +static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num); -#ifndef CFG_JFFS_CUSTOM_PART +/* command line only routines */ +#ifdef CONFIG_JFFS2_CMDLINE -#define CFG_JFFS_SINGLE_PART 1 +static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len); +static int device_del(struct mtd_device *dev); -static struct part_info part; - -#ifndef CONFIG_JFFS2_NAND - -struct part_info* -jffs2_part_info(int part_num) +/** + * Parses a string into a number. The number stored at ptr is + * potentially suffixed with K (for kilobytes, or 1024 bytes), + * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or + * 1073741824). If the number is suffixed with K, M, or G, then + * the return value is the number multiplied by one kilobyte, one + * megabyte, or one gigabyte, respectively. + * + * @param ptr where parse begins + * @param retptr output pointer to next char after parse completes (output) + * @return resulting unsigned int + */ +static unsigned long memsize_parse (const char *const ptr, const char **retptr) { - extern flash_info_t flash_info[]; /* info for FLASH chips */ + unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0); + + switch (**retptr) { + case 'G': + case 'g': + ret <<= 10; + case 'M': + case 'm': + ret <<= 10; + case 'K': + case 'k': + ret <<= 10; + (*retptr)++; + default: + break; + } + + return ret; +} + +/** + * Format string describing supplied size. This routine does the opposite job + * to memsize_parse(). Size in bytes is converted to string and if possible + * shortened by using k (kilobytes), m (megabytes) or g (gigabytes) suffix. + * + * Note, that this routine does not check for buffer overflow, it's the caller + * who must assure enough space. + * + * @param buf output buffer + * @param size size to be converted to string + */ +static void memsize_format(char *buf, u32 size) +{ +#define SIZE_GB ((u32)1024*1024*1024) +#define SIZE_MB ((u32)1024*1024) +#define SIZE_KB ((u32)1024) + + if ((size % SIZE_GB) == 0) + sprintf(buf, "%lug", size/SIZE_GB); + else if ((size % SIZE_MB) == 0) + sprintf(buf, "%lum", size/SIZE_MB); + else if (size % SIZE_KB == 0) + sprintf(buf, "%luk", size/SIZE_KB); + else + sprintf(buf, "%lu", size); +} + +/** + * Save current device and partition in environment variable 'partition'. + */ +static void current_save(void) +{ + char buf[16]; + + DEBUGF("--- current_save ---\n"); + + if (current_dev) { + sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_dev->id->type), + current_dev->id->num, current_partnum); + + setenv("partition", buf); + strncpy(last_partition, buf, 16); + + DEBUGF("=> partition %s\n", buf); + } else { + setenv("partition", NULL); + last_partition[0] = '\0'; + + DEBUGF("=> partition NULL\n"); + } +} + +/** + * Performs sanity check for supplied NOR flash partition. Table of existing + * NOR flash devices is searched and partition device is located. Alignment + * with the granularity of NOR flash sectors is verified. + * + * @param id of the parent device + * @param part partition to validate + * @return 0 if partition is valid, 1 otherwise + */ +static int part_validate_nor(struct mtdids *id, struct part_info *part) +{ +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + /* info for FLASH chips */ + extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + flash_info_t *flash; + int offset_aligned; + u32 end_offset; int i; - if(part_num==0){ + flash = &flash_info[id->num]; - if(part.usr_priv==(void*)1) - return ∂ + offset_aligned = 0; + for (i = 0; i < flash->sector_count; i++) { + if ((flash->start[i] - flash->start[0]) == part->offset) { + offset_aligned = 1; + break; + } + } + if (offset_aligned == 0) { + printf("%s%d: partition (%s) start offset alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } - memset(&part, 0, sizeof(part)); + end_offset = part->offset + part->size; + for (i = 0; i < flash->sector_count; i++) { + if ((flash->start[i] - flash->start[0]) == end_offset) + return 0; + } -#if defined(CFG_JFFS2_FIRST_SECTOR) - part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; + if (flash->size == end_offset) + return 0; + + printf("%s%d: partition (%s) size alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); +#endif + return 1; +} + +/** + * Performs sanity check for supplied NAND flash partition. Table of existing + * NAND flash devices is searched and partition device is located. Alignment + * with the granularity of nand erasesize is verified. + * + * @param id of the parent device + * @param part partition to validate + * @return 0 if partition is valid, 1 otherwise + */ +static int part_validate_nand(struct mtdids *id, struct part_info *part) +{ +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) + /* info for NAND chips */ + extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; + struct nand_chip *nand; + + nand = &nand_dev_desc[id->num]; + + if ((unsigned long)(part->offset) % nand->erasesize) { + printf("%s%d: partition (%s) start offset alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } + + if (part->size % nand->erasesize) { + printf("%s%d: partition (%s) size alignment incorrect\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } + + return 0; #else - part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[0]; + return 1; #endif +} - /* Figure out flash partition size */ - for (i = CFG_JFFS2_FIRST_BANK; i < CFG_JFFS2_NUM_BANKS+CFG_JFFS2_FIRST_BANK; i++) - part.size += flash_info[i].size; +/** + * Performs sanity check for supplied partition. Offset and size are verified + * to be within valid range. Partition type is checked and either + * parts_validate_nor() or parts_validate_nand() is called with the argument + * of part. + * + * @param id of the parent device + * @param part partition to validate + * @return 0 if partition is valid, 1 otherwise + */ +static int part_validate(struct mtdids *id, struct part_info *part) +{ + if (part->size == SIZE_REMAINING) + part->size = id->size - part->offset; -#if defined(CFG_JFFS2_FIRST_SECTOR) && (CFG_JFFS2_FIRST_SECTOR > 0) - part.size -= - flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - - flash_info[CFG_JFFS2_FIRST_BANK].start[0]; -#endif - - /* Mark the struct as ready */ - part.usr_priv=(void*)1; - - return ∂ + if (part->offset > id->size) { + printf("%s: offset %08lx beyond flash size %08lx\n", + id->mtd_id, part->offset, id->size); + return 1; } + + if ((part->offset + part->size) <= part->offset) { + printf("%s%d: partition (%s) size too big\n", + MTD_DEV_TYPE(id->type), id->num, part->name); + return 1; + } + + if (part->offset + part->size > id->size) { + printf("%s: partitioning exceeds flash size\n", id->mtd_id); + return 1; + } + + if (id->type == MTD_DEV_TYPE_NAND) + return part_validate_nand(id, part); + else if (id->type == MTD_DEV_TYPE_NOR) + return part_validate_nor(id, part); + else + DEBUGF("part_validate: invalid dev type\n"); + + return 1; +} + +/** + * Delete selected partition from the partion list of the specified device. + * + * @param dev device to delete partition from + * @param part partition to delete + * @return 0 on success, 1 otherwise + */ +static int part_del(struct mtd_device *dev, struct part_info *part) +{ + /* if there is only one partition, remove whole device */ + if (dev->num_parts == 1) + return device_del(dev); + + /* otherwise just delete this partition */ + + if (dev == current_dev) { + /* we are modyfing partitions for the current device, + * update current */ + struct part_info *curr_pi; + curr_pi = jffs2_part_info(current_dev, current_partnum); + + if (curr_pi) { + if (curr_pi == part) { + printf("current partition deleted, resetting current to 0\n"); + current_partnum = 0; + current_save(); + } else if (part->offset <= curr_pi->offset) { + current_partnum--; + current_save(); + } + } + } + + + jffs2_free_cache(part); + list_del(&part->link); + free(part); + dev->num_parts--; + return 0; } -#else /* CONFIG_JFFS2_NAND */ - -struct part_info* -jffs2_part_info(int part_num) +/** + * Delete all partitions from parts head list, free memory. + * + * @param head list of partitions to delete + */ +static void part_delall(struct list_head *head) { - if(part_num==0){ + struct list_head *entry, *n; + struct part_info *part_tmp; - if(part.usr_priv==(void*)1) - return ∂ + /* clean tmp_list and free allocated memory */ + list_for_each_safe(entry, n, head) { + part_tmp = list_entry(entry, struct part_info, link); - memset(&part, 0, sizeof(part)); - - part.offset = (char *)CONFIG_JFFS2_NAND_OFF; - part.size = CONFIG_JFFS2_NAND_SIZE; /* the bigger size the slower jffs2 */ - -#ifndef CONFIG_JFFS2_NAND_DEV -#define CONFIG_JFFS2_NAND_DEV 0 -#endif - /* nand device with the JFFS2 parition plus 1 */ - part.usr_priv = (void*)(CONFIG_JFFS2_NAND_DEV+1); - return ∂ + jffs2_free_cache(part_tmp); + list_del(entry); + free(part_tmp); } +} + +/** + * Add new partition to the supplied partition list. Make sure partitions are + * sorted by offset in ascending order. + * + * @param head list this partition is to be added to + * @param new partition to be added + */ +static int part_sort_add(struct mtd_device *dev, struct part_info *part) +{ + struct list_head *entry; + struct part_info *new_pi, *curr_pi; + + /* link partition to parrent dev */ + part->dev = dev; + + if (list_empty(&dev->parts)) { + DEBUGF("part_sort_add: list empty\n"); + list_add(&part->link, &dev->parts); + return 0; + } + + new_pi = list_entry(&part->link, struct part_info, link); + + /* get current partition info if we are updating current device */ + curr_pi = NULL; + if (dev == current_dev) + curr_pi = jffs2_part_info(current_dev, current_partnum); + + list_for_each(entry, &dev->parts) { + struct part_info *pi; + + pi = list_entry(entry, struct part_info, link); + + /* be compliant with kernel cmdline, allow only one partition at offset zero */ + if ((new_pi->offset == pi->offset) && (pi->offset == 0)) { + printf("cannot add second partition at offset 0\n"); + return 1; + } + + if (new_pi->offset <= pi->offset) { + list_add_tail(&part->link, entry); + + if (curr_pi && (pi->offset <= curr_pi->offset)) { + /* we are modyfing partitions for the current + * device, update current */ + current_partnum++; + current_save(); + } + + return 0; + } + } + list_add_tail(&part->link, &dev->parts); return 0; } -#endif /* CONFIG_JFFS2_NAND */ -#endif /* ifndef CFG_JFFS_CUSTOM_PART */ - -int -do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +/** + * Add provided partition to the partition list of a given device. + * + * @param dev device to which partition is added + * @param part partition to be added + * @return 0 on success, 1 otherwise + */ +static int part_add(struct mtd_device *dev, struct part_info *part) +{ + /* verify alignment and size */ + if (part_validate(dev->id, part) != 0) + return 1; + + /* partition is ok, add it to the list */ + if (part_sort_add(dev, part) != 0) + return 1; + + dev->num_parts++; + return 0; +} + +/** + * Parse one partition definition, allocate memory and return pointer to this + * location in retpart. + * + * @param partdef pointer to the partition definition string i.e. + * @param ret output pointer to next char after parse completes (output) + * @param retpart pointer to the allocated partition (output) + * @return 0 on success, 1 otherwise + */ +static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart) +{ + struct part_info *part; + unsigned long size; + unsigned long offset; + const char *name; + int name_len; + unsigned int mask_flags; + const char *p; + + p = partdef; + *retpart = NULL; + *ret = NULL; + + /* fetch the partition size */ + if (*p == '-') { + /* assign all remaining space to this partition */ + DEBUGF("'-': remaining size assigned\n"); + size = SIZE_REMAINING; + p++; + } else { + size = memsize_parse(p, &p); + if (size < MIN_PART_SIZE) { + printf("partition size too small (%lx)\n", size); + return 1; + } + } + + /* check for offset */ + offset = OFFSET_NOT_SPECIFIED; + if (*p == '@') { + p++; + offset = memsize_parse(p, &p); + } + + /* now look for the name */ + if (*p == '(') { + name = ++p; + if ((p = strchr(name, ')')) == NULL) { + printf("no closing ) found in partition name\n"); + return 1; + } + name_len = p - name + 1; + if ((name_len - 1) == 0) { + printf("empty partition name\n"); + return 1; + } + p++; + } else { + /* 0x00000000@0x00000000 */ + name_len = 22; + name = NULL; + } + + /* test for options */ + mask_flags = 0; + if (strncmp(p, "ro", 2) == 0) { + mask_flags |= MTD_WRITEABLE; + p += 2; + } + + /* check for next partition definition */ + if (*p == ',') { + if (size == SIZE_REMAINING) { + *ret = NULL; + printf("no partitions allowed after a fill-up partition\n"); + return 1; + } + *ret = ++p; + } else if ((*p == ';') || (*p == '\0')) { + *ret = p; + } else { + printf("unexpected character '%c' at the end of partition\n", *p); + *ret = NULL; + return 1; + } + + /* allocate memory */ + part = (struct part_info *)malloc(sizeof(struct part_info) + name_len); + if (!part) { + printf("out of memory\n"); + return 1; + } + memset(part, 0, sizeof(struct part_info) + name_len); + part->size = size; + part->offset = offset; + part->mask_flags = mask_flags; + part->name = (char *)(part + 1); + + if (name) { + /* copy user provided name */ + strncpy(part->name, name, name_len - 1); + part->auto_name = 0; + } else { + /* auto generated name in form of size@offset */ + sprintf(part->name, "0x%08lx@0x%08lx", size, offset); + part->auto_name = 1; + } + + part->name[name_len - 1] = '\0'; + INIT_LIST_HEAD(&part->link); + + DEBUGF("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n", + part->name, part->size, + part->offset, part->mask_flags); + + *retpart = part; + return 0; +} +#endif/* #ifdef CONFIG_JFFS2_CMDLINE */ + +/** + * Check device number to be within valid range for given device type. + * + * @param dev device to validate + * @return 0 if device is valid, 1 otherwise + */ +static int device_validate(u8 type, u8 num, u32 *size) +{ + if (type == MTD_DEV_TYPE_NOR) { +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + if (num < CFG_MAX_FLASH_BANKS) { + extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + *size = flash_info[num].size; + return 0; + } + + printf("no such FLASH device: %s%d (valid range 0 ... %d\n", + MTD_DEV_TYPE(type), num, CFG_MAX_FLASH_BANKS - 1); +#else + printf("support for FLASH devices not present\n"); +#endif + } else if (type == MTD_DEV_TYPE_NAND) { +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) + if (num < CFG_MAX_NAND_DEVICE) { + extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; + *size = nand_dev_desc[num].totlen; + return 0; + } + + printf("no such NAND device: %s%d (valid range 0 ... %d)\n", + MTD_DEV_TYPE(type), num, CFG_MAX_NAND_DEVICE - 1); +#else + printf("support for NAND devices not present\n"); +#endif + } + + return 1; +} + +#ifdef CONFIG_JFFS2_CMDLINE +/** + * Delete all mtd devices from a supplied devices list, free memory allocated for + * each device and delete all device partitions. + * + * @return 0 on success, 1 otherwise + */ +static int device_delall(struct list_head *head) +{ + struct list_head *entry, *n; + struct mtd_device *dev_tmp; + + /* clean devices list */ + list_for_each_safe(entry, n, head) { + dev_tmp = list_entry(entry, struct mtd_device, link); + list_del(entry); + part_delall(&dev_tmp->parts); + free(dev_tmp); + } + INIT_LIST_HEAD(&devices); + + return 0; +} + +/** + * If provided device exists it's partitions are deleted, device is removed + * from device list and device memory is freed. + * + * @param dev device to be deleted + * @return 0 on success, 1 otherwise + */ +static int device_del(struct mtd_device *dev) +{ + part_delall(&dev->parts); + list_del(&dev->link); + free(dev); + + if (dev == current_dev) { + /* we just deleted current device */ + if (list_empty(&devices)) { + current_dev = NULL; + } else { + /* reset first partition from first dev from the + * devices list as current */ + current_dev = list_entry(devices.next, struct mtd_device, link); + current_partnum = 0; + } + current_save(); + } + + + return 0; +} + +/** + * Search global device list and return pointer to the device of type and num + * specified. + * + * @param type device type + * @param num device number + * @return NULL if requested device does not exist + */ +static struct mtd_device* device_find(u8 type, u8 num) +{ + struct list_head *entry; + struct mtd_device *dev_tmp; + + list_for_each(entry, &devices) { + dev_tmp = list_entry(entry, struct mtd_device, link); + + if ((dev_tmp->id->type == type) && (dev_tmp->id->num == num)) + return dev_tmp; + } + + return NULL; +} + +/** + * Add specified device to the global device list. + * + * @param dev device to be added + */ +static void device_add(struct mtd_device *dev) +{ + if (list_empty(&devices)) { + current_dev = dev; + current_partnum = 0; + current_save(); + } + + list_add_tail(&dev->link, &devices); +} + +/** + * Parse device type, name and mtd-id. If syntax is ok allocate memory and + * return pointer to the device structure. + * + * @param mtd_dev pointer to the device definition string i.e. + * @param ret output pointer to next char after parse completes (output) + * @param retdev pointer to the allocated device (output) + * @return 0 on success, 1 otherwise + */ +static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev) +{ + struct mtd_device *dev; + struct part_info *part; + struct mtdids *id; + const char *mtd_id; + unsigned int mtd_id_len; + const char *p, *pend; + LIST_HEAD(tmp_list); + struct list_head *entry, *n; + u16 num_parts; + u32 offset; + int err = 1; + + p = mtd_dev; + *retdev = NULL; + *ret = NULL; + + DEBUGF("===device_parse===\n"); + + /* fetch */ + mtd_id = p; + if (!(p = strchr(mtd_id, ':'))) { + printf("no identifier\n"); + return 1; + } + mtd_id_len = p - mtd_id + 1; + p++; + + /* verify if we have a valid device specified */ + if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) { + printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id); + return 1; + } + + DEBUGF("dev type = %d (%s), dev num = %d, mtd-id = %s\n", + id->type, MTD_DEV_TYPE(id->type), + id->num, id->mtd_id); + pend = strchr(p, ';'); + DEBUGF("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p); + + + /* parse partitions */ + num_parts = 0; + + offset = 0; + if ((dev = device_find(id->type, id->num)) != NULL) { + /* if device already exists start at the end of the last partition */ + part = list_entry(dev->parts.prev, struct part_info, link); + offset = part->offset + part->size; + } + + while (p && (*p != '\0') && (*p != ';')) { + err = 1; + if ((part_parse(p, &p, &part) != 0) || (!part)) + break; + + /* calculate offset when not specified */ + if (part->offset == OFFSET_NOT_SPECIFIED) + part->offset = offset; + else + offset = part->offset; + + /* verify alignment and size */ + if (part_validate(id, part) != 0) + break; + + offset += part->size; + + /* partition is ok, add it to the list */ + list_add_tail(&part->link, &tmp_list); + num_parts++; + err = 0; + } + if (err == 1) { + part_delall(&tmp_list); + return 1; + } + + if (num_parts == 0) { + printf("no partitions for device %s%d (%s)\n", + MTD_DEV_TYPE(id->type), id->num, id->mtd_id); + return 1; + } + + DEBUGF("\ntotal partitions: %d\n", num_parts); + + /* check for next device presence */ + if (p) { + if (*p == ';') { + *ret = ++p; + } else if (*p == '\0') { + *ret = p; + } else { + printf("unexpected character '%c' at the end of device\n", *p); + *ret = NULL; + return 1; + } + } + + /* allocate memory for mtd_device structure */ + if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) { + printf("out of memory\n"); + return 1; + } + memset(dev, 0, sizeof(struct mtd_device)); + dev->id = id; + dev->num_parts = num_parts; + INIT_LIST_HEAD(&dev->parts); + INIT_LIST_HEAD(&dev->link); + + /* move partitions from tmp_list to dev->parts */ + list_for_each_safe(entry, n, &tmp_list) { + part = list_entry(entry, struct part_info, link); + list_del(entry); + if (part_sort_add(dev, part) != 0) { + device_del(dev); + return 1; + } + } + + *retdev = dev; + + DEBUGF("===\n\n"); + return 0; +} + +/** + * Initialize global device list. + * + * @return 0 on success, 1 otherwise + */ +static int devices_init(void) +{ + last_parts[0] = '\0'; + current_dev = NULL; + current_save(); + + return device_delall(&devices); +} + +/* + * Search global mtdids list and find id of requested type and number. + * + * @return pointer to the id if it exists, NULL otherwise + */ +static struct mtdids* id_find(u8 type, u8 num) +{ + struct list_head *entry; + struct mtdids *id; + + list_for_each(entry, &mtdids) { + id = list_entry(entry, struct mtdids, link); + + if ((id->type == type) && (id->num == num)) + return id; + } + + return NULL; +} + +/** + * Search global mtdids list and find id of a requested mtd_id. + * + * Note: first argument is not null terminated. + * + * @param mtd_id string containing requested mtd_id + * @param mtd_id_len length of supplied mtd_id + * @return pointer to the id if it exists, NULL otherwise + */ +static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len) +{ + struct list_head *entry; + struct mtdids *id; + + DEBUGF("--- id_find_by_mtd_id: '%.*s' (len = %d)\n", + mtd_id_len, mtd_id, mtd_id_len); + + list_for_each(entry, &mtdids) { + id = list_entry(entry, struct mtdids, link); + + DEBUGF("entry: '%s' (len = %d)\n", + id->mtd_id, strlen(id->mtd_id)); + + if (mtd_id_len != strlen(id->mtd_id)) + continue; + if (strncmp(id->mtd_id, mtd_id, mtd_id_len) == 0) + return id; + } + + return NULL; +} +#endif /* #ifdef CONFIG_JFFS2_CMDLINE */ + +/** + * Parse device id string := 'nand'|'nor', return device + * type and number. + * + * @param id string describing device id + * @param ret_id output pointer to next char after parse completes (output) + * @param dev_type parsed device type (output) + * @param dev_num parsed device number (output) + * @return 0 on success, 1 otherwise + */ +int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num) +{ + const char *p = id; + + *dev_type = 0; + if (strncmp(p, "nand", 4) == 0) { + *dev_type = MTD_DEV_TYPE_NAND; + p += 4; + } else if (strncmp(p, "nor", 3) == 0) { + *dev_type = MTD_DEV_TYPE_NOR; + p += 3; + } else { + printf("incorrect device type in %s\n", id); + return 1; + } + + if (!isdigit(*p)) { + printf("incorrect device number in %s\n", id); + return 1; + } + + *dev_num = simple_strtoul(p, (char **)&p, 0); + if (ret_id) + *ret_id = p; + return 0; +} + +#ifdef CONFIG_JFFS2_CMDLINE +/** + * Process all devices and generate corresponding mtdparts string describing + * all partitions on all devices. + * + * @param buf output buffer holding generated mtdparts string (output) + * @param buflen buffer size + * @return 0 on success, 1 otherwise + */ +static int generate_mtdparts(char *buf, u32 buflen) +{ + struct list_head *pentry, *dentry; + struct mtd_device *dev; + struct part_info *part, *prev_part; + char *p = buf; + char tmpbuf[32]; + u32 size, offset, len, part_cnt; + u32 maxlen = buflen - 1; + + DEBUGF("--- generate_mtdparts ---\n"); + + if (list_empty(&devices)) { + buf[0] = '\0'; + return 0; + } + + sprintf(p, "mtdparts="); + p += 9; + + list_for_each(dentry, &devices) { + dev = list_entry(dentry, struct mtd_device, link); + + /* copy mtd_id */ + len = strlen(dev->id->mtd_id) + 1; + if (len > maxlen) + goto cleanup; + memcpy(p, dev->id->mtd_id, len - 1); + p += len - 1; + *(p++) = ':'; + maxlen -= len; + + /* format partitions */ + prev_part = NULL; + part_cnt = 0; + list_for_each(pentry, &dev->parts) { + part = list_entry(pentry, struct part_info, link); + size = part->size; + offset = part->offset; + part_cnt++; + + /* partition size */ + memsize_format(tmpbuf, size); + len = strlen(tmpbuf); + if (len > maxlen) + goto cleanup; + memcpy(p, tmpbuf, len); + p += len; + maxlen -= len; + + + /* add offset only when there is a gap between + * partitions */ + if ((!prev_part && (offset != 0)) || + (prev_part && ((prev_part->offset + prev_part->size) != part->offset))) { + + memsize_format(tmpbuf, offset); + len = strlen(tmpbuf) + 1; + if (len > maxlen) + goto cleanup; + *(p++) = '@'; + memcpy(p, tmpbuf, len - 1); + p += len - 1; + maxlen -= len; + } + + /* copy name only if user supplied */ + if(!part->auto_name) { + len = strlen(part->name) + 2; + if (len > maxlen) + goto cleanup; + + *(p++) = '('; + memcpy(p, part->name, len - 2); + p += len - 2; + *(p++) = ')'; + maxlen -= len; + } + + /* ro mask flag */ + if (part->mask_flags && MTD_WRITEABLE) { + len = 2; + if (len > maxlen) + goto cleanup; + *(p++) = 'r'; + *(p++) = 'o'; + maxlen -= 2; + } + + /* print ',' separator if there are other partitions + * following */ + if (dev->num_parts > part_cnt) { + if (1 > maxlen) + goto cleanup; + *(p++) = ','; + maxlen--; + } + prev_part = part; + } + /* print ';' separator if there are other devices following */ + if (dentry->next != &devices) { + if (1 > maxlen) + goto cleanup; + *(p++) = ';'; + maxlen--; + } + } + + /* we still have at least one char left, as we decremented maxlen at + * the begining */ + *p = '\0'; + + return 0; + +cleanup: + last_parts[0] = '\0'; + return 1; +} + +/** + * Call generate_mtdparts to process all devices and generate corresponding + * mtdparts string, save it in mtdparts environment variable. + * + * @param buf output buffer holding generated mtdparts string (output) + * @param buflen buffer size + * @return 0 on success, 1 otherwise + */ +static int generate_mtdparts_save(char *buf, u32 buflen) +{ + int ret; + + ret = generate_mtdparts(buf, buflen); + + if ((buf[0] != '\0') && (ret == 0)) + setenv("mtdparts", buf); + else + setenv("mtdparts", NULL); + + return ret; +} + +/** + * Format and print out a partition list for each device from global device + * list. + */ +static void list_partitions(void) +{ + struct list_head *dentry, *pentry; + struct part_info *part; + struct mtd_device *dev; + int part_num; + + DEBUGF("\n---list_partitions---\n"); + list_for_each(dentry, &devices) { + dev = list_entry(dentry, struct mtd_device, link); + printf("\ndevice %s%d <%s>, # parts = %d\n", + MTD_DEV_TYPE(dev->id->type), dev->id->num, + dev->id->mtd_id, dev->num_parts); + printf(" #: name\t\t\tsize\t\toffset\t\tmask_flags\n"); + + /* list partitions for given device */ + part_num = 0; + list_for_each(pentry, &dev->parts) { + part = list_entry(pentry, struct part_info, link); + printf(" %d: %-22s\t0x%08x\t0x%08x\t%d\n", + part_num, part->name, part->size, + part->offset, part->mask_flags); + + part_num++; + } + } + if (list_empty(&devices)) + printf("no partitions defined\n"); + + /* current_dev is not NULL only when we have non empty device list */ + if (current_dev) { + part = jffs2_part_info(current_dev, current_partnum); + if (part) { + printf("\nactive partition: %s%d,%d - (%s) 0x%08lx @ 0x%08lx\n", + MTD_DEV_TYPE(current_dev->id->type), + current_dev->id->num, current_partnum, + part->name, part->size, part->offset); + } else { + printf("could not get current partition info\n\n"); + } + } + + printf("\ndefaults:\n"); + printf("mtdids : %s\n", mtdids_default); + printf("mtdparts: %s\n", mtdparts_default); +} + +/** + * Given partition identifier in form of , find + * corresponding device and verify partition number. + * + * @param id string describing device and partition + * @param dev pointer to the requested device (output) + * @param part_num verified partition number (output) + * @param part pointer to requested partition (output) + * @return 0 on success, 1 otherwise + */ +int find_dev_and_part(const char *id, struct mtd_device **dev, + u8 *part_num, struct part_info **part) +{ + u8 type, dnum, pnum; + const char *p; + + DEBUGF("--- find_dev_and_part ---\nid = %s\n", id); + + p = id; + *dev = NULL; + *part = NULL; + *part_num = 0; + + if (id_parse(p, &p, &type, &dnum) != 0) + return 1; + + if ((*p++ != ',') || (*p == '\0')) { + printf("no partition number specified\n"); + return 1; + } + pnum = simple_strtoul(p, (char **)&p, 0); + if (*p != '\0') { + printf("unexpected trailing character '%c'\n", *p); + return 1; + } + + if ((*dev = device_find(type, dnum)) == NULL) { + printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum); + return 1; + } + + if ((*part = jffs2_part_info(*dev, pnum)) == NULL) { + printf("no such partition\n"); + *dev = NULL; + return 1; + } + + *part_num = pnum; + + return 0; +} + +/** + * Find and delete partition. For partition id format see find_dev_and_part(). + * + * @param id string describing device and partition + * @return 0 on success, 1 otherwise + */ +static int delete_partition(const char *id) +{ + u8 pnum; + struct mtd_device *dev; + struct part_info *part; + + if (find_dev_and_part(id, &dev, &pnum, &part) == 0) { + + DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08lx@0x%08lx\n", + MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum, + part->name, part->size, part->offset); + + if (part_del(dev, part) != 0) + return 1; + + if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) { + printf("generated mtdparts too long, reseting to null\n"); + return 1; + } + return 0; + } + + printf("partition %s not found\n", id); + return 1; +} + +/** + * Accept character string describing mtd partitions and call device_parse() + * for each entry. Add created devices to the global devices list. + * + * @param mtdparts string specifing mtd partitions + * @return 0 on success, 1 otherwise + */ +static int parse_mtdparts(const char *const mtdparts) +{ + const char *p = mtdparts; + struct mtd_device *dev; + int err = 1; + + DEBUGF("\n---parse_mtdparts---\nmtdparts = %s\n\n", p); + + /* delete all devices and partitions */ + if (devices_init() != 0) { + printf("could not initialise device list\n"); + return err; + } + + /* re-read 'mtdparts' variable, devices_init may be updating env */ + p = getenv("mtdparts"); + + if (strncmp(p, "mtdparts=", 9) != 0) { + printf("mtdparts variable doesn't start with 'mtdparts='\n"); + return err; + } + p += 9; + + while (p && (*p != '\0')) { + err = 1; + if ((device_parse(p, &p, &dev) != 0) || (!dev)) + break; + + DEBUGF("+ device: %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type), + dev->id->num, dev->id->mtd_id); + + /* check if parsed device is already on the list */ + if (device_find(dev->id->type, dev->id->num) != NULL) { + printf("device %s%d redefined, please correct mtdparts variable\n", + MTD_DEV_TYPE(dev->id->type), dev->id->num); + break; + } + + list_add_tail(&dev->link, &devices); + err = 0; + } + if (err == 1) { + device_delall(&devices); + return 1; + } + + return 0; +} + +/** + * Parse provided string describing mtdids mapping (see file header for mtdids + * variable format). Allocate memory for each entry and add all found entries + * to the global mtdids list. + * + * @param ids mapping string + * @return 0 on success, 1 otherwise + */ +static int parse_mtdids(const char *const ids) +{ + const char *p = ids; + const char *mtd_id; + int mtd_id_len; + struct mtdids *id; + struct list_head *entry, *n; + struct mtdids *id_tmp; + u8 type, num; + u32 size; + int ret = 1; + + DEBUGF("\n---parse_mtdids---\nmtdids = %s\n\n", ids); + + /* clean global mtdids list */ + list_for_each_safe(entry, n, &mtdids) { + id_tmp = list_entry(entry, struct mtdids, link); + DEBUGF("mtdids del: %d %d\n", id_tmp->type, id_tmp->num); + list_del(entry); + free(id_tmp); + } + last_ids[0] = '\0'; + INIT_LIST_HEAD(&mtdids); + + while(p && (*p != '\0')) { + + ret = 1; + /* parse 'nor'|'nand' */ + if (id_parse(p, &p, &type, &num) != 0) + break; + + if (*p != '=') { + printf("mtdids: incorrect \n"); + break; + } + p++; + + /* check if requested device exists */ + if (device_validate(type, num, &size) != 0) + return 1; + + /* locate */ + mtd_id = p; + if ((p = strchr(mtd_id, ',')) != NULL) { + mtd_id_len = p - mtd_id + 1; + p++; + } else { + mtd_id_len = strlen(mtd_id) + 1; + } + if (mtd_id_len == 0) { + printf("mtdids: no identifier\n"); + break; + } + + /* check if this id is already on the list */ + int double_entry = 0; + list_for_each(entry, &mtdids) { + id_tmp = list_entry(entry, struct mtdids, link); + if ((id_tmp->type == type) && (id_tmp->num == num)) { + double_entry = 1; + break; + } + } + if (double_entry) { + printf("device id %s%d redefined, please correct mtdids variable\n", + MTD_DEV_TYPE(type), num); + break; + } + + /* allocate mtdids structure */ + if (!(id = (struct mtdids *)malloc(sizeof(struct mtdids) + mtd_id_len))) { + printf("out of memory\n"); + break; + } + memset(id, 0, sizeof(struct mtdids) + mtd_id_len); + id->num = num; + id->type = type; + id->size = size; + id->mtd_id = (char *)(id + 1); + strncpy(id->mtd_id, mtd_id, mtd_id_len - 1); + id->mtd_id[mtd_id_len - 1] = '\0'; + INIT_LIST_HEAD(&id->link); + + DEBUGF("+ id %s%d\t%16d bytes\t%s\n", + MTD_DEV_TYPE(id->type), id->num, + id->size, id->mtd_id); + + list_add_tail(&id->link, &mtdids); + ret = 0; + } + if (ret == 1) { + /* clean mtdids list and free allocated memory */ + list_for_each_safe(entry, n, &mtdids) { + id_tmp = list_entry(entry, struct mtdids, link); + list_del(entry); + free(id_tmp); + } + return 1; + } + + return 0; +} + +/** + * Parse and initialize global mtdids mapping and create global + * device/partition list. + * + * @return 0 on success, 1 otherwise + */ +int mtdparts_init(void) +{ + static int initialized = 0; + const char *ids, *parts; + const char *current_partition; + int ids_changed; + char tmp_ep[PARTITION_MAXLEN]; + + DEBUGF("\n---mtdparts_init---\n"); + if (!initialized) { + INIT_LIST_HEAD(&mtdids); + INIT_LIST_HEAD(&devices); + memset(last_ids, 0, MTDIDS_MAXLEN); + memset(last_parts, 0, MTDPARTS_MAXLEN); + memset(last_partition, 0, PARTITION_MAXLEN); + initialized = 1; + } + + /* get variables */ + ids = getenv("mtdids"); + parts = getenv("mtdparts"); + current_partition = getenv("partition"); + + /* save it for later parsing, cannot rely on current partition pointer + * as 'partition' variable may be updated during init */ + tmp_ep[0] = '\0'; + if (current_partition) + strncpy(tmp_ep, current_partition, PARTITION_MAXLEN); + + DEBUGF("last_ids : %s\n", last_ids); + DEBUGF("env_ids : %s\n", ids); + DEBUGF("last_parts: %s\n", last_parts); + DEBUGF("env_parts : %s\n\n", parts); + + DEBUGF("last_partition : %s\n", last_partition); + DEBUGF("env_partition : %s\n", current_partition); + + /* if mtdids varible is empty try to use defaults */ + if (!ids) { + if (mtdids_default) { + DEBUGF("mtdids variable not defined, using default\n"); + ids = mtdids_default; + setenv("mtdids", (char *)ids); + } else { + printf("mtdids not defined, no default present\n"); + return 1; + } + } + if (strlen(ids) > MTDIDS_MAXLEN - 1) { + printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN); + return 1; + } + + /* do no try to use defaults when mtdparts variable is not defined, + * just check the length */ + if (!parts) + printf("mtdparts variable not set, see 'help mtdparts'\n"); + + if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) { + printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN); + return 1; + } + + /* check if we have already parsed those mtdids */ + if ((last_ids[0] != '\0') && (strcmp(last_ids, ids) == 0)) { + ids_changed = 0; + } else { + ids_changed = 1; + + if (parse_mtdids(ids) != 0) { + device_delall(&devices); + return 1; + } + + /* ok it's good, save new ids */ + strncpy(last_ids, ids, MTDIDS_MAXLEN); + } + + /* parse partitions if either mtdparts or mtdids were updated */ + if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) { + if (parse_mtdparts(parts) != 0) + return 1; + + if (list_empty(&devices)) { + printf("mtdparts_init: no valid partitions\n"); + return 1; + } + + /* ok it's good, save new parts */ + strncpy(last_parts, parts, MTDPARTS_MAXLEN); + + /* reset first partition from first dev from the list as current */ + current_dev = list_entry(devices.next, struct mtd_device, link); + current_partnum = 0; + current_save(); + + DEBUGF("mtdparts_init: current_dev = %s%d, current_partnum = %d\n", + MTD_DEV_TYPE(current_dev->id->type), + current_dev->id->num, current_partnum); + } + + /* mtdparts variable was reset to NULL, delete all devices/partitions */ + if (!parts && (last_parts[0] != '\0')) + return devices_init(); + + /* do not process current partition if mtdparts variable is null */ + if (!parts) + return 0; + + /* is current partition set in environment? if so, use it */ + if ((tmp_ep[0] != '\0') && (strcmp(tmp_ep, last_partition) != 0)) { + struct part_info *p; + struct mtd_device *cdev; + u8 pnum; + + DEBUGF("--- getting current partition: %s\n", tmp_ep); + + if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) { + current_dev = cdev; + current_partnum = pnum; + current_save(); + } + } else if (getenv("partition") == NULL) { + DEBUGF("no partition variable set, setting...\n"); + current_save(); + } + + return 0; +} +#else /* #ifdef CONFIG_JFFS2_CMDLINE */ +/* + * 'Static' version of command line mtdparts_init() routine. Single partition on + * a single device configuration. + */ + +/** + * Parse and initialize global mtdids mapping and create global + * device/partition list. + * + * @return 0 on success, 1 otherwise + */ +int mtdparts_init(void) +{ + static int initialized = 0; + u32 size; + char *dev_name; + + DEBUGF("\n---mtdparts_init---\n"); + if (!initialized) { + initialized = 1; + current_dev = (struct mtd_device *) + malloc(sizeof(struct mtd_device) + + sizeof(struct part_info) + + sizeof(struct mtdids)); + if (!current_dev) { + printf("out of memory\n"); + return 1; + } + memset(current_dev, 0, sizeof(struct mtd_device) + + sizeof(struct part_info) + sizeof(struct mtdids)); + + struct mtdids *id = (struct mtdids *)(current_dev + 1); + struct part_info *part = (struct part_info *)(id + 1); + + /* id */ + id->mtd_id = "single part"; + +#if defined(CONFIG_JFFS2_DEV) + dev_name = CONFIG_JFFS2_DEV; +#else + dev_name = "nor0"; +#endif + + if ((id_parse(dev_name, NULL, &id->type, &id->num) != 0) || + (device_validate(id->type, id->num, &size) != 0)) { + printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num); + free(current_dev); + return 1; + } + id->size = size; + INIT_LIST_HEAD(&id->link); + + DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n", + id->type, id->num, id->size, id->mtd_id); + + /* partition */ + part->name = "static"; + part->auto_name = 0; + +#if defined(CONFIG_JFFS2_PART_SIZE) + part->size = CONFIG_JFFS2_PART_SIZE; +#else + part->size = SIZE_REMAINING; +#endif + +#if defined(CONFIG_JFFS2_PART_OFFSET) + part->offset = CONFIG_JFFS2_PART_OFFSET; +#else + part->offset = 0x00000000; +#endif + + part->dev = current_dev; + INIT_LIST_HEAD(&part->link); + + /* recalculate size if needed */ + if (part->size == SIZE_REMAINING) + part->size = id->size - part->offset; + + DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n", + part->name, part->size, part->offset); + + /* device */ + current_dev->id = id; + INIT_LIST_HEAD(¤t_dev->link); + current_dev->num_parts = 1; + INIT_LIST_HEAD(¤t_dev->parts); + list_add(&part->link, ¤t_dev->parts); + } + + return 0; +} +#endif /* #ifdef CONFIG_JFFS2_CMDLINE */ + +/** + * Return pointer to the partition of a requested number from a requested + * device. + * + * @param dev device that is to be searched for a partition + * @param part_num requested partition number + * @return pointer to the part_info, NULL otherwise + */ +static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num) +{ + struct list_head *entry; + struct part_info *part; + int num; + + if (!dev) + return NULL; + + DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n", + part_num, MTD_DEV_TYPE(dev->id->type), + dev->id->num, dev->id->mtd_id); + + if (part_num >= dev->num_parts) { + printf("invalid partition number %d for device %s%d (%s)\n", + part_num, MTD_DEV_TYPE(dev->id->type), + dev->id->num, dev->id->mtd_id); + return NULL; + } + + /* locate partition number, return it */ + num = 0; + list_for_each(entry, &dev->parts) { + part = list_entry(entry, struct part_info, link); + + if (part_num == num++) { + return part; + } + } + + return NULL; +} + +/***************************************************/ +/* U-boot commands */ +/***************************************************/ + +/** + * Routine implementing fsload u-boot command. This routine tries to load + * a requested file from jffs2/cramfs filesystem on a current partition. + * + * @param cmdtp command internal data + * @param flag command flag + * @param argc number of arguments supplied to the command + * @param argv arguments list + * @return 0 on success, 1 otherwise + */ +int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info* jffs2_part_info(int); - int jffs2_1pass_load(char *, struct part_info *,const char *); char *fsname; char *filename; int size; @@ -143,7 +1778,11 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) filename = argv[2]; } - if (0 != (part=jffs2_part_info(part_num))){ + /* make sure we are in sync with env variables */ + if (mtdparts_init() !=0) + return 1; + + if ((part = jffs2_part_info(current_dev, current_partnum))){ /* check partition type for cramfs */ fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2"); @@ -168,15 +1807,21 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return !(size > 0); } - puts ("Active partition not valid\n"); return 0; } -int -do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +/** + * Routine implementing u-boot ls command which lists content of a given + * directory on a current partition. + * + * @param cmdtp command internal data + * @param flag command flag + * @param argc number of arguments supplied to the command + * @param argv arguments list + * @return 0 on success, 1 otherwise + */ +int do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info* jffs2_part_info(int); - int jffs2_1pass_ls(struct part_info *,char *); char *filename = "/"; int ret; struct part_info *part; @@ -184,7 +1829,11 @@ do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (argc == 2) filename = argv[1]; - if (0 != (part=jffs2_part_info(part_num))){ + /* make sure we are in sync with env variables */ + if (mtdparts_init() !=0) + return 1; + + if ((part = jffs2_part_info(current_dev, current_partnum))){ /* check partition type for cramfs */ if (cramfs_check(part)) { @@ -196,20 +1845,30 @@ do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return (ret == 1); } - puts ("Active partition not valid\n"); return 0; } -int -do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +/** + * Routine implementing u-boot fsinfo command. This routine prints out + * miscellaneous filesystem informations/statistics. + * + * @param cmdtp command internal data + * @param flag command flag + * @param argc number of arguments supplied to the command + * @param argv arguments list + * @return 0 on success, 1 otherwise + */ +int do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info* jffs2_part_info(int); - int jffs2_1pass_info(struct part_info *); struct part_info *part; char *fsname; int ret; - if ((part=jffs2_part_info(part_num))){ + /* make sure we are in sync with env variables */ + if (mtdparts_init() !=0) + return 1; + + if ((part = jffs2_part_info(current_dev, current_partnum))){ /* check partition type for cramfs */ fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2"); @@ -224,48 +1883,159 @@ do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return (ret == 1); } - puts ("Active partition not valid\n"); return 0; } -#ifndef CFG_JFFS_SINGLE_PART -int -do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +/* command line only */ +#ifdef CONFIG_JFFS2_CMDLINE +/** + * Routine implementing u-boot chpart command. Sets new current partition based + * on the user supplied partition id. For partition id format see find_dev_and_part(). + * + * @param cmdtp command internal data + * @param flag command flag + * @param argc number of arguments supplied to the command + * @param argv arguments list + * @return 0 on success, 1 otherwise + */ +int do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - int tmp_part; - char str_part_num[3]; - struct part_info* jffs2_part_info(int); +/* command line only */ + struct mtd_device *dev; + struct part_info *part; + u8 pnum; - if (argc >= 2) { - tmp_part = simple_strtoul(argv[1], NULL, 16); - } else { - puts ("Need partition number in argument list\n"); - return 0; + if (mtdparts_init() !=0) + return 1; + if (argc < 2) { + printf("no partition id specified\n"); + return 1; } - if (jffs2_part_info(tmp_part)){ - printf("Partition changed to %d\n",tmp_part); - part_num=tmp_part; - sprintf(str_part_num, "%d", part_num); - setenv("partition", str_part_num); - return 0; - } + if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0) + return 1; + + current_dev = dev; + current_partnum = pnum; + current_save(); + + printf("partition changed to %s%d,%d\n", + MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum); - printf("Partition %d is not valid partiton\n",tmp_part); return 0; - } -U_BOOT_CMD( - chpart, 2, 0, do_jffs2_chpart, - "chpart\t- change active partition\n", - " - change active partition\n" -); -#endif /* CFG_JFFS_SINGLE_PART */ +/** + * Routine implementing u-boot mtdparts command. Initialize/update default global + * partition list and process user partition request (list, add, del). + * + * @param cmdtp command internal data + * @param flag command flag + * @param argc number of arguments supplied to the command + * @param argv arguments list + * @return 0 on success, 1 otherwise + */ +int do_jffs2_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc == 2) { + if (strcmp(argv[1], "default") == 0) { + setenv("mtdids", (char *)mtdids_default); + setenv("mtdparts", (char *)mtdparts_default); + setenv("partition", NULL); + + mtdparts_init(); + return 0; + } else if (strcmp(argv[1], "delall") == 0) { + /* this may be the first run, initialize lists if needed */ + mtdparts_init(); + + setenv("mtdparts", NULL); + + /* devices_init() calls current_save() */ + return devices_init(); + } + } + + /* make sure we are in sync with env variables */ + if (mtdparts_init() != 0) + return 1; + + if (argc == 1) { + list_partitions(); + return 0; + } + + /* mtdparts add [@] [ro] */ + if (((argc == 5) || (argc == 6)) && (strcmp(argv[1], "add") == 0)) { +#define PART_ADD_DESC_MAXLEN 64 + char tmpbuf[PART_ADD_DESC_MAXLEN]; + u8 type, num, len; + struct mtd_device *dev; + struct mtd_device *dev_tmp; + struct mtdids *id; + struct part_info *p; + + if (id_parse(argv[2], NULL, &type, &num) != 0) + return 1; + + if ((id = id_find(type, num)) == NULL) { + printf("no such device %s defined in mtdids variable\n", argv[2]); + return 1; + } + + len = strlen(id->mtd_id) + 1; /* 'mtd_id:' */ + len += strlen(argv[3]); /* size@offset */ + len += strlen(argv[4]) + 2; /* '(' name ')' */ + if (argv[5] && (strlen(argv[5]) == 2)) + len += 2; /* 'ro' */ + + if (len >= PART_ADD_DESC_MAXLEN) { + printf("too long partition description\n"); + return 1; + } + sprintf(tmpbuf, "%s:%s(%s)%s", + id->mtd_id, argv[3], argv[4], argv[5] ? argv[5] : ""); + DEBUGF("add tmpbuf: %s\n", tmpbuf); + + if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev)) + return 1; + + DEBUGF("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type), + dev->id->num, dev->id->mtd_id); + + if ((dev_tmp = device_find(dev->id->type, dev->id->num)) == NULL) { + device_add(dev); + } else { + /* merge new partition with existing ones*/ + p = list_entry(dev->parts.next, struct part_info, link); + if (part_add(dev_tmp, p) != 0) { + device_del(dev); + return 1; + } + } + + if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) { + printf("generated mtdparts too long, reseting to null\n"); + return 1; + } + + return 0; + } + + /* mtdparts del part-id */ + if ((argc == 3) && (strcmp(argv[1], "del") == 0)) { + DEBUGF("del: part-id = %s\n", argv[2]); + + return delete_partition(argv[2]); + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} +#endif /* #ifdef CONFIG_JFFS2_CMDLINE */ /***************************************************/ - U_BOOT_CMD( fsload, 3, 0, do_jffs2_fsload, "fsload\t- load binary file from a filesystem image\n", @@ -273,6 +2043,12 @@ U_BOOT_CMD( " - load binary file from flash bank\n" " with offset 'off'\n" ); +U_BOOT_CMD( + ls, 2, 1, do_jffs2_ls, + "ls\t- list files in a directory (default /)\n", + "[ directory ]\n" + " - list files in a directory.\n" +); U_BOOT_CMD( fsinfo, 1, 1, do_jffs2_fsinfo, @@ -280,11 +2056,50 @@ U_BOOT_CMD( " - print information about filesystems\n" ); +#ifdef CONFIG_JFFS2_CMDLINE U_BOOT_CMD( - ls, 2, 1, do_jffs2_ls, - "ls\t- list files in a directory (default /)\n", - "[ directory ]\n" - " - list files in a directory.\n" + chpart, 2, 0, do_jffs2_chpart, + "chpart\t- change active partition\n", + "part-id\n" + " - change active partition (e.g. part-id = nand0,1)\n" ); +U_BOOT_CMD( + mtdparts, 6, 0, do_jffs2_mtdparts, + "mtdparts- define flash/nand partitions\n", + "\n" + " - list partition table\n" + "mtdparts delall\n" + " - delete all partitions\n" + "mtdparts del part-id\n" + " - delete partition (e.g. part-id = nand0,1)\n" + "mtdparts add [@] [] [ro]\n" + " - add partition\n" + "mtdparts default\n" + " - reset partition table to defaults\n\n" + "-----\n\n" + "this command uses three environment variables:\n\n" + "'partition' - keeps current partition identifier\n\n" + "partition := \n" + " := ,part_num\n\n" + "'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n" + "mtdids=[,,...]\n\n" + " := =\n" + " := 'nand'|'nor'\n" + " := mtd device number, 0...\n" + " := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n" + "'mtdparts' - partition list\n\n" + "mtdparts=mtdparts=[;...]\n\n" + " := :[,...]\n" + " := unique device tag used by linux kernel to find mtd device (mtd->name)\n" + " := [@][][]\n" + " := standard linux memsize OR '-' to denote all remaining space\n" + " := partition start offset within the device\n" + " := '(' NAME ')'\n" + " := when set to 'ro' makes partition read-only (not used, passed to kernel)\n" +); +#endif /* #ifdef CONFIG_JFFS2_CMDLINE */ + +/***************************************************/ + #endif /* CFG_CMD_JFFS2 */ diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index 98ff56726..f02bf3c74 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -42,17 +42,22 @@ struct cramfs_super super; +/* CPU address space offset calculation macro, struct part_info offset is + * device address space offset, so we need to shift it by a device start address. */ +extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; +#define PART_OFFSET(x) (x->offset + flash_info[x->dev->id->num].start[0]) + static int cramfs_read_super (struct part_info *info) { unsigned long root_offset; /* Read the first block and get the superblock from it */ - memcpy (&super, (void *) info->offset, sizeof (super)); + memcpy (&super, (void *) PART_OFFSET(info), sizeof (super)); /* Do sanity checks on the superblock */ if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) { /* check at 512 byte offset */ - memcpy (&super, (void *) info->offset + 512, sizeof (super)); + memcpy (&super, (void *) PART_OFFSET(info) + 512, sizeof (super)); if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) { printf ("cramfs: wrong magic\n"); return -1; @@ -87,7 +92,7 @@ static int cramfs_read_super (struct part_info *info) return 0; } -static unsigned long cramfs_resolve (char *begin, unsigned long offset, +static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, unsigned long size, int raw, char *filename) { @@ -150,7 +155,7 @@ static unsigned long cramfs_resolve (char *begin, unsigned long offset, return 0; } -static int cramfs_uncompress (char *begin, unsigned long offset, +static int cramfs_uncompress (unsigned long begin, unsigned long offset, unsigned long loadoffset) { struct cramfs_inode *inode = (struct cramfs_inode *) (begin + offset); @@ -187,7 +192,7 @@ int cramfs_load (char *loadoffset, struct part_info *info, char *filename) if (cramfs_read_super (info)) return -1; - offset = cramfs_resolve (info->offset, + offset = cramfs_resolve (PART_OFFSET(info), CRAMFS_GET_OFFSET (&(super.root)) << 2, CRAMFS_24 (super.root.size), 0, strtok (filename, "/")); @@ -195,14 +200,14 @@ int cramfs_load (char *loadoffset, struct part_info *info, char *filename) if (offset <= 0) return offset; - return cramfs_uncompress (info->offset, offset, + return cramfs_uncompress (PART_OFFSET(info), offset, (unsigned long) loadoffset); } static int cramfs_list_inode (struct part_info *info, unsigned long offset) { struct cramfs_inode *inode = (struct cramfs_inode *) - (info->offset + offset); + (PART_OFFSET(info) + offset); char *name, str[20]; int namelen, nextoff; @@ -233,7 +238,7 @@ static int cramfs_list_inode (struct part_info *info, unsigned long offset) unsigned long size = CRAMFS_24 (inode->size); char *link = malloc (size); - if (link != NULL && cramfs_uncompress (info->offset, offset, + if (link != NULL && cramfs_uncompress (PART_OFFSET(info), offset, (unsigned long) link) == size) printf (" -> %*.*s\n", (int) size, (int) size, link); @@ -262,7 +267,7 @@ int cramfs_ls (struct part_info *info, char *filename) size = CRAMFS_24 (super.root.size); } else { /* Resolve the path */ - offset = cramfs_resolve (info->offset, + offset = cramfs_resolve (PART_OFFSET(info), CRAMFS_GET_OFFSET (&(super.root)) << 2, CRAMFS_24 (super.root.size), 1, strtok (filename, "/")); @@ -271,7 +276,7 @@ int cramfs_ls (struct part_info *info, char *filename) return offset; /* Resolving was successful. Examine the inode */ - inode = (struct cramfs_inode *) (info->offset + offset); + inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset); if (!S_ISDIR (CRAMFS_16 (inode->mode))) { /* It's not a directory - list it, and that's that */ return (cramfs_list_inode (info, offset) > 0); @@ -284,7 +289,7 @@ int cramfs_ls (struct part_info *info, char *filename) /* List the given directory */ while (inodeoffset < size) { - inode = (struct cramfs_inode *) (info->offset + offset + + inode = (struct cramfs_inode *) (PART_OFFSET(info) + offset + inodeoffset); nextoffset = cramfs_list_inode (info, offset + inodeoffset); @@ -324,14 +329,17 @@ int cramfs_info (struct part_info *info) int cramfs_check (struct part_info *info) { - struct cramfs_super *sb = (struct cramfs_super *) info->offset; + struct cramfs_super *sb; + if (info->dev->id->type != MTD_DEV_TYPE_NOR) + return 0; + + sb = (struct cramfs_super *) PART_OFFSET(info); if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC)) { /* check at 512 byte offset */ - sb = (struct cramfs_super *) (info->offset + 512); - if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC)) { + sb = (struct cramfs_super *) (PART_OFFSET(info) + 512); + if (sb->magic != CRAMFS_32 (CRAMFS_MAGIC)) return 0; - } } return 1; } diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index c3553cb4a..5180107f4 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -140,8 +140,10 @@ # define DEBUGF(fmt,args...) #endif -#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) +/* keeps pointer to currentlu processed partition */ +static struct part_info *current_part; +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) /* * Support for jffs2 on top of NAND-flash * @@ -167,10 +169,10 @@ int read_jffs2_nand(size_t start, size_t len, static u8* nand_cache = NULL; static u32 nand_cache_off = (u32)-1; -static int nanddev = 0; /* nand device of current partition */ static int read_nand_cached(u32 off, u32 size, u_char *buf) { + struct mtdids *id = current_part->dev->id; u32 bytes_read = 0; size_t retlen; int cpy_bytes; @@ -190,10 +192,10 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) } } if (read_jffs2_nand(nand_cache_off, NAND_CACHE_SIZE, - &retlen, nand_cache, nanddev) < 0 || - retlen != NAND_CACHE_SIZE) { + &retlen, nand_cache, id->num) < 0 || + retlen != NAND_CACHE_SIZE) { printf("read_nand_cached: error reading nand off %#x size %d bytes\n", - nand_cache_off, NAND_CACHE_SIZE); + nand_cache_off, NAND_CACHE_SIZE); return -1; } } @@ -208,12 +210,12 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) return bytes_read; } -static void *get_fl_mem(u32 off, u32 size, void *ext_buf) +static void *get_fl_mem_nand(u32 off, u32 size, void *ext_buf) { u_char *buf = ext_buf ? (u_char*)ext_buf : (u_char*)malloc(size); if (NULL == buf) { - printf("get_fl_mem: can't alloc %d bytes\n", size); + printf("get_fl_mem_nand: can't alloc %d bytes\n", size); return NULL; } if (read_nand_cached(off, size, buf) < 0) { @@ -225,15 +227,15 @@ static void *get_fl_mem(u32 off, u32 size, void *ext_buf) return buf; } -static void *get_node_mem(u32 off) +static void *get_node_mem_nand(u32 off) { struct jffs2_unknown_node node; void *ret = NULL; - if (NULL == get_fl_mem(off, sizeof(node), &node)) + if (NULL == get_fl_mem_nand(off, sizeof(node), &node)) return NULL; - if (!(ret = get_fl_mem(off, node.magic == + if (!(ret = get_fl_mem_nand(off, node.magic == JFFS2_MAGIC_BITMASK ? node.totlen : sizeof(node), NULL))) { printf("off = %#x magic %#x type %#x node.totlen = %d\n", @@ -242,30 +244,89 @@ static void *get_node_mem(u32 off) return ret; } -static void put_fl_mem(void *buf) +static void put_fl_mem_nand(void *buf) { free(buf); } +#endif /* #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */ -#else /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */ +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) +/* + * Support for jffs2 on top of NOR-flash + * + * NOR flash memory is mapped in processor's address space, + * just return address. + */ +static inline void *get_fl_mem_nor(u32 off) +{ + u32 addr = off; + struct mtdids *id = current_part->dev->id; + + extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + flash_info_t *flash = &flash_info[id->num]; + + addr += flash->start[0]; + return (void*)addr; +} + +static inline void *get_node_mem_nor(u32 off) +{ + return (void*)get_fl_mem_nor(off); +} +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */ + + +/* + * Generic jffs2 raw memory and node read routines. + * + */ static inline void *get_fl_mem(u32 off, u32 size, void *ext_buf) { + struct mtdids *id = current_part->dev->id; + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + if (id->type == MTD_DEV_TYPE_NOR) + return get_fl_mem_nor(off); +#endif + +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) + if (id->type == MTD_DEV_TYPE_NAND) + return get_fl_mem_nand(off, size, ext_buf); +#endif + + printf("get_fl_mem: unknown device type, using raw offset!\n"); return (void*)off; } static inline void *get_node_mem(u32 off) { + struct mtdids *id = current_part->dev->id; + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + if (id->type == MTD_DEV_TYPE_NOR) + return get_node_mem_nor(off); +#endif + +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) + if (id->type == MTD_DEV_TYPE_NAND) + return get_node_mem_nand(off); +#endif + + printf("get_node_mem: unknown device type, using raw offset!\n"); return (void*)off; } static inline void put_fl_mem(void *buf) { +#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) + struct mtdids *id = current_part->dev->id; + + if (id->type == MTD_DEV_TYPE_NAND) + return put_fl_mem_nand(buf); +#endif } -#endif /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */ - - /* Compression names */ static char *compr_names[] = { "NONE", @@ -457,8 +518,8 @@ static int compare_dirents(struct b_node *new, struct b_node *old) static u32 jffs2_scan_empty(u32 start_offset, struct part_info *part) { - char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode); - char *offset = part->offset + start_offset; + char *max = (char *)(part->offset + part->size - sizeof(struct jffs2_raw_inode)); + char *offset = (char *)(part->offset + start_offset); u32 off; while (offset < max && @@ -468,11 +529,11 @@ jffs2_scan_empty(u32 start_offset, struct part_info *part) if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break; } - return offset - part->offset; + return (u32)offset - part->offset; } -static u32 -jffs_init_1pass_list(struct part_info *part) +void +jffs2_free_cache(struct part_info *part) { struct b_lists *pL; @@ -482,6 +543,15 @@ jffs_init_1pass_list(struct part_info *part) free_nodes(&pL->dir); free(pL); } +} + +static u32 +jffs_init_1pass_list(struct part_info *part) +{ + struct b_lists *pL; + + jffs2_free_cache(part); + if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) { pL = (struct b_lists *)part->jffs2_priv; @@ -979,25 +1049,13 @@ jffs2_1pass_rescan_needed(struct part_info *part) DEBUGF ("rescan: First time in use\n"); return 1; } + /* if we have no list, we need to rescan */ if (pL->frag.listCount == 0) { DEBUGF ("rescan: fraglist zero\n"); return 1; } - /* or if we are scanning a new partition */ - if (pL->partOffset != part->offset) { - DEBUGF ("rescan: different partition\n"); - return 1; - } - -#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) - if (nanddev != (int)part->usr_priv - 1) { - DEBUGF ("rescan: nand device changed\n"); - return -1; - } -#endif /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */ - /* but suppose someone reflashed a partition at the same offset... */ b = pL->dir.listHead; while (b) { @@ -1087,10 +1145,6 @@ jffs2_1pass_build_lists(struct part_info * part) u32 counterF = 0; u32 counterN = 0; -#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) - nanddev = (int)part->usr_priv - 1; -#endif /* defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) */ - /* turn off the lcd. Refreshing the lcd adds 50% overhead to the */ /* jffs2 list building enterprise nope. in newer versions the overhead is */ /* only about 5 %. not enough to inconvenience people for. */ @@ -1099,7 +1153,6 @@ jffs2_1pass_build_lists(struct part_info * part) /* if we are building a list we need to refresh the cache. */ jffs_init_1pass_list(part); pL = (struct b_lists *)part->jffs2_priv; - pL->partOffset = part->offset; offset = 0; puts ("Scanning JFFS2 FS: "); @@ -1217,6 +1270,9 @@ jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL) static struct b_lists * jffs2_get_list(struct part_info * part, const char *who) { + /* copy requested part_info struct pointer to global location */ + current_part = part; + if (jffs2_1pass_rescan_needed(part)) { if (!jffs2_1pass_build_lists(part)) { printf("%s: Failed to scan JFFSv2 file structure\n", who); diff --git a/fs/jffs2/jffs2_private.h b/fs/jffs2/jffs2_private.h index d53e5764b..65ca6eb98 100644 --- a/fs/jffs2/jffs2_private.h +++ b/fs/jffs2/jffs2_private.h @@ -22,7 +22,6 @@ struct b_list { }; struct b_lists { - char *partOffset; struct b_list dir; struct b_list frag; diff --git a/include/configs/ADNPESC1.h b/include/configs/ADNPESC1.h index 2d212c91c..2efca1056 100644 --- a/include/configs/ADNPESC1.h +++ b/include/configs/ADNPESC1.h @@ -674,5 +674,21 @@ #undef CFG_MEMTEST_END #endif +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/Alaska8220.h b/include/configs/Alaska8220.h index dc01f0cb1..9a3acfecd 100644 --- a/include/configs/Alaska8220.h +++ b/include/configs/Alaska8220.h @@ -229,17 +229,6 @@ #undef CFG_ENV_IS_IN_FLASH #endif -#ifndef CFG_JFFS2_FIRST_SECTOR -#define CFG_JFFS2_FIRST_SECTOR 0 -#endif -#ifndef CFG_JFFS2_FIRST_BANK -#define CFG_JFFS2_FIRST_BANK 0 -#endif -#ifndef CFG_JFFS2_NUM_BANKS -#define CFG_JFFS2_NUM_BANKS 1 -#endif -#define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1) - /* * Memory map */ @@ -314,4 +303,23 @@ #define CFG_HID0_INIT HID0_ICE | HID0_ICFI #define CFG_HID0_FINAL HID0_ICE +/* + * JFFS2 partitions + */ + +/* No command line, one static partition */ +/* +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0x00400000 +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 +*/ + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=alaska-0" +#define MTDPARTS_DEFAULT "mtdparts=alaska-0:4m(user)" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/BAB7xx.h b/include/configs/BAB7xx.h index 5dd7a7e9f..81c8d59e8 100644 --- a/include/configs/BAB7xx.h +++ b/include/configs/BAB7xx.h @@ -28,8 +28,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - #undef DEBUG #define GTREGREAD(x) 0xffffffff /* needed for debug */ @@ -201,8 +199,25 @@ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support + * + * Note: fake mtd_id used, no linux mtd map file + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=bab7xx-0" +#define MTDPARTS_DEFAULT "mtdparts=bab7xx-0:-(jffs2)" +*/ #define CFG_MONITOR_BASE CFG_FLASH_BASE #define CFG_MONITOR_LEN 0x40000 /* Reserve 256 kB for Monitor */ diff --git a/include/configs/CATcenter.h b/include/configs/CATcenter.h index 61022e8d5..776fce5a9 100644 --- a/include/configs/CATcenter.h +++ b/include/configs/CATcenter.h @@ -377,11 +377,6 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#if 0 /* test-only */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ -#endif - /*----------------------------------------------------------------------- * Environment Variable setup */ @@ -767,9 +762,26 @@ #endif /* CONFIG_NO_SERIAL_EEPROM */ #define CONFIG_JFFS2_NAND 1 /* jffs2 on nand support */ -#define CONFIG_JFFS2_NAND_DEV 0 /* nand device jffs2 lives on */ -#define CONFIG_JFFS2_NAND_OFF 0 /* start of jffs2 partition */ -#define CONFIG_JFFS2_NAND_SIZE 2*1024*1024 /* size of jffs2 partition */ #define NAND_CACHE_PAGES 16 /* size of nand cache in 512 bytes pages */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nand" +#define CONFIG_JFFS2_PART_SIZE 0x00200000 +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support + * + * Note: fake mtd_id used, no linux mtd map file + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nand0=catcenter" +#define MTDPARTS_DEFAULT "mtdparts=catcenter:2m(nand)" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h index 4bb47c324..d1498eed3 100644 --- a/include/configs/CPCI4052.h +++ b/include/configs/CPCI4052.h @@ -242,8 +242,28 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ + +/* + * JFFS2 partitions + */ + +/* No command line, one static partition, use whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=cpci4052-0" +#define MTDPARTS_DEFAULT "mtdparts=cpci4052-0:-(jffs2)" +*/ #if 0 /* Use NVRAM for environment variables */ /*----------------------------------------------------------------------- diff --git a/include/configs/CPCI405AB.h b/include/configs/CPCI405AB.h index dee26f871..29bd3da98 100644 --- a/include/configs/CPCI405AB.h +++ b/include/configs/CPCI405AB.h @@ -225,8 +225,26 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ +/* + * JFFS2 partitions + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=cpci405ab-0" +#define MTDPARTS_DEFAULT "mtdparts=cpci405ab-0:-(jffs2)" +*/ /*----------------------------------------------------------------------- * I2C EEPROM (CAT24WC32) for environment diff --git a/include/configs/CPCI405DT.h b/include/configs/CPCI405DT.h index 5c4259df3..6673073c0 100644 --- a/include/configs/CPCI405DT.h +++ b/include/configs/CPCI405DT.h @@ -247,8 +247,26 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ +/* + * JFFS2 partitions + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=cpci405dt-0" +#define MTDPARTS_DEFAULT "mtdparts=cpci405dt-0:-(jffs2)" +*/ #if 0 /* Use NVRAM for environment variables */ /*----------------------------------------------------------------------- diff --git a/include/configs/CPCI750.h b/include/configs/CPCI750.h index fab263b4b..8bfd0ee82 100644 --- a/include/configs/CPCI750.h +++ b/include/configs/CPCI750.h @@ -38,8 +38,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - /* This define must be before the core.h include */ #define CONFIG_CPCI750 1 /* this is an CPCI750 board */ diff --git a/include/configs/DB64360.h b/include/configs/DB64360.h index d6ce8a873..e2b4b1da6 100644 --- a/include/configs/DB64360.h +++ b/include/configs/DB64360.h @@ -88,8 +88,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - /* This define must be before the core.h include */ #define CONFIG_DB64360 1 /* this is an DB64360 board */ @@ -219,10 +217,27 @@ ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000;\0" #define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ CONFIG_BOOTP_BOOTFILESIZE) +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor1" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 1 -#define CFG_JFFS2_NUM_BANKS 1 +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor1=db64360-1" +#define MTDPARTS_DEFAULT "mtdparts=db64360-1:-(jffs2)" +*/ #define CONFIG_COMMANDS (CONFIG_CMD_DFL \ | CFG_CMD_ASKENV \ diff --git a/include/configs/DB64460.h b/include/configs/DB64460.h index fb0248102..5f541bb9a 100644 --- a/include/configs/DB64460.h +++ b/include/configs/DB64460.h @@ -28,8 +28,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - /* This define must be before the core.h include */ #define CONFIG_DB64460 1 /* this is an DB64460 board */ @@ -157,10 +155,27 @@ ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000;\0" #define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ CONFIG_BOOTP_BOOTFILESIZE) +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor1" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 1 -#define CFG_JFFS2_NUM_BANKS 1 +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor1=db64460-1" +#define MTDPARTS_DEFAULT "mtdparts=db64460-1:-(jffs2)" +*/ #define CONFIG_COMMANDS (CONFIG_CMD_DFL \ | CFG_CMD_ASKENV \ diff --git a/include/configs/DK1C20.h b/include/configs/DK1C20.h index 14a09b6dd..b58846d83 100644 --- a/include/configs/DK1C20.h +++ b/include/configs/DK1C20.h @@ -536,5 +536,21 @@ #undef CFG_MEMTEST_END #endif +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/DK1S10.h b/include/configs/DK1S10.h index e79eb490f..3e3803cd2 100644 --- a/include/configs/DK1S10.h +++ b/include/configs/DK1S10.h @@ -545,5 +545,21 @@ #undef CFG_MEMTEST_END #endif +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/ELPPC.h b/include/configs/ELPPC.h index 7176905a3..e51d05804 100644 --- a/include/configs/ELPPC.h +++ b/include/configs/ELPPC.h @@ -28,8 +28,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - #undef DEBUG #define GTREGREAD(x) 0xffffffff /* needed for debug */ @@ -181,8 +179,23 @@ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 2 /* ! second bank contains U-Boot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=elppc-0,nor1=elppc-1" +#define MTDPARTS_DEFAULT "mtdparts=elppc-0:-(jffs2),elppc-1:-(user)" +*/ #define CFG_MONITOR_BASE CFG_FLASH_BASE #define CFG_MONITOR_LEN 0x40000 /* Reserve 256 kB for Monitor */ diff --git a/include/configs/EVB64260.h b/include/configs/EVB64260.h index 9baf252f6..78e571688 100644 --- a/include/configs/EVB64260.h +++ b/include/configs/EVB64260.h @@ -28,8 +28,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - #ifndef __ASSEMBLY__ #include #endif diff --git a/include/configs/LANTEC.h b/include/configs/LANTEC.h index 91011be36..933a42c5c 100644 --- a/include/configs/LANTEC.h +++ b/include/configs/LANTEC.h @@ -356,4 +356,21 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/MHPC.h b/include/configs/MHPC.h index f942e9554..cd21c2dbb 100644 --- a/include/configs/MHPC.h +++ b/include/configs/MHPC.h @@ -184,8 +184,23 @@ #define CFG_MONITOR_BASE CFG_FLASH_BASE #define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* one flash only */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=mhpc-0" +#define MTDPARTS_DEFAULT "mtdparts=mhpc-0:-(jffs2)" +*/ /* * For booting Linux, the board info and command line data diff --git a/include/configs/MIP405.h b/include/configs/MIP405.h index 41a3d394a..0af9c68dc 100644 --- a/include/configs/MIP405.h +++ b/include/configs/MIP405.h @@ -236,8 +236,23 @@ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=mip405-0" +#define MTDPARTS_DEFAULT "mtdparts=mip405-0:-(jffs2)" +*/ /*----------------------------------------------------------------------- * Cache Configuration diff --git a/include/configs/ML2.h b/include/configs/ML2.h index c6cc69bc2..6e54d71e5 100644 --- a/include/configs/ML2.h +++ b/include/configs/ML2.h @@ -241,9 +241,22 @@ #define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ #endif -/* JFFS2 stuff */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00080000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=ml2-0" +#define MTDPARTS_DEFAULT "mtdparts=ml2-0:-@512k(jffs2)" +*/ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_NUM_BANKS 1 -#define CFG_JFFS2_FIRST_SECTOR 1 #endif /* __CONFIG_H */ diff --git a/include/configs/MPC8260ADS.h b/include/configs/MPC8260ADS.h index bba476a6a..9188ae5bb 100644 --- a/include/configs/MPC8260ADS.h +++ b/include/configs/MPC8260ADS.h @@ -278,10 +278,14 @@ #define CFG_FLASH_UNLOCK_TOUT 10000 /* Timeout for Flash Clear Lock Bits (in ms) */ #define CFG_FLASH_PROTECTION /* "Real" (hardware) sectors protection */ -#define CFG_JFFS2_FIRST_SECTOR 1 -#define CFG_JFFS2_LAST_SECTOR 27 +/* + * JFFS2 partitions + * + * Note: fake mtd_id used, no linux mtd map file + */ +#define MTDIDS_DEFAULT "nor0=mpc8260ads-0" +#define MTDPARTS_DEFAULT "mtdparts=mpc8260ads-0:-@1m(jffs2)" #define CFG_JFFS2_SORT_FRAGMENTS -#define CFG_JFFS_CUSTOM_PART /* this is stuff came out of the Motorola docs */ #ifndef CFG_LOWBOOT diff --git a/include/configs/MPC8266ADS.h b/include/configs/MPC8266ADS.h index d8e91a530..0a4b04df4 100644 --- a/include/configs/MPC8266ADS.h +++ b/include/configs/MPC8266ADS.h @@ -573,5 +573,21 @@ #define CFG_PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */ #define CFG_POCMR2_MASK_ATTRIB (POCMR_MASK_64MB | POCMR_ENABLE | POCMR_PCI_IO) +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/NC650.h b/include/configs/NC650.h index 3acdd77fe..d24d05f25 100644 --- a/include/configs/NC650.h +++ b/include/configs/NC650.h @@ -400,9 +400,27 @@ #define BOOTFLAG_WARM 0x02 /* Software reboot */ #define CONFIG_JFFS2_NAND 1 /* jffs2 on nand support */ -#define CONFIG_JFFS2_NAND_DEV 0 /* nand device jffs2 lives on */ -#define CONFIG_JFFS2_NAND_OFF 0 /* start of jffs2 partition */ -#define CONFIG_JFFS2_NAND_SIZE 4*1024*1024 /* size of jffs2 partition */ #define NAND_CACHE_PAGES 16 /* size of nand cache in 512 bytes pages */ +/* + * JFFS2 partitions + */ + +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nand0" +#define CONFIG_JFFS2_PART_SIZE 0x00400000 +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=nc650-0,nand0=nc650-nand" + +#define MTDPARTS_DEFAULT "mtdparts=nc650-0:1m(kernel1),1m(kernel2)," \ + "2560k(cramfs1),2560k(cramfs2)," \ + "256k(u-boot),256k(env);" \ + "nc650-nand:4m(nand1),28m(nand2)" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/NETTA.h b/include/configs/NETTA.h index 1d12eb4c6..3573b3711 100644 --- a/include/configs/NETTA.h +++ b/include/configs/NETTA.h @@ -685,11 +685,26 @@ ((unsigned char)(*(volatile unsigned char *)(unsigned long)(adr))) #define CONFIG_JFFS2_NAND 1 /* jffs2 on nand support */ -#define CONFIG_JFFS2_NAND_DEV 0 /* nand device jffs2 lives on */ -#define CONFIG_JFFS2_NAND_OFF (2 * 1024 * 1024) /* start of jffs2 partition */ -#define CONFIG_JFFS2_NAND_SIZE (1*1024*1024) /* size of jffs2 partition */ #define NAND_CACHE_PAGES 16 /* size of nand cache in 512 bytes pages */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nand0" +#define CONFIG_JFFS2_PART_SIZE 0x00100000 +#define CONFIG_JFFS2_PART_OFFSET 0x00200000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nand0=netta-nand" +#define MTDPARTS_DEFAULT "mtdparts=netta-nand:1m@2m(jffs2)" +*/ + /*****************************************************************************/ #define CFG_DIRECT_FLASH_TFTP diff --git a/include/configs/PMC405.h b/include/configs/PMC405.h index d8d963262..11d6fa767 100644 --- a/include/configs/PMC405.h +++ b/include/configs/PMC405.h @@ -193,8 +193,23 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains u-boot */ +/* + * JFFS2 partitions - second bank contains u-boot + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=pmc405-0" +#define MTDPARTS_DEFAULT "mtdparts=pmc405-0:-(jffs2)" +*/ /*----------------------------------------------------------------------- * Environment Variable setup diff --git a/include/configs/PPChameleonEVB.h b/include/configs/PPChameleonEVB.h index ca0bd12f0..2d89f3ffa 100644 --- a/include/configs/PPChameleonEVB.h +++ b/include/configs/PPChameleonEVB.h @@ -336,9 +336,19 @@ * Please note that CFG_SDRAM_BASE _must_ start at 0 */ #define CFG_SDRAM_BASE 0x00000000 + +/* Reserve 256 kB for Monitor */ #define CFG_FLASH_BASE 0xFFFC0000 #define CFG_MONITOR_BASE CFG_FLASH_BASE -#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_LEN (256 * 1024) + +/* Reserve 320 kB for Monitor */ +/* +#define CFG_FLASH_BASE 0xFFFB0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (320 * 1024) +*/ + #define CFG_MALLOC_LEN (256 * 1024) /* Reserve 256 kB for malloc() */ /* @@ -369,11 +379,6 @@ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ -#if 0 /* test-only */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ -#endif - /*----------------------------------------------------------------------- * Environment Variable setup */ @@ -770,9 +775,36 @@ #endif /* CONFIG_NO_SERIAL_EEPROM */ #define CONFIG_JFFS2_NAND 1 /* jffs2 on nand support */ -#define CONFIG_JFFS2_NAND_DEV 0 /* nand device jffs2 lives on */ -#define CONFIG_JFFS2_NAND_OFF 0 /* start of jffs2 partition */ -#define CONFIG_JFFS2_NAND_SIZE 4*1024*1024 /* size of jffs2 partition */ #define NAND_CACHE_PAGES 16 /* size of nand cache in 512 bytes pages */ +/* + * JFFS2 partitions + */ + +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nand0" +#define CONFIG_JFFS2_PART_SIZE 0x00400000 +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=PPChameleon-0,nand0=ppchameleonevb-nand" +*/ + +/* 256 kB U-boot image */ +/* +#define MTDPARTS_DEFAULT "mtdparts=PPChameleon-0:1m(kernel1),1m(kernel2)," \ + "1792k(user),256k(u-boot);" \ + "ppchameleonevb-nand:-(nand)" +*/ + +/* 320 kB U-boot image */ +/* +#define MTDPARTS_DEFAULT "mtdparts=PPChameleon-0:1m(kernel1),1m(kernel2)," \ + "1728k(user),320k(u-boot);" \ + "ppchameleonevb-nand:-(nand)" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/R360MPI.h b/include/configs/R360MPI.h index c456fbf18..d7b093b3c 100644 --- a/include/configs/R360MPI.h +++ b/include/configs/R360MPI.h @@ -152,10 +152,22 @@ #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } -/* JFFS2 stuff */ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_NUM_BANKS 1 -#define CFG_JFFS2_FIRST_SECTOR 24 +/* + * JFFS2 partitions + */ +/* No command line, one static partition + * use all the space starting at offset 3MB*/ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00300000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=r360-0" +#define MTDPARTS_DEFAULT "mtdparts=r360-0:-@3m(user)" +*/ /* * Low Level Configuration Settings diff --git a/include/configs/RBC823.h b/include/configs/RBC823.h index b0e491067..4d47d3ee5 100644 --- a/include/configs/RBC823.h +++ b/include/configs/RBC823.h @@ -417,4 +417,22 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/Rattler.h b/include/configs/Rattler.h index a55297096..a170f290e 100644 --- a/include/configs/Rattler.h +++ b/include/configs/Rattler.h @@ -186,10 +186,26 @@ #define CFG_DIRECT_FLASH_TFTP #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) -#define CFG_JFFS2_FIRST_BANK 0 #define CFG_JFFS2_NUM_BANKS CFG_MAX_FLASH_BANKS -#define CFG_JFFS2_FIRST_SECTOR 16 #define CFG_JFFS2_SORT_FRAGMENTS + +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00100000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=rattler-0" +#define MTDPARTS_DEFAULT "mtdparts=rattler-0:-@1m(jffs2)" +*/ #endif /* CFG_CMD_JFFS2 */ #define CFG_MONITOR_BASE TEXT_BASE diff --git a/include/configs/SXNI855T.h b/include/configs/SXNI855T.h index 195c036bb..9ce83b48b 100644 --- a/include/configs/SXNI855T.h +++ b/include/configs/SXNI855T.h @@ -154,14 +154,32 @@ /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include -#define CFG_JFFS_CUSTOM_PART #define CFG_JFFS2_SORT_FRAGMENTS -/* JFFS2 location when using NOR flash */ -#define CFG_JFFS2_BASE (CFG_FLASH_BASE + 0x80000) -#define CFG_JFFS2_SIZE (0x780000) -/* JFFS2 location (in RAM) when using NAND flash */ -#define CFG_JFFS2_RAMBASE 0x400000 -#define CFG_JFFS2_RAMSIZE 0x200000 /* NAND boot partition is 2MiB */ + +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE + +/* +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0x00780000 +#define CONFIG_JFFS2_PART_OFFSET 0x00080000 +*/ + +#define CONFIG_JFFS2_DEV "nand0" +#define CONFIG_JFFS2_PART_SIZE 0x00200000 +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=sixnet-0,nand0=sixnet-nand" +#define MTDPARTS_DEFAULT "mtdparts=sixnet-0:7680k@512k();sixnet-nand:2m(jffs2-nand)" +*/ /* NAND flash support */ #define CONFIG_MTD_NAND_ECC_JFFS2 diff --git a/include/configs/ZUMA.h b/include/configs/ZUMA.h index 578f152fd..f163d003b 100644 --- a/include/configs/ZUMA.h +++ b/include/configs/ZUMA.h @@ -28,8 +28,6 @@ #ifndef __CONFIG_H #define __CONFIG_H -#include - #define CFG_GT_6426x GT_64260 /* with a 64260 system controller */ #define CONFIG_ETHER_PORT_MII /* use two MII ports */ #define CONFIG_INTEL_LXT97X /* Intel LXT97X phy */ @@ -115,9 +113,23 @@ CFG_CMD_MII | \ CFG_CMD_DATE) -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 1 -#define CFG_JFFS2_NUM_BANKS 2 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor1=zuma-1,nor2=zuma-2" +#define MTDPARTS_DEFAULT "mtdparts=zuma-1:-(jffs2),zuma-2:-(user)" +*/ /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include diff --git a/include/configs/debris.h b/include/configs/debris.h index a9a245887..b483f407d 100644 --- a/include/configs/debris.h +++ b/include/configs/debris.h @@ -217,8 +217,27 @@ #define CFG_FLASH_RANGE_SIZE 0x01000000 #define FLASH_BASE0_PRELIM 0x7C000000 /* debris flash */ -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ + +/* Use first bank for JFFS2, second bank contains U-Boot. + * + * Note: fake mtd_id's used, no linux mtd map file. + */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=debris-0" +#define MTDPARTS_DEFAULT "mtdparts=debris-0:-(jffs2)" +*/ #define CFG_ENV_IS_IN_NVRAM 1 #define CONFIG_ENV_OVERWRITE 1 diff --git a/include/configs/ep7312.h b/include/configs/ep7312.h index c6a028fab..bdda6292e 100644 --- a/include/configs/ep7312.h +++ b/include/configs/ep7312.h @@ -142,9 +142,22 @@ #define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x20000) /* Addr of Environment Sector */ #define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_FIRST_SECTOR 2 -#define CFG_JFFS2_NUM_BANKS 1 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=ep7312-0" +#define MTDPARTS_DEFAULT "mtdparts=ep7312-0:-(jffs2)" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/ep8260.h b/include/configs/ep8260.h index 98e1716bf..8b0afd5a6 100644 --- a/include/configs/ep8260.h +++ b/include/configs/ep8260.h @@ -744,4 +744,22 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/hymod.h b/include/configs/hymod.h index 0d62b9efd..aadb59f1f 100644 --- a/include/configs/hymod.h +++ b/include/configs/hymod.h @@ -712,4 +712,21 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH*/ #define BOOTFLAG_WARM 0x02 /* Software reboot */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "" +#define MTDPARTS_DEFAULT "" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/impa7.h b/include/configs/impa7.h index c187c54d6..8b841ff54 100644 --- a/include/configs/impa7.h +++ b/include/configs/impa7.h @@ -144,9 +144,21 @@ #define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x1C000) /* Addr of Environment Sector */ #define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_FIRST_SECTOR 8 -#define CFG_JFFS2_NUM_BANKS 2 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00020000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=impA7 NOR Flash Bank #0,nor1=impA7 NOR Flash Bank #1" +#define MTDPARTS_DEFAULT "mtdparts=impA7 NOR Flash Bank #0:-(FileSystem1);impA7 NOR Flash Bank #1:-(FileSystem2)" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/incaip.h b/include/configs/incaip.h index 7db3744cf..0f548a52a 100644 --- a/include/configs/incaip.h +++ b/include/configs/incaip.h @@ -148,8 +148,26 @@ #define CONFIG_NET_MULTI #define CONFIG_INCA_IP_SWITCH_AMDIX -#define CFG_JFFS2_FIRST_BANK 1 -#define CFG_JFFS2_NUM_BANKS 1 +/* + * JFFS2 partitions + */ +/* No command line, one static partition, use all space on the device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor1" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=INCA-IP Bank 0" +#define MTDPARTS_DEFAULT "mtdparts=INCA-IP Bank 0:192k(uboot)," \ + "64k(env)," \ + "768k(linux)," \ + "1m@3m(rootfs)," \ + "768k(linux2)," \ + "3m@5m(rootfs2)" +*/ /*----------------------------------------------------------------------- * Cache Configuration diff --git a/include/configs/innokom.h b/include/configs/innokom.h index fce72e112..3cb9ebc45 100644 --- a/include/configs/innokom.h +++ b/include/configs/innokom.h @@ -164,14 +164,42 @@ #define CFG_FLASH_BASE PHYS_FLASH_1 - /* - * JFFS2 Partitions + * JFFS2 partitions + * */ -#define CFG_JFFS_CUSTOM_PART 1 /* see board/innokom/flash.c */ -#define CONFIG_MTD_INNOKOM_16MB 1 /* development flash */ -#undef CONFIG_MTD_INNOKOM_64MB /* production flash */ +/* development flash */ +#define CONFIG_MTD_INNOKOM_16MB 1 +#undef CONFIG_MTD_INNOKOM_64MB +/* production flash */ +/* +#define CONFIG_MTD_INNOKOM_64MB 1 +#undef CONFIG_MTD_INNOKOM_16MB +*/ + +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=innokom-0" +*/ + +/* development flash */ +/* +#define MTDPARTS_DEFAULT "mtdparts=innokom-0:256k(uboot),768k(kernel),8m(user),7m(data)" +*/ + +/* production flash */ +/* +#define MTDPARTS_DEFAULT "mtdparts=innokom-0:256k(uboot),768k(kernel),16256k(user1),16256k(user2),32m(data)" +*/ /* * GPIO settings diff --git a/include/configs/modnet50.h b/include/configs/modnet50.h index 067c84623..20287674f 100644 --- a/include/configs/modnet50.h +++ b/include/configs/modnet50.h @@ -165,9 +165,22 @@ #define CFG_ENV_SECT_SIZE 0x10000 /* Total Size of Environment Sector */ #define CFG_ENV_SIZE 0x4000 /* max size for environment */ -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_FIRST_SECTOR 8 -#define CFG_JFFS2_NUM_BANKS 2 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00080000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=modnet50-0" +#define MTDPARTS_DEFAULT "mtdparts=modnet50-0:-@512k(jffs2)" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/mx1fs2.h b/include/configs/mx1fs2.h index 7b4dc92c6..9816be8dc 100644 --- a/include/configs/mx1fs2.h +++ b/include/configs/mx1fs2.h @@ -87,7 +87,6 @@ #define CONFIG_INITRD_TAG 1 /* send initrd params */ #undef CONFIG_VFD /* do not send framebuffer setup */ -#define CFG_JFFS_CUSTOM_PART /* * Malloc pool need to host env + 128 Kb reserve for other allocations. */ @@ -136,10 +135,6 @@ #define MX1FS2_FLASH_INTERLEAVE 2 /* ... made of 2 chips */ #define MX1FS2_FLASH_BANK_SIZE 0x02000000 /* size of one flash bank*/ #define MX1FS2_FLASH_SECT_SIZE 0x00020000 /* size of erase sector */ -#define MX1FS2_JFFS2_PART0_START 0x10200000 -#define MX1FS2_JFFS2_PART0_SIZE 0x00500000 -#define MX1FS2_JFFS2_PART1_START 0x10700000 -#define MX1FS2_JFFS2_PART1_SIZE 0x00900000 #else #define MX1FS2_FLASH_BUS_WIDTH 2 /* we use 16 bit FLASH memory... */ #define MX1FS2_FLASH_INTERLEAVE 1 /* ... made of 1 chip */ @@ -167,9 +162,28 @@ * footprint. * NOTE: Enable CFG_CMD_JFFS2 for JFFS2 support. */ -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS2_FIRST_SECTOR 5 -#define CFG_JFFS2_NUM_BANKS 1 + +/* + * JFFS2 partitions + */ +/* No command line, one static partition, whole device */ +/* +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00050000 +*/ + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=mx1fs2-0" + +#ifdef BUS32BIT_VERSION +#define MTDPARTS_DEFAULT "mtdparts=mx1fs2-0:2m@5m(part0),5m@9m(part1)" +#else +#define MTDPARTS_DEFAULT "mtdparts=mx1fs2-0:-@320k(jffs2)" +#endif /* * Environment setup. Definitions of monitor location and size with diff --git a/include/configs/omap2420h4.h b/include/configs/omap2420h4.h index 47f78fad4..c7916036f 100644 --- a/include/configs/omap2420h4.h +++ b/include/configs/omap2420h4.h @@ -265,10 +265,23 @@ #define CFG_FLASH_ERASE_TOUT (30*75*CFG_HZ) /* Timeout for Flash Erase */ #define CFG_FLASH_WRITE_TOUT (30*75*CFG_HZ) /* Timeout for Flash Write */ -/* Flash banks JFFS2 should use */ -#define CFG_MAX_MTD_BANKS (CFG_MAX_FLASH_BANKS+CFG_MAX_NAND_DEVICE) #define CFG_JFFS2_MEM_NAND -#define CFG_JFFS2_FIRST_BANK 1 /* use flash_info[1] */ -#define CFG_JFFS2_NUM_BANKS 1 + +/* + * JFFS2 partitions + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor1" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor1=omap2420-1" +#define MTDPARTS_DEFAULT "mtdparts=omap2420-1:-(jffs2)" +*/ #endif /* __CONFIG_H */ diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h index 764efdf72..d7d07a62f 100644 --- a/include/configs/sc520_cdp.h +++ b/include/configs/sc520_cdp.h @@ -138,8 +138,22 @@ #define CONFIG_SC520_CDP_USE_SPI /* Store configuration in the SPI part */ #undef CONFIG_SC520_CDP_USE_MW /* Store configuration in the MicroWire part */ #define CONFIG_SPI_X 1 -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* */ + +/* + * JFFS2 partitions + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=SC520CDP Flash Bank #0" +#define MTDPARTS_DEFAULT "mtdparts=SC520CDP Flash Bank #0:-(jffs2)" +*/ /*----------------------------------------------------------------------- * Device drivers diff --git a/include/configs/sc520_spunk.h b/include/configs/sc520_spunk.h index 4114dd323..a8e355508 100644 --- a/include/configs/sc520_spunk.h +++ b/include/configs/sc520_spunk.h @@ -147,8 +147,23 @@ #endif -#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ -#define CFG_JFFS2_NUM_BANKS 1 /* */ +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=sc520_spunk-0" +#define MTDPARTS_DEFAULT "mtdparts=sc520_spunk-0:-(jffs2)" +*/ /*----------------------------------------------------------------------- * Device drivers diff --git a/include/configs/v37.h b/include/configs/v37.h index 45bc353ad..b3c62556d 100644 --- a/include/configs/v37.h +++ b/include/configs/v37.h @@ -87,10 +87,23 @@ CFG_CMD_JFFS2 | \ CFG_CMD_DATE ) +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor1" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 -/* Flash banks JFFS2 should use */ -#define CFG_JFFS2_FIRST_BANK 1 -#define CFG_JFFS2_NUM_BANKS 1 +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor1=v37-1" +#define MTDPARTS_DEFAULT "mtdparts=v37-1:-(jffs2)" +*/ /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ #include diff --git a/include/configs/voiceblue.h b/include/configs/voiceblue.h index 1640163cd..72b0a4c8e 100644 --- a/include/configs/voiceblue.h +++ b/include/configs/voiceblue.h @@ -247,4 +247,22 @@ #define VOICEBLUE_LED_REG 0x04030000 +/* + * JFFS2 partitions + * + */ +/* No command line, one static partition */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00040000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=voiceblue-0" +#define MTDPARTS_DEFAULT "mtdparts=voiceblue-0:128k(uboot),64k(env),64k(renv),-(jffs2)" +*/ + #endif /* __CONFIG_H */ diff --git a/include/configs/xsengine.h b/include/configs/xsengine.h index 847e91a05..dc702cf44 100644 --- a/include/configs/xsengine.h +++ b/include/configs/xsengine.h @@ -59,9 +59,23 @@ #define PHYS_FLASH_2 0x00000000 /* Flash Bank #2 */ #define PHYS_FLASH_SECT_SIZE 0x00020000 /* 127 KB sectors */ #define CFG_FLASH_BASE PHYS_FLASH_1 -#define CFG_JFFS2_NUM_BANKS 1 -#define CFG_JFFS2_FIRST_BANK 0 -#define CFG_JFFS_CUSTOM_PART 1 + +/* + * JFFS2 partitions + */ +/* No command line, one static partition, whole device */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" +#define CONFIG_JFFS2_PART_SIZE 0xFFFFFFFF +#define CONFIG_JFFS2_PART_OFFSET 0x00000000 + +/* mtdparts command line support */ +/* Note: fake mtd_id used, no linux mtd map file */ +/* +#define CONFIG_JFFS2_CMDLINE +#define MTDIDS_DEFAULT "nor0=xsengine-0" +#define MTDPARTS_DEFAULT "mtdparts=xsengine-0:256k(uboot),1m(kernel1),8m(kernel2)" +*/ /* Environment settings */ #define CONFIG_ENV_OVERWRITE diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h index d8b424076..882a80ea3 100644 --- a/include/jffs2/load_kernel.h +++ b/include/jffs2/load_kernel.h @@ -25,40 +25,37 @@ * */ -/* this struct is very similar to mtd_info */ -struct part_info { - u32 size; /* Total size of the Partition */ +#include - /* "Major" erase size for the device. Naïve users may take this - * to be the only erase size available, or may use the more detailed - * information below if they desire - */ - u32 erasesize; +/* mtd device types */ +#define MTD_DEV_TYPE_NOR 0x0001 +#define MTD_DEV_TYPE_NAND 0x0002 +#define MTD_DEV_TYPE(type) ((type == MTD_DEV_TYPE_NAND) ? "nand" : "nor") - /* Where in memory does this partition start? */ - char *offset; - - /* used by jffs2 set to NULL */ - void *jffs2_priv; - - /* private filed used by user */ - void *usr_priv; +struct mtd_device { + struct list_head link; + struct mtdids *id; /* parent mtd id entry */ + u16 num_parts; /* number of partitions on this device */ + struct list_head parts; /* partitions */ }; -struct part_info* -jffs2_part_info(int part_num); +struct part_info { + struct list_head link; + char *name; /* partition name */ + u8 auto_name; /* set to 1 for generated name */ + u32 size; /* total size of the partition */ + u32 offset; /* offset within device */ + void *jffs2_priv; /* used internaly by jffs2 */ + u32 mask_flags; /* kernel MTD mask flags */ + struct mtd_device *dev; /* parent device */ +}; -struct kernel_loader { - - /* Return true if there is a kernel contained at src */ - int (* check_magic)(struct part_info *part); - - /* load the kernel from the partition part to dst, return the number - * of bytes copied if successful, zero if not */ - u32 (* load_kernel)(u32 *dst, struct part_info *part, const char *kernel_filename); - - /* A brief description of the module (ie, "cramfs") */ - char *name; +struct mtdids { + struct list_head link; + u8 type; /* device type */ + u8 num; /* device number */ + u32 size; /* device size */ + char *mtd_id; /* linux kernel device id */ }; #define ldr_strlen strlen diff --git a/include/linux/list.h b/include/linux/list.h new file mode 100644 index 000000000..d2a7d43be --- /dev/null +++ b/include/linux/list.h @@ -0,0 +1,258 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#ifndef ARCH_HAS_PREFETCH +#define ARCH_HAS_PREFETCH +static inline void prefetch(const void *x) {;} +#endif + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +#endif