rendered paste bodyIndex: linux/drivers/mtd/Kconfig===================================================================--- linux.orig/drivers/mtd/Kconfig+++ linux/drivers/mtd/Kconfig@@ -47,6 +47,16 @@ config MTD_PARTITIONS devices. Partitioning on NFTL 'devices' is a different - that's the 'normal' form of partitioning used on a block device. +config MTD_ROOTFS_ROOT_DEV+ bool "Automatically set 'rootfs' partition to be root filesystem"+ depends on MTD_PARTITIONS+ default y++config MTD_ROOTFS_SPLIT+ bool "Automatically split 'rootfs' partition for squashfs"+ depends on MTD_PARTITIONS+ default y+ config MTD_REDBOOT_PARTS tristate "RedBoot partition table parsing" depends on MTD_PARTITIONSIndex: linux/drivers/mtd/mtdpart.c===================================================================--- linux.orig/drivers/mtd/mtdpart.c+++ linux/drivers/mtd/mtdpart.c@@ -20,6 +20,8 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/compatmac.h>+#include <linux/squashfs_fs.h>+#include <linux/root_dev.h> /* Our partition linked list */ static LIST_HEAD(mtd_partitions);@@ -308,6 +310,265 @@ int del_mtd_partitions(struct mtd_info * return 0; } +static u_int32_t cur_offset = 0;+static int add_one_partition(struct mtd_info *master, const struct mtd_partition *part,+ int i, struct mtd_part **slp)+{+ struct mtd_part *slave;++ /* allocate the partition structure */+ slave = kzalloc (sizeof(*slave), GFP_KERNEL);+ if (!slave) {+ printk ("memory allocation error while creating partitions for \"%s\"\n",+ master->name);+ del_mtd_partitions(master);+ return -ENOMEM;+ }+ list_add(&slave->list, &mtd_partitions);++ /* set up the MTD object for this partition */+ slave->mtd.type = master->type;+ slave->mtd.flags = master->flags & ~part->mask_flags;+ slave->mtd.size = part->size;+ slave->mtd.writesize = master->writesize;+ slave->mtd.oobsize = master->oobsize;+ slave->mtd.oobavail = master->oobavail;+ slave->mtd.subpage_sft = master->subpage_sft;++ slave->mtd.name = part->name;+ slave->mtd.owner = master->owner;++ slave->mtd.read = part_read;+ slave->mtd.write = part_write;++ if(master->point && master->unpoint){+ slave->mtd.point = part_point;+ slave->mtd.unpoint = part_unpoint;+ }++ if (master->read_oob)+ slave->mtd.read_oob = part_read_oob;+ if (master->write_oob)+ slave->mtd.write_oob = part_write_oob;+ if(master->read_user_prot_reg)+ slave->mtd.read_user_prot_reg = part_read_user_prot_reg;+ if(master->read_fact_prot_reg)+ slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;+ if(master->write_user_prot_reg)+ slave->mtd.write_user_prot_reg = part_write_user_prot_reg;+ if(master->lock_user_prot_reg)+ slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;+ if(master->get_user_prot_info)+ slave->mtd.get_user_prot_info = part_get_user_prot_info;+ if(master->get_fact_prot_info)+ slave->mtd.get_fact_prot_info = part_get_fact_prot_info;+ if (master->sync)+ slave->mtd.sync = part_sync;+ if (!i && master->suspend && master->resume) {+ slave->mtd.suspend = part_suspend;+ slave->mtd.resume = part_resume;+ }+ if (master->writev)+ slave->mtd.writev = part_writev;+ if (master->lock)+ slave->mtd.lock = part_lock;+ if (master->unlock)+ slave->mtd.unlock = part_unlock;+ if (master->block_isbad)+ slave->mtd.block_isbad = part_block_isbad;+ if (master->block_markbad)+ slave->mtd.block_markbad = part_block_markbad;+ slave->mtd.erase = part_erase;+ slave->master = master;+ slave->offset = part->offset;+ slave->index = i;++ if (slave->offset == MTDPART_OFS_APPEND)+ slave->offset = cur_offset;+ if (slave->offset == MTDPART_OFS_NXTBLK) {+ slave->offset = cur_offset;+ if ((cur_offset % master->erasesize) != 0) {+ /* Round up to next erasesize */+ slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;+ printk(KERN_NOTICE "Moving partition %d: "+ "0x%08x -> 0x%08x\n", i,+ cur_offset, slave->offset);+ }+ }+ if (slave->mtd.size == MTDPART_SIZ_FULL)+ slave->mtd.size = master->size - slave->offset;+ cur_offset = slave->offset + slave->mtd.size;++ printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,+ slave->offset + slave->mtd.size, slave->mtd.name);++ /* let's do some sanity checks */+ if (slave->offset >= master->size) {+ /* let's register it anyway to preserve ordering */+ slave->offset = 0;+ slave->mtd.size = 0;+ printk ("mtd: partition \"%s\" is out of reach -- disabled\n",+ part->name);+ }+ if (slave->offset + slave->mtd.size > master->size) {+ slave->mtd.size = master->size - slave->offset;+ printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",+ part->name, master->name, slave->mtd.size);+ }+ if (master->numeraseregions>1) {+ /* Deal with variable erase size stuff */+ int i;+ struct mtd_erase_region_info *regions = master->eraseregions;++ /* Find the first erase regions which is part of this partition. */+ for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)+ ;++ for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {+ if (slave->mtd.erasesize < regions[i].erasesize) {+ slave->mtd.erasesize = regions[i].erasesize;+ }+ }+ } else {+ /* Single erase size */+ slave->mtd.erasesize = master->erasesize;+ }++ if ((slave->mtd.flags & MTD_WRITEABLE) &&+ (slave->offset % slave->mtd.erasesize)) {+ /* Doesn't start on a boundary of major erase size */+ /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */+ slave->mtd.flags &= ~MTD_WRITEABLE;+ printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",+ part->name);+ }+ if ((slave->mtd.flags & MTD_WRITEABLE) &&+ (slave->mtd.size % slave->mtd.erasesize)) {+ slave->mtd.flags &= ~MTD_WRITEABLE;+ printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",+ part->name);+ }++ slave->mtd.ecclayout = master->ecclayout;+ if (master->block_isbad) {+ uint32_t offs = 0;++ while(offs < slave->mtd.size) {+ if (master->block_isbad(master,+ offs + slave->offset))+ slave->mtd.ecc_stats.badblocks++;+ offs += slave->mtd.erasesize;+ }+ }++ if(part->mtdp)+ { /* store the object pointer (caller may or may not register it */+ *part->mtdp = &slave->mtd;+ slave->registered = 0;+ }+ else+ {+ /* register our partition */+ add_mtd_device(&slave->mtd);+ slave->registered = 1;+ }++ if (slp)+ *slp = slave;++ return 0;+}++#ifdef CONFIG_MTD_ROOTFS_SPLIT+#define ROOTFS_SPLIT_NAME "rootfs_data"+static int split_squashfs(struct mtd_info *master, struct mtd_partition *old,+ struct mtd_partition **new)+{+ struct mtd_partition *part = NULL;+ int len;+ char buf[512];+ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;+ int ret;++ ret = master->read(master, old->offset, sizeof(*sb), &len, buf);+ if (ret) {+ printk(KERN_ALERT "split_squashfs: error occured while reading "+ "from \"%s\"\n", master->name);+ goto out;+ }++ if (len != sizeof(*sb)) {+ printk(KERN_ALERT "split_squashfs: unable to read superblock "+ "from \"%s\"\n", master->name);+ ret=-1;+ goto out;+ }++ if (*((u32 *) buf) != SQUASHFS_MAGIC) {+ printk(KERN_ALERT "split_squasfs: no squashfs found in \"%s\"\n",+ master->name);+ ret=0;+ goto out;+ }++ if (sb->bytes_used <= 0) {+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",+ master->name);+ ret=0;+ goto out;+ }++ part = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);+ if (part == NULL) {+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",+ ROOTFS_SPLIT_NAME);+ ret = -ENOMEM;+ goto out;+ }++ part->name = (unsigned char *)&part[1];+ memcpy(part, old, sizeof(*part));+ strcpy(part->name, ROOTFS_SPLIT_NAME);++ len = (u32) sb->bytes_used;+ len += (part->offset & 0x000fffff);+ len += (master->erasesize - 1);+ len &= ~(master->erasesize - 1);+ len -= (part->offset & 0x000fffff);+ part->offset += len;+ part->size -= len;++ ret = 0;++out:+ *new = part;+ return ret;+}++static int split_rootfs_data(struct mtd_info *master, struct mtd_partition *part,+ int index)+{+ struct mtd_partition *dpart;+ int ret;++ ret = split_squashfs(master, part, &dpart);+ if (ret)+ return ret;++ if (dpart == NULL)+ return 1;++ printk(KERN_INFO "mtd: \"%s\" created, ofs=%lX, len=%lX \n",+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);++ ret = add_one_partition(master, dpart, index, NULL);+ if (ret)+ kfree(dpart);++ return ret;+}+#endif /* CONFIG_MTD_ROOTFS_SPLIT */+ /* * This function, given a master MTD object and a partition table, creates * and registers slave MTD objects which are bound to the master according to@@ -320,168 +581,31 @@ int add_mtd_partitions(struct mtd_info * int nbparts) { struct mtd_part *slave;- u_int32_t cur_offset = 0;- int i;+ struct mtd_partition *part;+ int i, j, ret = 0; printk (KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); - for (i = 0; i < nbparts; i++) {-- /* allocate the partition structure */- slave = kzalloc (sizeof(*slave), GFP_KERNEL);- if (!slave) {- printk ("memory allocation error while creating partitions for \"%s\"\n",- master->name);- del_mtd_partitions(master);- return -ENOMEM;- }- list_add(&slave->list, &mtd_partitions);-- /* set up the MTD object for this partition */- slave->mtd.type = master->type;- slave->mtd.flags = master->flags & ~parts[i].mask_flags;- slave->mtd.size = parts[i].size;- slave->mtd.writesize = master->writesize;- slave->mtd.oobsize = master->oobsize;- slave->mtd.oobavail = master->oobavail;- slave->mtd.subpage_sft = master->subpage_sft;-- slave->mtd.name = parts[i].name;- slave->mtd.owner = master->owner;-- slave->mtd.read = part_read;- slave->mtd.write = part_write;-- if(master->point && master->unpoint){- slave->mtd.point = part_point;- slave->mtd.unpoint = part_unpoint;- }-- if (master->read_oob)- slave->mtd.read_oob = part_read_oob;- if (master->write_oob)- slave->mtd.write_oob = part_write_oob;- if(master->read_user_prot_reg)- slave->mtd.read_user_prot_reg = part_read_user_prot_reg;- if(master->read_fact_prot_reg)- slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;- if(master->write_user_prot_reg)- slave->mtd.write_user_prot_reg = part_write_user_prot_reg;- if(master->lock_user_prot_reg)- slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;- if(master->get_user_prot_info)- slave->mtd.get_user_prot_info = part_get_user_prot_info;- if(master->get_fact_prot_info)- slave->mtd.get_fact_prot_info = part_get_fact_prot_info;- if (master->sync)- slave->mtd.sync = part_sync;- if (!i && master->suspend && master->resume) {- slave->mtd.suspend = part_suspend;- slave->mtd.resume = part_resume;- }- if (master->writev)- slave->mtd.writev = part_writev;- if (master->lock)- slave->mtd.lock = part_lock;- if (master->unlock)- slave->mtd.unlock = part_unlock;- if (master->block_isbad)- slave->mtd.block_isbad = part_block_isbad;- if (master->block_markbad)- slave->mtd.block_markbad = part_block_markbad;- slave->mtd.erase = part_erase;- slave->master = master;- slave->offset = parts[i].offset;- slave->index = i;-- if (slave->offset == MTDPART_OFS_APPEND)- slave->offset = cur_offset;- if (slave->offset == MTDPART_OFS_NXTBLK) {- slave->offset = cur_offset;- if ((cur_offset % master->erasesize) != 0) {- /* Round up to next erasesize */- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;- printk(KERN_NOTICE "Moving partition %d: "- "0x%08x -> 0x%08x\n", i,- cur_offset, slave->offset);- }- }- if (slave->mtd.size == MTDPART_SIZ_FULL)- slave->mtd.size = master->size - slave->offset;- cur_offset = slave->offset + slave->mtd.size;-- printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,- slave->offset + slave->mtd.size, slave->mtd.name);-- /* let's do some sanity checks */- if (slave->offset >= master->size) {- /* let's register it anyway to preserve ordering */- slave->offset = 0;- slave->mtd.size = 0;- printk ("mtd: partition \"%s\" is out of reach -- disabled\n",- parts[i].name);- }- if (slave->offset + slave->mtd.size > master->size) {- slave->mtd.size = master->size - slave->offset;- printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",- parts[i].name, master->name, slave->mtd.size);- }- if (master->numeraseregions>1) {- /* Deal with variable erase size stuff */- int i;- struct mtd_erase_region_info *regions = master->eraseregions;-- /* Find the first erase regions which is part of this partition. */- for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)- ;-- for (i--; i < master->numeraseregions && slave->offset + slave->mtd.size > regions[i].offset; i++) {- if (slave->mtd.erasesize < regions[i].erasesize) {- slave->mtd.erasesize = regions[i].erasesize;- }- }- } else {- /* Single erase size */- slave->mtd.erasesize = master->erasesize;- }-- if ((slave->mtd.flags & MTD_WRITEABLE) &&- (slave->offset % slave->mtd.erasesize)) {- /* Doesn't start on a boundary of major erase size */- /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */- slave->mtd.flags &= ~MTD_WRITEABLE;- printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",- parts[i].name);- }- if ((slave->mtd.flags & MTD_WRITEABLE) &&- (slave->mtd.size % slave->mtd.erasesize)) {- slave->mtd.flags &= ~MTD_WRITEABLE;- printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",- parts[i].name);- }-- slave->mtd.ecclayout = master->ecclayout;- if (master->block_isbad) {- uint32_t offs = 0;-- while(offs < slave->mtd.size) {- if (master->block_isbad(master,- offs + slave->offset))- slave->mtd.ecc_stats.badblocks++;- offs += slave->mtd.erasesize;+ for (i = 0, j = 0; i < nbparts; i++) {+ part = (struct mtd_partition *) &parts[i];+ ret = add_one_partition(master, part, j, &slave);+ if (ret)+ return ret;+ j++;++ if (strcmp(part->name, "rootfs") == 0 && slave->registered) {+#if CONFIG_MTD_ROOTFS_ROOT_DEV+ if (ROOT_DEV == 0) {+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "+ "set to be root filesystem\n");+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); }- }-- if(parts[i].mtdp)- { /* store the object pointer (caller may or may not register it */- *parts[i].mtdp = &slave->mtd;- slave->registered = 0;- }- else- {- /* register our partition */- add_mtd_device(&slave->mtd);- slave->registered = 1;+#endif+#if CONFIG_MTD_ROOTFS_SPLIT+ ret = split_rootfs_data(master, part, j);+ if (ret == 0)+ j++;+#endif } }