All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] mtd: add support for typed parsers splitting partitions
@ 2015-05-18 12:34 Rafał Miłecki
  2015-05-18 12:34 ` [PATCH PROOF 2/1] mtd: add TRX parser splitting firmware partition Rafał Miłecki
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Rafał Miłecki @ 2015-05-18 12:34 UTC (permalink / raw)
  To: Brian Norris, linux-mtd
  Cc: Gabor Juhos, Felix Fietkau, Rafał Miłecki, Hauke Mehrtens

This extends MTD architecture by introducing partition types which allow
handling selected (marked) partitions in a specific way. There are some
types of partitions that require splitting, e.g. firmware containers.
On some devices we want to have "firmware" container partition (for easy
firmware upgrade) as well as subpartitions (e.g. to use rootfs).

Thanks to this change we will also avoid code duplication across various
drivers/architectures. It will allow multiple drivers to use the same
parser just by setting a proper type.

An example use case for this can be TRX firmware format parser. This
format contains 2-4 partitions including kernel and rootfs. It is used
by many Broadcom devices on various platforms (bcm47xx, bcm53xx, ath79).

When partition with a specified type is created we loop over registered
parsers running ones with a matching type. When one returns list of new
partitions we create them.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/mtd/mtdpart.c          | 74 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/mtd/partitions.h |  7 ++++
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index cafdb88..d583d6d 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -52,6 +52,8 @@ struct mtd_part {
  */
 #define PART(x)  ((struct mtd_part *)(x))
 
+static int mtd_parse_typed_part(struct mtd_part *slave,
+				enum mtd_partition_type type);
 
 /*
  * MTD methods which simply translate the effective address and pass through
@@ -663,7 +665,9 @@ int add_mtd_partitions(struct mtd_info *master,
 	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
 	for (i = 0; i < nbparts; i++) {
-		slave = allocate_partition(master, parts + i, i, cur_offset);
+		const struct mtd_partition *part = parts + i;
+
+		slave = allocate_partition(master, part, i, cur_offset);
 		if (IS_ERR(slave))
 			return PTR_ERR(slave);
 
@@ -673,6 +677,8 @@ int add_mtd_partitions(struct mtd_info *master,
 
 		add_mtd_device(&slave->mtd);
 		mtd_add_partition_attrs(slave);
+		if (part->type)
+			mtd_parse_typed_part(slave, part->type);
 
 		cur_offset = slave->offset + slave->mtd.size;
 	}
@@ -775,6 +781,72 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
 	return ret;
 }
 
+int mtd_parse_typed_partitions(struct mtd_info *slave,
+			       enum mtd_partition_type type,
+			       struct mtd_partition **pparts,
+			       struct mtd_part_parser_data *data)
+{
+	struct mtd_part_parser *p = NULL;
+	bool found;
+	int ret = 0;
+
+	while (1) {
+		found = false;
+
+		spin_lock(&part_parser_lock);
+		p = list_prepare_entry(p, &part_parsers, list);
+		list_for_each_entry_continue(p, &part_parsers, list) {
+			if (p->type == type && try_module_get(p->owner)) {
+				found = true;
+				break;
+			}
+		}
+		spin_unlock(&part_parser_lock);
+
+		if (!found)
+			break;
+
+		ret = (*p->parse_fn)(slave, pparts, data);
+		if (ret > 0) {
+			put_partition_parser(p);
+			pr_notice("%d %s partitions found on MTD device %s\n",
+				  ret, p->name, slave->name);
+			break;
+		}
+
+		put_partition_parser(p);
+	}
+
+	return ret;
+}
+
+static int mtd_parse_typed_part(struct mtd_part *slave,
+				enum mtd_partition_type type)
+{
+	struct mtd_partition *parts;
+	int nr_parts;
+	int i;
+
+	nr_parts = mtd_parse_typed_partitions(&slave->mtd, type, &parts, NULL);
+	if (nr_parts <= 0)
+		return nr_parts;
+
+	if (WARN_ON(!parts))
+		return 0;
+
+	for (i = 0; i < nr_parts; i++) {
+		/* adjust partition offsets */
+		parts[i].offset += slave->offset;
+
+		mtd_add_partition(slave->master, parts[i].name, parts[i].offset,
+				  parts[i].size);
+	}
+
+	kfree(parts);
+
+	return nr_parts;
+}
+
 int mtd_is_partition(const struct mtd_info *mtd)
 {
 	struct mtd_part *part;
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 6a35e6d..4d2432a 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -11,6 +11,9 @@
 
 #include <linux/types.h>
 
+enum mtd_partition_type {
+	MTD_PARTITION_TYPE_GENERIC = 0,
+};
 
 /*
  * Partition definition structure:
@@ -20,6 +23,8 @@
  *
  * For each partition, these fields are available:
  * name: string that will be used to label the partition's MTD device.
+ * type: some partitions may require specific handling like splitting them into
+ *	into subpartitions (e.g. firmware which may contain kernel and rootfs)
  * 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 +43,7 @@
 
 struct mtd_partition {
 	const char *name;		/* identifier string */
+	enum mtd_partition_type type;	/* partition type */
 	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 */
@@ -72,6 +78,7 @@ struct mtd_part_parser {
 	struct list_head list;
 	struct module *owner;
 	const char *name;
+	enum mtd_partition_type type;
 	int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
 			struct mtd_part_parser_data *);
 };
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH PROOF 2/1] mtd: add TRX parser splitting firmware partition
  2015-05-18 12:34 [PATCH 1/1] mtd: add support for typed parsers splitting partitions Rafał Miłecki
@ 2015-05-18 12:34 ` Rafał Miłecki
  2015-05-20 18:45 ` [PATCH 1/1] mtd: add support for typed parsers splitting partitions Brian Norris
  2015-05-26  5:18 ` [PATCH V2 " Rafał Miłecki
  2 siblings, 0 replies; 6+ messages in thread
From: Rafał Miłecki @ 2015-05-18 12:34 UTC (permalink / raw)
  To: Brian Norris, linux-mtd
  Cc: Gabor Juhos, Felix Fietkau, Rafał Miłecki, Hauke Mehrtens

This is just a proof of concept, not clean enough for being applied.

It results in creating subpartitions in a following way:
[    1.890000] Creating 3 MTD partitions on "bcm47xxsflash":                                                                                        
[    1.900000] 0x000000000000-0x000000020000 : "boot"                                                                                               
[    1.900000] 0x000000020000-0x0000007f0000 : "firmware"                                                                                           
[    1.940000] 3 trx_parser partitions found on MTD device firmware
[    1.980000] 0x00000002001c-0x00000002090c : "loader"
[    2.000000] 0x00000002090c-0x00000013b800 : "linux"
[    2.030000] 0x00000013b800-0x0000007f0000 : "rootfs"
[    2.060000] 0x0000007f0000-0x000000800000 : "nvram"

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/mtd/Makefile           |   1 +
 drivers/mtd/mtdsplit_trx.c     | 124 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/partitions.h |   1 +
 3 files changed, 126 insertions(+)
 create mode 100644 drivers/mtd/mtdsplit_trx.c

diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 99bb9a1..c43742f 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
 obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o
+obj-y				+= mtdsplit_trx.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o
diff --git a/drivers/mtd/mtdsplit_trx.c b/drivers/mtd/mtdsplit_trx.c
new file mode 100644
index 0000000..d075cc0e
--- /dev/null
+++ b/drivers/mtd/mtdsplit_trx.c
@@ -0,0 +1,124 @@
+/*
+ * TRX subpartitioning
+ *
+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#define TRX_PARSER_MAX_PARTS		4
+#define TRX_MAGIC			0x30524448
+
+struct trx_header {
+	uint32_t magic;
+	uint32_t length;
+	uint32_t crc32;
+	uint16_t flags;
+	uint16_t version;
+	uint32_t offset[3];
+} __packed;
+
+static void trx_parser_add_part(struct mtd_partition *part, char *name,
+				 u64 offset, uint32_t mask_flags)
+{
+	part->name = name;
+	part->offset = offset;
+	part->mask_flags = mask_flags;
+}
+
+static int trx_parser_parse(struct mtd_info *master,
+			    struct mtd_partition **pparts,
+			    struct mtd_part_parser_data *data)
+{
+	struct mtd_partition *parts;
+	struct trx_header trx;
+	size_t bytes_read;
+	int curr_part = 0;
+	int ret, i;
+
+	/* Alloc */
+	parts = kzalloc(sizeof(struct mtd_partition) * TRX_PARSER_MAX_PARTS,
+			GFP_KERNEL);
+	if (!parts)
+		return -ENOMEM;
+
+	/* Read beginning of the block */
+	ret = mtd_read(master, 0, sizeof(trx), &bytes_read, (uint8_t *)&trx);
+	if (ret < 0 || bytes_read != sizeof(trx)) {
+		kfree(parts);
+		return -EIO;
+	}
+
+	/* TRX */
+	if (le32_to_cpu(trx.magic) != TRX_MAGIC) {
+		kfree(parts);
+		return -EIO;
+	}
+
+	i = 0;
+	/* We have LZMA loader if offset[2] points to sth */
+	if (trx.offset[2]) {
+		trx_parser_add_part(&parts[curr_part++], "loader",
+				    trx.offset[i], 0);
+		i++;
+	}
+
+	if (trx.offset[i]) {
+		trx_parser_add_part(&parts[curr_part++], "linux",
+				    trx.offset[i], 0);
+		i++;
+	}
+
+	if (trx.offset[i]) {
+		trx_parser_add_part(&parts[curr_part++], "rootfs",
+				    trx.offset[i], 0);
+		i++;
+	}
+
+	/*
+	 * Assume that partitions end at the beginning of the one they are
+	 * followed by.
+	 */
+	for (i = 0; i < curr_part; i++) {
+		u64 next_part_offset = (i < curr_part - 1) ?
+				       parts[i + 1].offset : master->size;
+
+		parts[i].size = next_part_offset - parts[i].offset;
+	}
+
+	*pparts = parts;
+	return curr_part;
+};
+
+static struct mtd_part_parser trx_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = trx_parser_parse,
+	.name = "trx_parser",
+	.type = MTD_PARTITION_TYPE_FIRMWARE,
+};
+
+static int __init trx_parser_init(void)
+{
+	register_mtd_parser(&trx_parser);
+	return 0;
+}
+
+static void __exit trx_parser_exit(void)
+{
+	deregister_mtd_parser(&trx_parser);
+}
+
+module_init(trx_parser_init);
+module_exit(trx_parser_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TRX subpartitioning");
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 4d2432a..295e417 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -13,6 +13,7 @@
 
 enum mtd_partition_type {
 	MTD_PARTITION_TYPE_GENERIC = 0,
+	MTD_PARTITION_TYPE_FIRMWARE,
 };
 
 /*
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] mtd: add support for typed parsers splitting partitions
  2015-05-18 12:34 [PATCH 1/1] mtd: add support for typed parsers splitting partitions Rafał Miłecki
  2015-05-18 12:34 ` [PATCH PROOF 2/1] mtd: add TRX parser splitting firmware partition Rafał Miłecki
@ 2015-05-20 18:45 ` Brian Norris
  2015-05-21  7:15   ` Rafał Miłecki
  2015-05-26  5:18 ` [PATCH V2 " Rafał Miłecki
  2 siblings, 1 reply; 6+ messages in thread
From: Brian Norris @ 2015-05-20 18:45 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Gabor Juhos, Felix Fietkau, linux-mtd, Hauke Mehrtens

I haven't reviewed this entirely yet, but my build tests complained:

On Mon, May 18, 2015 at 02:34:53PM +0200, Rafał Miłecki wrote:
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index cafdb88..d583d6d 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
[...]
> @@ -775,6 +781,72 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
>  	return ret;
>  }
>  
> +int mtd_parse_typed_partitions(struct mtd_info *slave,
> +			       enum mtd_partition_type type,
> +			       struct mtd_partition **pparts,
> +			       struct mtd_part_parser_data *data)

drivers/mtd/mtdpart.c:784:5: warning: no previous prototype for ‘mtd_parse_typed_partitions’ [-Wmissing-prototypes]
 int mtd_parse_typed_partitions(struct mtd_info *slave,
     ^
drivers/mtd/mtdpart.c:784:5: warning: symbol 'mtd_parse_typed_partitions' was not declared. Should it be static? [sparse]

> +{
> +	struct mtd_part_parser *p = NULL;
> +	bool found;
> +	int ret = 0;
> +
> +	while (1) {

[...]

Brian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] mtd: add support for typed parsers splitting partitions
  2015-05-20 18:45 ` [PATCH 1/1] mtd: add support for typed parsers splitting partitions Brian Norris
@ 2015-05-21  7:15   ` Rafał Miłecki
  0 siblings, 0 replies; 6+ messages in thread
From: Rafał Miłecki @ 2015-05-21  7:15 UTC (permalink / raw)
  To: Brian Norris; +Cc: Gabor Juhos, Felix Fietkau, linux-mtd, Hauke Mehrtens

On 20 May 2015 at 20:45, Brian Norris <computersforpeace@gmail.com> wrote:
> I haven't reviewed this entirely yet, but my build tests complained:
>
> On Mon, May 18, 2015 at 02:34:53PM +0200, Rafał Miłecki wrote:
>> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
>> index cafdb88..d583d6d 100644
>> --- a/drivers/mtd/mtdpart.c
>> +++ b/drivers/mtd/mtdpart.c
> [...]
>> @@ -775,6 +781,72 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
>>       return ret;
>>  }
>>
>> +int mtd_parse_typed_partitions(struct mtd_info *slave,
>> +                            enum mtd_partition_type type,
>> +                            struct mtd_partition **pparts,
>> +                            struct mtd_part_parser_data *data)
>
> drivers/mtd/mtdpart.c:784:5: warning: no previous prototype for ‘mtd_parse_typed_partitions’ [-Wmissing-prototypes]
>  int mtd_parse_typed_partitions(struct mtd_info *slave,
>      ^
> drivers/mtd/mtdpart.c:784:5: warning: symbol 'mtd_parse_typed_partitions' was not declared. Should it be static? [sparse]

Sure, I'll fix that, just let me wait to see if there are any other
comments to this patch.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH V2 1/1] mtd: add support for typed parsers splitting partitions
  2015-05-18 12:34 [PATCH 1/1] mtd: add support for typed parsers splitting partitions Rafał Miłecki
  2015-05-18 12:34 ` [PATCH PROOF 2/1] mtd: add TRX parser splitting firmware partition Rafał Miłecki
  2015-05-20 18:45 ` [PATCH 1/1] mtd: add support for typed parsers splitting partitions Brian Norris
@ 2015-05-26  5:18 ` Rafał Miłecki
  2015-05-29 16:15   ` Hauke Mehrtens
  2 siblings, 1 reply; 6+ messages in thread
From: Rafał Miłecki @ 2015-05-26  5:18 UTC (permalink / raw)
  To: Brian Norris, linux-mtd
  Cc: Gabor Juhos, Felix Fietkau, Rafał Miłecki, Hauke Mehrtens

This extends MTD architecture by introducing partition types which allow
handling selected (marked) partitions in a specific way. There are some
types of partitions that require splitting, e.g. firmware containers.
On some devices we want to have "firmware" container partition (for easy
firmware upgrade) as well as subpartitions (e.g. to use rootfs).

Thanks to this change we will also avoid code duplication across various
drivers/architectures. It will allow multiple drivers to use the same
parser just by setting a proper type.

An example use case for this can be TRX firmware format parser. This
format contains 2-4 partitions including kernel and rootfs. It is used
by many Broadcom devices on various platforms (bcm47xx, bcm53xx, ath79).

When partition with a specified type is created we loop over registered
parsers running ones with a matching type. When one returns list of new
partitions we create them.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
V2: Add missing "static" for mtd_parse_typed_partitions
---
 drivers/mtd/mtdpart.c          | 74 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/mtd/partitions.h |  7 ++++
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index cafdb88..020c6b7 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -52,6 +52,8 @@ struct mtd_part {
  */
 #define PART(x)  ((struct mtd_part *)(x))
 
+static int mtd_parse_typed_part(struct mtd_part *slave,
+				enum mtd_partition_type type);
 
 /*
  * MTD methods which simply translate the effective address and pass through
@@ -663,7 +665,9 @@ int add_mtd_partitions(struct mtd_info *master,
 	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
 	for (i = 0; i < nbparts; i++) {
-		slave = allocate_partition(master, parts + i, i, cur_offset);
+		const struct mtd_partition *part = parts + i;
+
+		slave = allocate_partition(master, part, i, cur_offset);
 		if (IS_ERR(slave))
 			return PTR_ERR(slave);
 
@@ -673,6 +677,8 @@ int add_mtd_partitions(struct mtd_info *master,
 
 		add_mtd_device(&slave->mtd);
 		mtd_add_partition_attrs(slave);
+		if (part->type)
+			mtd_parse_typed_part(slave, part->type);
 
 		cur_offset = slave->offset + slave->mtd.size;
 	}
@@ -775,6 +781,72 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
 	return ret;
 }
 
+static int mtd_parse_typed_partitions(struct mtd_info *slave,
+				      enum mtd_partition_type type,
+				      struct mtd_partition **pparts,
+				      struct mtd_part_parser_data *data)
+{
+	struct mtd_part_parser *p = NULL;
+	bool found;
+	int ret = 0;
+
+	while (1) {
+		found = false;
+
+		spin_lock(&part_parser_lock);
+		p = list_prepare_entry(p, &part_parsers, list);
+		list_for_each_entry_continue(p, &part_parsers, list) {
+			if (p->type == type && try_module_get(p->owner)) {
+				found = true;
+				break;
+			}
+		}
+		spin_unlock(&part_parser_lock);
+
+		if (!found)
+			break;
+
+		ret = (*p->parse_fn)(slave, pparts, data);
+		if (ret > 0) {
+			put_partition_parser(p);
+			pr_notice("%d %s partitions found on MTD device %s\n",
+				  ret, p->name, slave->name);
+			break;
+		}
+
+		put_partition_parser(p);
+	}
+
+	return ret;
+}
+
+static int mtd_parse_typed_part(struct mtd_part *slave,
+				enum mtd_partition_type type)
+{
+	struct mtd_partition *parts;
+	int nr_parts;
+	int i;
+
+	nr_parts = mtd_parse_typed_partitions(&slave->mtd, type, &parts, NULL);
+	if (nr_parts <= 0)
+		return nr_parts;
+
+	if (WARN_ON(!parts))
+		return 0;
+
+	for (i = 0; i < nr_parts; i++) {
+		/* adjust partition offsets */
+		parts[i].offset += slave->offset;
+
+		mtd_add_partition(slave->master, parts[i].name, parts[i].offset,
+				  parts[i].size);
+	}
+
+	kfree(parts);
+
+	return nr_parts;
+}
+
 int mtd_is_partition(const struct mtd_info *mtd)
 {
 	struct mtd_part *part;
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 6a35e6d..4d2432a 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -11,6 +11,9 @@
 
 #include <linux/types.h>
 
+enum mtd_partition_type {
+	MTD_PARTITION_TYPE_GENERIC = 0,
+};
 
 /*
  * Partition definition structure:
@@ -20,6 +23,8 @@
  *
  * For each partition, these fields are available:
  * name: string that will be used to label the partition's MTD device.
+ * type: some partitions may require specific handling like splitting them into
+ *	into subpartitions (e.g. firmware which may contain kernel and rootfs)
  * 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 +43,7 @@
 
 struct mtd_partition {
 	const char *name;		/* identifier string */
+	enum mtd_partition_type type;	/* partition type */
 	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 */
@@ -72,6 +78,7 @@ struct mtd_part_parser {
 	struct list_head list;
 	struct module *owner;
 	const char *name;
+	enum mtd_partition_type type;
 	int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
 			struct mtd_part_parser_data *);
 };
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH V2 1/1] mtd: add support for typed parsers splitting partitions
  2015-05-26  5:18 ` [PATCH V2 " Rafał Miłecki
@ 2015-05-29 16:15   ` Hauke Mehrtens
  0 siblings, 0 replies; 6+ messages in thread
