From 4d5f296af857ecbd3916d1d156d1bc63c998995a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 23 Jun 2017 10:47:18 +0200 Subject: [PATCH] kernel: backport upstream mtd support for partition parsers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In a log term it should replace our implementation. For now both can coexist. Signed-off-by: Rafał Miłecki --- ...itions-add-support-for-subpartitions.patch | 96 +++++++++++++++ ...ns-add-support-for-partition-parsers.patch | 110 ++++++++++++++++++ ...-generic-parsing-of-linux-part-probe.patch | 6 +- .../400-mtd-add-rootfs-split-support.patch | 12 +- ...for-different-partition-parser-types.patch | 8 +- ...arsers-for-rootfs-and-firmware-split.patch | 8 +- .../404-mtd-add-more-helper-functions.patch | 6 +- ...rward-declaration-of-struct-mtd_info.patch | 4 +- .../411-mtd-partial_eraseblock_write.patch | 2 +- 9 files changed, 229 insertions(+), 23 deletions(-) create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0006-mtd-partitions-add-support-for-subpartitions.patch create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0007-mtd-partitions-add-support-for-partition-parsers.patch diff --git a/target/linux/generic/patches-4.9/065-v4.13-0006-mtd-partitions-add-support-for-subpartitions.patch b/target/linux/generic/patches-4.9/065-v4.13-0006-mtd-partitions-add-support-for-subpartitions.patch new file mode 100644 index 000000000000..0d3e10ac201e --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0006-mtd-partitions-add-support-for-subpartitions.patch @@ -0,0 +1,96 @@ +From 97519dc52b44af054d7654776e78eaa211cf1842 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Jun 2017 08:26:45 +0200 +Subject: [PATCH] mtd: partitions: add support for subpartitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some flash device partitions can be containers with extra subpartitions +(volumes). All callbacks are already capable of this additional level of +indirection. + +This patch makes sure we always display subpartitions using a tree +structure and takes care of deleting subpartitions when parent gets +removed. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -413,7 +413,7 @@ static struct mtd_part *allocate_partiti + * parent conditional on that option. Note, this is a way to + * distinguish between the master and the partition in sysfs. + */ +- slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ? ++ slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ? + &parent->dev : + parent->dev.parent; + slave->mtd.dev.of_node = part->of_node; +@@ -664,8 +664,17 @@ EXPORT_SYMBOL_GPL(mtd_add_partition); + */ + static int __mtd_del_partition(struct mtd_part *priv) + { ++ struct mtd_part *child, *next; + int err; + ++ list_for_each_entry_safe(child, next, &mtd_partitions, list) { ++ if (child->parent == &priv->mtd) { ++ err = __mtd_del_partition(child); ++ if (err) ++ return err; ++ } ++ } ++ + sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs); + + err = del_mtd_device(&priv->mtd); +@@ -680,16 +689,16 @@ static int __mtd_del_partition(struct mt + + /* + * This function unregisters and destroy all slave MTD objects which are +- * attached to the given master MTD object. ++ * attached to the given MTD object. + */ +-int del_mtd_partitions(struct mtd_info *master) ++int del_mtd_partitions(struct mtd_info *mtd) + { + struct mtd_part *slave, *next; + int ret, err = 0; + + mutex_lock(&mtd_partitions_mutex); + list_for_each_entry_safe(slave, next, &mtd_partitions, list) +- if (slave->parent == master) { ++ if (slave->parent == mtd) { + ret = __mtd_del_partition(slave); + if (ret < 0) + err = ret; +@@ -699,14 +708,14 @@ int del_mtd_partitions(struct mtd_info * + return err; + } + +-int mtd_del_partition(struct mtd_info *master, int partno) ++int mtd_del_partition(struct mtd_info *mtd, int partno) + { + struct mtd_part *slave, *next; + int ret = -EINVAL; + + mutex_lock(&mtd_partitions_mutex); + list_for_each_entry_safe(slave, next, &mtd_partitions, list) +- if ((slave->parent == master) && ++ if ((slave->parent == mtd) && + (slave->mtd.index == partno)) { + ret = __mtd_del_partition(slave); + break; +@@ -939,6 +948,6 @@ uint64_t mtd_get_device_size(const struc + if (!mtd_is_partition(mtd)) + return mtd->size; + +- return mtd_to_part(mtd)->parent->size; ++ return mtd_get_device_size(mtd_to_part(mtd)->parent); + } + EXPORT_SYMBOL_GPL(mtd_get_device_size); diff --git a/target/linux/generic/patches-4.9/065-v4.13-0007-mtd-partitions-add-support-for-partition-parsers.patch b/target/linux/generic/patches-4.9/065-v4.13-0007-mtd-partitions-add-support-for-partition-parsers.patch new file mode 100644 index 000000000000..a28ee316fac7 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0007-mtd-partitions-add-support-for-partition-parsers.patch @@ -0,0 +1,110 @@ +From 1a0915be192606fee64830b9c5d70b7ed59426b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 21 Jun 2017 08:26:46 +0200 +Subject: [PATCH] mtd: partitions: add support for partition parsers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some devices have partitions that are kind of containers with extra +subpartitions / volumes instead of e.g. a simple filesystem data. To +support such cases we need to first create normal flash device +partitions and then take care of these special ones. + +It's very common case for home routers. Depending on the vendor there +are formats like TRX, Seama, TP-Link, WRGG & more. All of them are used +to embed few partitions into a single one / single firmware file. + +Ideally all vendors would use some well documented / standardized format +like UBI (and some probably start doing so), but there are still +countless devices on the market using these poor vendor specific +formats. + +This patch extends MTD subsystem by allowing to specify list of parsers +that should be tried for a given partition. Supporting such poor formats +is highly unlikely to be the top priority so these changes try to +minimize maintenance cost to the minimum. It reuses existing code for +these new parsers and just adds a one property and one new function. + +This implementation requires setting partition parsers in a flash +parser. A proper change of bcm47xxpart will follow and in the future we +will hopefully also find a solution for doing it with ofpart +("fixed-partitions"). + +Signed-off-by: Rafał Miłecki +Signed-off-by: Brian Norris +--- + drivers/mtd/mtdpart.c | 31 +++++++++++++++++++++++++++++++ + include/linux/mtd/partitions.h | 7 +++++++ + 2 files changed, 38 insertions(+) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -369,6 +369,35 @@ static inline void free_partition(struct + kfree(p); + } + ++/** ++ * mtd_parse_part - parse MTD partition looking for subpartitions ++ * ++ * @slave: part that is supposed to be a container and should be parsed ++ * @types: NULL-terminated array with names of partition parsers to try ++ * ++ * Some partitions are kind of containers with extra subpartitions (volumes). ++ * There can be various formats of such containers. This function tries to use ++ * specified parsers to analyze given partition and registers found ++ * subpartitions on success. ++ */ ++static int mtd_parse_part(struct mtd_part *slave, const char *const *types) ++{ ++ struct mtd_partitions parsed; ++ int err; ++ ++ err = parse_mtd_partitions(&slave->mtd, types, &parsed, NULL); ++ if (err) ++ return err; ++ else if (!parsed.nr_parts) ++ return -ENOENT; ++ ++ err = add_mtd_partitions(&slave->mtd, parsed.parts, parsed.nr_parts); ++ ++ mtd_part_parser_cleanup(&parsed); ++ ++ return err; ++} ++ + static struct mtd_part *allocate_partition(struct mtd_info *parent, + const struct mtd_partition *part, int partno, + uint64_t cur_offset) +@@ -758,6 +787,8 @@ int add_mtd_partitions(struct mtd_info * + + add_mtd_device(&slave->mtd); + mtd_add_partition_attrs(slave); ++ if (parts[i].types) ++ mtd_parse_part(slave, parts[i].types); + + cur_offset = slave->offset + slave->mtd.size; + } +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -20,6 +20,12 @@ + * + * For each partition, these fields are available: + * name: string that will be used to label the partition's MTD device. ++ * types: some partitions can be containers using specific format to describe ++ * embedded subpartitions / volumes. E.g. many home routers use "firmware" ++ * partition that contains at least kernel and rootfs. In such case an ++ * extra parser is needed that will detect these dynamic partitions and ++ * report them to the MTD subsystem. If set this property stores an array ++ * of parser names to use when looking for subpartitions. + * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition + * will extend to the end of the master MTD device. + * offset: absolute starting position within the master MTD device; if +@@ -38,6 +44,7 @@ + + struct mtd_partition { + const char *name; /* identifier string */ ++ const char *const *types; /* names of parsers to use if any */ + 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 */ diff --git a/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch b/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch index 8bca58a31e62..41609d5aaedd 100644 --- a/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch +++ b/target/linux/generic/patches-4.9/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch @@ -116,7 +116,7 @@ Signed-off-by: Hauke Mehrtens #include #include "mtdcore.h" -@@ -815,6 +816,42 @@ void deregister_mtd_parser(struct mtd_pa +@@ -855,6 +856,42 @@ void deregister_mtd_parser(struct mtd_pa EXPORT_SYMBOL_GPL(deregister_mtd_parser); /* @@ -159,7 +159,7 @@ Signed-off-by: Hauke Mehrtens * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you * are changing this array! */ -@@ -872,6 +909,13 @@ int parse_mtd_partitions(struct mtd_info +@@ -912,6 +949,13 @@ int parse_mtd_partitions(struct mtd_info { struct mtd_part_parser *parser; int ret, err = 0; @@ -173,7 +173,7 @@ Signed-off-by: Hauke Mehrtens if (!types) types = default_mtd_part_types; -@@ -897,6 +941,7 @@ int parse_mtd_partitions(struct mtd_info +@@ -937,6 +981,7 @@ int parse_mtd_partitions(struct mtd_info if (ret < 0 && !err) err = ret; } diff --git a/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch b/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch index bc402a2c119c..96a50c88dc32 100644 --- a/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch +++ b/target/linux/generic/patches-4.9/400-mtd-add-rootfs-split-support.patch @@ -48,7 +48,7 @@ /* * Given a pointer to the MTD object in the mtd_part structure, we can retrieve * the pointer to that structure. -@@ -649,6 +653,7 @@ int mtd_add_partition(struct mtd_info *p +@@ -678,6 +682,7 @@ int mtd_add_partition(struct mtd_info *p mutex_unlock(&mtd_partitions_mutex); add_mtd_device(&new->mtd); @@ -56,7 +56,7 @@ mtd_add_partition_attrs(new); -@@ -718,6 +723,35 @@ int mtd_del_partition(struct mtd_info *m +@@ -756,6 +761,35 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); @@ -92,17 +92,17 @@ /* * 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 -@@ -749,6 +783,7 @@ int add_mtd_partitions(struct mtd_info * +@@ -787,6 +821,7 @@ int add_mtd_partitions(struct mtd_info * mutex_unlock(&mtd_partitions_mutex); add_mtd_device(&slave->mtd); + mtd_partition_split(master, slave); mtd_add_partition_attrs(slave); - - cur_offset = slave->offset + slave->mtd.size; + if (parts[i].types) + mtd_parse_part(slave, parts[i].types); --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -102,5 +102,7 @@ int mtd_add_partition(struct mtd_info *m +@@ -109,5 +109,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); diff --git a/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch b/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch index 71a97a00f441..2cf69ffa1727 100644 --- a/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch +++ b/target/linux/generic/patches-4.9/401-mtd-add-support-for-different-partition-parser-types.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -996,6 +996,62 @@ void mtd_part_parser_cleanup(struct mtd_ +@@ -1036,6 +1036,62 @@ void mtd_part_parser_cleanup(struct mtd_ } } @@ -76,7 +76,7 @@ Signed-off-by: Gabor Juhos struct mtd_part *part; --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -61,11 +61,14 @@ struct mtd_part_parser_data { +@@ -68,11 +68,14 @@ struct mtd_part_parser_data { unsigned long origin; }; @@ -92,7 +92,7 @@ Signed-off-by: Gabor Juhos struct mtd_part_parser { struct list_head list; struct module *owner; -@@ -73,6 +76,7 @@ struct mtd_part_parser { +@@ -80,6 +83,7 @@ struct mtd_part_parser { int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, struct mtd_part_parser_data *); void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); @@ -100,7 +100,7 @@ Signed-off-by: Gabor Juhos }; /* Container for passing around a set of parsed partitions */ -@@ -105,4 +109,9 @@ uint64_t mtd_get_device_size(const struc +@@ -112,4 +116,9 @@ uint64_t mtd_get_device_size(const struc extern void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, int offset, int size); diff --git a/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch b/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch index 02fb9cce3e7b..490107ec4043 100644 --- a/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch +++ b/target/linux/generic/patches-4.9/402-mtd-use-typed-mtd-parsers-for-rootfs-and-firmware-split.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -723,6 +723,36 @@ int mtd_del_partition(struct mtd_info *m +@@ -761,6 +761,36 @@ int mtd_del_partition(struct mtd_info *m } EXPORT_SYMBOL_GPL(mtd_del_partition); @@ -37,7 +37,7 @@ #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else -@@ -731,6 +761,7 @@ EXPORT_SYMBOL_GPL(mtd_del_partition); +@@ -769,6 +799,7 @@ EXPORT_SYMBOL_GPL(mtd_del_partition); static void split_firmware(struct mtd_info *master, struct mtd_part *part) { @@ -45,7 +45,7 @@ } void __weak arch_split_mtd_part(struct mtd_info *master, const char *name, -@@ -745,6 +776,12 @@ static void mtd_partition_split(struct m +@@ -783,6 +814,12 @@ static void mtd_partition_split(struct m if (rootfs_found) return; @@ -60,7 +60,7 @@ split_firmware(master, part); --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -67,6 +67,8 @@ struct mtd_part_parser_data { +@@ -74,6 +74,8 @@ struct mtd_part_parser_data { enum mtd_parser_type { MTD_PARSER_TYPE_DEVICE = 0, diff --git a/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch b/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch index 319a22a4502c..ef7b671b8b90 100644 --- a/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch +++ b/target/linux/generic/patches-4.9/404-mtd-add-more-helper-functions.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -753,6 +753,17 @@ run_parsers_by_type(struct mtd_part *sla +@@ -791,6 +791,17 @@ run_parsers_by_type(struct mtd_part *sla return nr_parts; } @@ -18,7 +18,7 @@ #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else -@@ -1106,6 +1117,24 @@ int mtd_is_partition(const struct mtd_in +@@ -1146,6 +1157,24 @@ int mtd_is_partition(const struct mtd_in } EXPORT_SYMBOL_GPL(mtd_is_partition); @@ -45,7 +45,7 @@ { --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -107,6 +107,8 @@ int mtd_is_partition(const struct mtd_in +@@ -114,6 +114,8 @@ int mtd_is_partition(const struct mtd_in int mtd_add_partition(struct mtd_info *master, const char *name, long long offset, long long length); int mtd_del_partition(struct mtd_info *master, int partno); diff --git a/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch b/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch index 78ebbf88ca9d..7c927359cffc 100644 --- a/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch +++ b/target/linux/generic/patches-4.9/410-mtd-move-forward-declaration-of-struct-mtd_info.patch @@ -1,6 +1,6 @@ --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h -@@ -35,6 +35,7 @@ +@@ -41,6 +41,7 @@ * Note: writeable partitions require their size and offset be * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). */ @@ -8,7 +8,7 @@ struct mtd_partition { const char *name; /* identifier string */ -@@ -50,7 +51,6 @@ struct mtd_partition { +@@ -57,7 +58,6 @@ struct mtd_partition { #define MTDPART_SIZ_FULL (0) diff --git a/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch index 0e2d4920e456..359eb5a6f8a2 100644 --- a/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch +++ b/target/linux/generic/patches-4.9/411-mtd-partial_eraseblock_write.patch @@ -97,7 +97,7 @@ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) instr->fail_addr -= part->offset; -@@ -561,19 +630,22 @@ static struct mtd_part *allocate_partiti +@@ -590,19 +659,22 @@ static struct mtd_part *allocate_partiti remainder = do_div(tmp, wr_alignment); if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { /* Doesn't start on a boundary of major erase size */ -- 2.30.2