X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fgeneric%2Fpatches-3.10%2F400-rootfs_split.patch;h=4cacf641d8eb1822ce5826a020410406db68f370;hb=4570f03865c8d5d64adadd18d5537556e428fa1f;hp=2bb7774fc6dcd597de4ffa022bb2779ba441485e;hpb=f6ad0fc9373a736f9640d698e557c86dc6074edd;p=openwrt.git diff --git a/target/linux/generic/patches-3.10/400-rootfs_split.patch b/target/linux/generic/patches-3.10/400-rootfs_split.patch index 2bb7774fc6..4cacf641d8 100644 --- a/target/linux/generic/patches-3.10/400-rootfs_split.patch +++ b/target/linux/generic/patches-3.10/400-rootfs_split.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -23,6 +23,14 @@ config MTD_TESTS +@@ -23,6 +23,23 @@ config MTD_TESTS WARNING: some of the tests will ERASE entire MTD device which they test. Do not use these tests unless you really know what you do. @@ -12,6 +12,15 @@ + bool "Automatically split 'rootfs' partition for squashfs" + default y + ++config MTD_UIMAGE_SPLIT ++ bool "Automatically split off rootfs from a kernel partition containing a uImage" ++ default y ++ ++config MTD_UIMAGE_SPLIT_NAME ++ string "uImage partition name" ++ depends on MTD_UIMAGE_SPLIT ++ default "firmware" ++ config MTD_REDBOOT_PARTS tristate "RedBoot partition table parsing" ---help--- @@ -26,7 +35,14 @@ #include #include "mtdcore.h" -@@ -50,7 +52,7 @@ struct mtd_part { +@@ -45,12 +47,14 @@ struct mtd_part { + struct list_head list; + }; + ++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part); ++ + /* + * Given a pointer to the MTD object in the mtd_part structure, we can retrieve * the pointer to that structure with this macro. */ #define PART(x) ((struct mtd_part *)(x)) @@ -35,10 +51,82 @@ /* * MTD methods which simply translate the effective address and pass through -@@ -613,6 +615,144 @@ int mtd_del_partition(struct mtd_info *m +@@ -533,8 +537,10 @@ out_register: + return slave; + } + +-int mtd_add_partition(struct mtd_info *master, char *name, +- long long offset, long long length) ++ ++static int ++__mtd_add_partition(struct mtd_info *master, char *name, ++ long long offset, long long length, bool dup_check) + { + struct mtd_partition part; + struct mtd_part *p, *new; +@@ -566,21 +572,24 @@ int mtd_add_partition(struct mtd_info *m + end = offset + length; + + mutex_lock(&mtd_partitions_mutex); +- list_for_each_entry(p, &mtd_partitions, list) +- if (p->master == master) { +- if ((start >= p->offset) && +- (start < (p->offset + p->mtd.size))) +- goto err_inv; +- +- if ((end >= p->offset) && +- (end < (p->offset + p->mtd.size))) +- goto err_inv; +- } ++ if (dup_check) { ++ list_for_each_entry(p, &mtd_partitions, list) ++ if (p->master == master) { ++ if ((start >= p->offset) && ++ (start < (p->offset + p->mtd.size))) ++ goto err_inv; ++ ++ if ((end >= p->offset) && ++ (end < (p->offset + p->mtd.size))) ++ goto err_inv; ++ } ++ } + + list_add(&new->list, &mtd_partitions); + mutex_unlock(&mtd_partitions_mutex); + + add_mtd_device(&new->mtd); ++ mtd_partition_split(master, new); + + return ret; + err_inv: +@@ -590,6 +599,12 @@ err_inv: + } + EXPORT_SYMBOL_GPL(mtd_add_partition); + ++int mtd_add_partition(struct mtd_info *master, char *name, ++ long long offset, long long length) ++{ ++ return __mtd_add_partition(master, name, offset, length, true); ++} ++ + int mtd_del_partition(struct mtd_info *master, int partno) + { + struct mtd_part *slave, *next; +@@ -613,6 +628,149 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); ++static inline unsigned long ++mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len) ++{ ++ unsigned long mask = mtd->erasesize - 1; ++ ++ len += offset & mask; ++ len = (len + mask) & ~mask; ++ len -= offset & mask; ++ return len; ++} ++ +#ifdef CONFIG_MTD_ROOTFS_SPLIT +#define ROOTFS_SPLIT_NAME "rootfs_data" +#define ROOTFS_REMOVED_NAME "" @@ -77,240 +165,118 @@ + } + + len = (u32) le64_to_cpu(sb.bytes_used); -+ len += (offset & 0x000fffff); -+ len += (master->erasesize - 1); -+ len &= ~(master->erasesize - 1); -+ len -= (offset & 0x000fffff); ++ len = mtd_pad_erasesize(master, offset, len); + *split_offset = offset + len; + + return 0; +} + -+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) ++static void split_rootfs_data(struct mtd_info *master, struct mtd_part *part) +{ -+ struct mtd_partition dpart; -+ struct mtd_part *slave = NULL; -+ struct mtd_part *spart; -+ int ret, split_offset = 0; ++ unsigned int split_offset = 0; ++ unsigned int split_size; ++ int ret; + -+ spart = PART(rpart); -+ ret = split_squashfs(master, spart->offset, &split_offset); ++ ret = split_squashfs(master, part->offset, &split_offset); + if (ret) -+ return ret; ++ return; + + if (split_offset <= 0) -+ return 0; ++ return; + -+ memcpy(&dpart, part, sizeof(dpart)); -+ dpart.name = ROOTFS_SPLIT_NAME; ++ split_size = part->mtd.size - (split_offset - part->offset); ++ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=0x%x, len=0x%x\n", ++ ROOTFS_SPLIT_NAME, split_offset, split_size); + -+ dpart.size = rpart->size - (split_offset - spart->offset); -+ dpart.offset = split_offset; ++ __mtd_add_partition(master, ROOTFS_SPLIT_NAME, split_offset, ++ split_size, false); ++} ++#endif /* CONFIG_MTD_ROOTFS_SPLIT */ + -+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", -+ ROOTFS_SPLIT_NAME, dpart.offset, dpart.size); ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++#define UBOOT_MAGIC 0x27051956 + -+ slave = allocate_partition(master, &dpart, 0, split_offset); -+ if (IS_ERR(slave)) -+ return PTR_ERR(slave); -+ mutex_lock(&mtd_partitions_mutex); -+ list_add(&slave->list, &mtd_partitions); -+ mutex_unlock(&mtd_partitions_mutex); ++static void split_uimage(struct mtd_info *master, struct mtd_part *part) ++{ ++ struct { ++ __be32 magic; ++ __be32 pad[2]; ++ __be32 size; ++ } hdr; ++ size_t len; + -+ add_mtd_device(&slave->mtd); ++ if (strcmp(part->mtd.name, CONFIG_MTD_UIMAGE_SPLIT_NAME) != 0) ++ return; + -+ rpart->split = &slave->mtd; ++ if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) ++ return; + -+ return 0; ++ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) ++ return; ++ ++ len = be32_to_cpu(hdr.size) + 0x40; ++ len = mtd_pad_erasesize(master, part->offset, len); ++ if (len + master->erasesize > part->mtd.size) ++ return; ++ ++ __mtd_add_partition(master, "rootfs", part->offset + len, ++ part->mtd.size - len, false); +} ++#endif + -+static int refresh_rootfs_split(struct mtd_info *mtd) ++void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, ++ int offset, int size) +{ -+ struct mtd_partition tpart; -+ struct mtd_part *part; -+ char *name; -+ //int index = 0; -+ int offset, size; -+ int ret; ++} + -+ part = PART(mtd); + -+ /* check for the new squashfs offset first */ -+ ret = split_squashfs(part->master, part->offset, &offset); -+ if (ret) -+ return ret; -+ -+ if ((offset > 0) && !mtd->split) { -+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); -+ /* if we don't have a rootfs split partition, create a new one */ -+ tpart.name = (char *) mtd->name; -+ tpart.size = mtd->size; -+ tpart.offset = part->offset; -+ -+ return split_rootfs_data(part->master, &part->mtd, &tpart); -+ } else if ((offset > 0) && mtd->split) { -+ /* update the offsets of the existing partition */ -+ size = mtd->size + part->offset - offset; -+ -+ part = PART(mtd->split); -+ part->offset = offset; -+ part->mtd.size = size; -+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", -+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), -+ (u32) part->offset, (u32) part->mtd.size); -+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); -+ strcpy(name, ROOTFS_SPLIT_NAME); -+ part->mtd.name = name; -+ } else if ((offset <= 0) && mtd->split) { -+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); -+ -+ /* mark existing partition as removed */ -+ part = PART(mtd->split); -+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); -+ strcpy(name, ROOTFS_REMOVED_NAME); -+ part->mtd.name = name; -+ part->offset = 0; -+ part->mtd.size = 0; -+ } ++static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part) ++{ ++ static int rootfs_found = 0; + -+ return 0; -+} -+#endif /* CONFIG_MTD_ROOTFS_SPLIT */ ++ if (rootfs_found) ++ return; ++ ++ if (!strcmp(part->mtd.name, "rootfs")) { ++ rootfs_found = 1; + - /* - * 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 -@@ -629,6 +769,9 @@ int add_mtd_partitions(struct mtd_info * - struct mtd_part *slave; - uint64_t cur_offset = 0; - int i; -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ int ret; -+#endif - - printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); - -@@ -643,12 +786,53 @@ int add_mtd_partitions(struct mtd_info * - - add_mtd_device(&slave->mtd); - -+ if (!strcmp(parts[i].name, "rootfs")) { +#ifdef 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 (ROOT_DEV == 0) { ++ printk(KERN_NOTICE "mtd: partition \"rootfs\" " ++ "set to be root filesystem\n"); ++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, part->mtd.index); ++ } +#endif +#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ ret = split_rootfs_data(master, &slave->mtd, &parts[i]); -+ /* if (ret == 0) -+ * j++; */ ++ split_rootfs_data(master, part); +#endif -+ } -+ - cur_offset = slave->offset + slave->mtd.size; - } - - return 0; - } - -+int mtd_device_refresh(struct mtd_info *mtd) -+{ -+ int ret = 0; -+ -+ if (IS_PART(mtd)) { -+ struct mtd_part *part; -+ struct mtd_info *master; -+ -+ part = PART(mtd); -+ master = part->master; -+ if (master->refresh_device) -+ ret = master->refresh_device(master); + } + -+ if (!ret && mtd->refresh_device) -+ ret = mtd->refresh_device(mtd); -+ -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) -+ refresh_rootfs_split(mtd); ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++ split_uimage(master, part); +#endif + -+ return 0; ++ arch_split_mtd_part(master, part->mtd.name, part->offset, ++ part->mtd.size); +} -+EXPORT_SYMBOL_GPL(mtd_device_refresh); -+ - static DEFINE_SPINLOCK(part_parser_lock); - static LIST_HEAD(part_parsers); + /* + * 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 +@@ -642,6 +800,7 @@ int add_mtd_partitions(struct mtd_info * + mutex_unlock(&mtd_partitions_mutex); ---- a/drivers/mtd/mtdchar.c -+++ b/drivers/mtd/mtdchar.c -@@ -1010,6 +1010,12 @@ static int mtdchar_ioctl(struct file *fi - break; - } + add_mtd_device(&slave->mtd); ++ mtd_partition_split(master, slave); -+ case MTDREFRESH: -+ { -+ ret = mtd_device_refresh(mtd); -+ break; -+ } -+ - default: - ret = -ENOTTY; + cur_offset = slave->offset + slave->mtd.size; } ---- a/include/linux/mtd/mtd.h -+++ b/include/linux/mtd/mtd.h -@@ -114,6 +114,7 @@ struct nand_ecclayout { - - struct module; /* only needed for owner field in mtd_info */ - -+struct mtd_info; - struct mtd_info { - u_char type; - uint32_t flags; -@@ -226,6 +227,9 @@ struct mtd_info { - int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); - int (*_suspend) (struct mtd_info *mtd); - void (*_resume) (struct mtd_info *mtd); -+ int (*refresh_device)(struct mtd_info *mtd); -+ struct mtd_info *split; -+ - /* - * If the driver is something smart, like UBI, it may need to maintain - * its own reference counting. The below functions are only for driver. -@@ -368,6 +372,7 @@ extern int mtd_device_parse_register(str - int defnr_parts); - #define mtd_device_register(master, parts, nr_parts) \ - mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) -+extern int mtd_device_refresh(struct mtd_info *master); - extern int mtd_device_unregister(struct mtd_info *master); - extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); - extern int __get_mtd_device(struct mtd_info *mtd); --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -36,12 +36,14 @@ - * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). - */ +@@ -84,5 +84,7 @@ int mtd_add_partition(struct mtd_info *m + long long offset, long long length); + int mtd_del_partition(struct mtd_info *master, int partno); + uint64_t mtd_get_device_size(const struct mtd_info *mtd); ++extern void __weak arch_split_mtd_part(struct mtd_info *master, ++ const char *name, int offset, int size); -+struct mtd_partition; - struct mtd_partition { - char *name; /* identifier string */ - uint64_t size; /* partition size */ - uint64_t offset; /* offset within the master MTD space */ - uint32_t mask_flags; /* master MTD flags to mask out for this partition */ - struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */ -+ int (*refresh_partition)(struct mtd_info *); - }; - - #define MTDPART_OFS_RETAIN (-3) ---- a/include/uapi/mtd/mtd-abi.h -+++ b/include/uapi/mtd/mtd-abi.h -@@ -202,6 +202,7 @@ struct otp_info { - * without OOB, e.g., NOR flash. - */ - #define MEMWRITE _IOWR('M', 24, struct mtd_write_req) -+#define MTDREFRESH _IO('M', 50) - - /* - * Obsolete legacy interface. Keep it in order not to break userspace + #endif