From: Hauke Mehrtens @ 2015-05-29 16:15 UTC (permalink / raw)
  To: Rafał Miłecki, Brian Norris, linux-mtd
  Cc: Gabor Juhos, Felix Fietkau



On 05/26/2015 07:18 AM, Rafał Miłecki wrote:
> This extends MTD architecture by introducing partition types which allow
> handling selected (marked) partitions in a specific way. There are some
> types of partitions that require splitting, e.g. firmware containers.
> On some devices we want to have "firmware" container partition (for easy
> firmware upgrade) as well as subpartitions (e.g. to use rootfs).
> 
> Thanks to this change we will also avoid code duplication across various
> drivers/architectures. It will allow multiple drivers to use the same
> parser just by setting a proper type.
> 
> An example use case for this can be TRX firmware format parser. This
> format contains 2-4 partitions including kernel and rootfs. It is used
> by many Broadcom devices on various platforms (bcm47xx, bcm53xx, ath79).
> 
> When partition with a specified type is created we loop over registered
> parsers running ones with a matching type. When one returns list of new
> partitions we create them.

I liked Jonas interface better, see
http://www.spinics.net/lists/devicetree/msg80451.html

Instead of adding a new type why not make it possible to say that a
specific partition should be parsed with an other partition parser. Then
the sub partition parser gets the range and can run in that space. This
way we can reuse the old interface, at least I hope so and also make it
possible to define new combination just in device tree.

I would not use an enum for this, but a string, so it can easily be
provided through device tree. This string should be the partition parer
name.

Then the partition parer like bcm47xxpart must take the decision if an
other partition parser should be called.

> 
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> ---
> V2: Add missing "static" for mtd_parse_typed_partitions
> ---
>  drivers/mtd/mtdpart.c          | 74 +++++++++++++++++++++++++++++++++++++++++-
>  include/linux/mtd/partitions.h |  7 ++++
>  2 files changed, 80 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index cafdb88..020c6b7 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -52,6 +52,8 @@ struct mtd_part {
>   */
>  #define PART(x)  ((struct mtd_part *)(x))
>  
> +static int mtd_parse_typed_part(struct mtd_part *slave,
> +				enum mtd_partition_type type);

If you change the ordering you can avoid this forward declaration.

>  
>  /*
>   * MTD methods which simply translate the effective address and pass through
> @@ -663,7 +665,9 @@ int add_mtd_partitions(struct mtd_info *master,
>  	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
>  
>  	for (i = 0; i < nbparts; i++) {
> -		slave = allocate_partition(master, parts + i, i, cur_offset);
> +		const struct mtd_partition *part = parts + i;
> +
> +		slave = allocate_partition(master, part, i, cur_offset);
>  		if (IS_ERR(slave))
>  			return PTR_ERR(slave);
>  
> @@ -673,6 +677,8 @@ int add_mtd_partitions(struct mtd_info *master,
>  
>  		add_mtd_device(&slave->mtd);
>  		mtd_add_partition_attrs(slave);
> +		if (part->type)
> +			mtd_parse_typed_part(slave, part->type);
>  
>  		cur_offset = slave->offset + slave->mtd.size;
>  	}
> @@ -775,6 +781,72 @@ int parse_mtd_partitions(struct mtd_info *master, const char *const *types,
>  	return ret;
>  }
>  
> +static int mtd_parse_typed_partitions(struct mtd_info *slave,
> +				      enum mtd_partition_type type,
> +				      struct mtd_partition **pparts,
> +				      struct mtd_part_parser_data *data)
> +{
> +	struct mtd_part_parser *p = NULL;
> +	bool found;
> +	int ret = 0;
> +
> +	while (1) {
> +		found = false;
> +
> +		spin_lock(&part_parser_lock);
> +		p = list_prepare_entry(p, &part_parsers, list);
> +		list_for_each_entry_continue(p, &part_parsers, list) {
> +			if (p->type == type && try_module_get(p->owner)) {
> +				found = true;
> +				break;
> +			}
> +		}
> +		spin_unlock(&part_parser_lock);
> +
> +		if (!found)
> +			break;
> +
> +		ret = (*p->parse_fn)(slave, pparts, data);
> +		if (ret > 0) {
> +			put_partition_parser(p);
> +			pr_notice("%d %s partitions found on MTD device %s\n",
> +				  ret, p->name, slave->name);
> +			break;
> +		}
> +
> +		put_partition_parser(p);
> +	}
> +
> +	return ret;
> +}
> +
> +static int mtd_parse_typed_part(struct mtd_part *slave,
> +				enum mtd_partition_type type)
> +{
> +	struct mtd_partition *parts;
> +	int nr_parts;
> +	int i;
> +
> +	nr_parts = mtd_parse_typed_partitions(&slave->mtd, type, &parts, NULL);
> +	if (nr_parts <= 0)
> +		return nr_parts;
> +
> +	if (WARN_ON(!parts))
> +		return 0;
> +
> +	for (i = 0; i < nr_parts; i++) {
> +		/* adjust partition offsets */
> +		parts[i].offset += slave->offset;
> +
> +		mtd_add_partition(slave->master, parts[i].name, parts[i].offset,
> +				  parts[i].size);
> +	}
> +
> +	kfree(parts);
> +
> +	return nr_parts;
> +}
> +
>  int mtd_is_partition(const struct mtd_info *mtd)
>  {
>  	struct mtd_part *part;
> diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
> index 6a35e6d..4d2432a 100644
> --- a/include/linux/mtd/partitions.h
> +++ b/include/linux/mtd/partitions.h
> @@ -11,6 +11,9 @@
>  
>  #include <linux/types.h>
>  
> +enum mtd_partition_type {
> +	MTD_PARTITION_TYPE_GENERIC = 0,
> +};
>  
>  /*
>   * Partition definition structure:
> @@ -20,6 +23,8 @@
>   *
>   * For each partition, these fields are available:
>   * name: string that will be used to label the partition's MTD device.
> + * type: some partitions may require specific handling like splitting them into
> + *	into subpartitions (e.g. firmware which may contain kernel and rootfs)
>   * 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 +43,7 @@
>  
>  struct mtd_partition {
>  	const char *name;		/* identifier string */
> +	enum mtd_partition_type type;	/* partition type */
>  	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 */
> @@ -72,6 +78,7 @@ struct mtd_part_parser {
>  	struct list_head list;
>  	struct module *owner;
>  	const char *name;
> +	enum mtd_partition_type type;
>  	int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
>  			struct mtd_part_parser_data *);
>  };
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-05-29 16:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-18 12:34 [PATCH 1/1] mtd: add support for typed parsers splitting partitions Rafał Miłecki
2015-05-18 12:34 ` [PATCH PROOF 2/1] mtd: add TRX parser splitting firmware partition Rafał Miłecki
2015-05-20 18:45 ` [PATCH 1/1] mtd: add support for typed parsers splitting partitions Brian Norris
2015-05-21  7:15   ` Rafał Miłecki
2015-05-26  5:18 ` [PATCH V2 " Rafał Miłecki
2015-05-29 16:15   ` Hauke Mehrtens

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.