Message ID | 20170221124002.585-1-zajec5@gmail.com |
---|---|
State | Changes Requested |
Headers | show |
On 02/21/2017 01:40 PM, Rafał Miłecki wrote: > From: Rafał Miłecki <rafal@milecki.pl> > > Some devices have partitions that are kind of containers with extra > subpartitions / volumes instead of e.g. simple filesystem data. To > support such cases we need to first create normal flash 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, uImage uImage is file format, not partition type. It's just a blob of data (usually kernel) with small header, I don't think we should represent the content of it as a partition. > , WRGG and 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 partition format > and trying to use a proper parser when needed. 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 format 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 <rafal@milecki.pl> > --- > V2: A totally rebased & refreshed version. > --- > drivers/mtd/mtdpart.c | 38 ++++++++++++++++++++++++++++++++++++++ > include/linux/mtd/partitions.h | 7 +++++++ > 2 files changed, 45 insertions(+) > > diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c > index ea5e5307f667..9a40c3ea384b 100644 > --- a/drivers/mtd/mtdpart.c > +++ b/drivers/mtd/mtdpart.c > @@ -363,6 +363,42 @@ static inline void free_partition(struct mtd_part *p) > kfree(p); > } > > +/** > + * mtd_parse_part - parse MTD partition with a matching parser > + * > + * Some partitions use a specific format to describe contained subpartitions > + * (volumes). This function tries to use a proper parser for a given format and > + * registers found (sub)partitions. > + */ > +static int mtd_parse_part(struct mtd_part *slave, const char *format) > +{ > + struct mtd_partitions parsed; > + const char *probes[2]; > + int i; > + int err; > + > + probes[0] = format; /* Use parser with name matching the format */ > + probes[1] = NULL; /* End of parsers */ > + err = parse_mtd_partitions(&slave->mtd, probes, &parsed, NULL); > + if (err) > + return err; > + else if (!parsed.nr_parts) > + return -ENOENT; > + > + for (i = 0; i < parsed.nr_parts; i++) { > + struct mtd_partition *part; > + > + part = (struct mtd_partition *)&parsed.parts[i]; > + part->offset += slave->offset; > + } > + > + err = add_mtd_partitions(slave->master, parsed.parts, parsed.nr_parts); > + > + mtd_part_parser_cleanup(&parsed); > + > + return err; > +} > + > /* > * This function unregisters and destroy all slave MTD objects which are > * attached to the given master MTD object. > @@ -724,6 +760,8 @@ int add_mtd_partitions(struct mtd_info *master, > > add_mtd_device(&slave->mtd); > mtd_add_partition_attrs(slave); > + if (parts[i].format) > + mtd_parse_part(slave, parts[i].format); > > cur_offset = slave->offset + slave->mtd.size; > } > diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h > index 06df1e06b6e0..2787e76c030f 100644 > --- 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. > + * format: 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. This property describes partition > + * format and allows MTD core to call a proper parser. > * 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 *format; /* partition format */ > 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 */ >
On 27 February 2017 at 10:36, Marek Vasut <marek.vasut@gmail.com> wrote: > On 02/21/2017 01:40 PM, Rafał Miłecki wrote: >> From: Rafał Miłecki <rafal@milecki.pl> >> >> Some devices have partitions that are kind of containers with extra >> subpartitions / volumes instead of e.g. simple filesystem data. To >> support such cases we need to first create normal flash 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, uImage > > uImage is file format, not partition type. It's just a blob of data > (usually kernel) with small header, I don't think we should represent > the content of it as a partition. You are correct, this isn't any standard container with subpartitions/volumes. This shouldn't be listed in this commit message, sorry. I'll drop it in V2.
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index ea5e5307f667..9a40c3ea384b 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -363,6 +363,42 @@ static inline void free_partition(struct mtd_part *p) kfree(p); } +/** + * mtd_parse_part - parse MTD partition with a matching parser + * + * Some partitions use a specific format to describe contained subpartitions + * (volumes). This function tries to use a proper parser for a given format and + * registers found (sub)partitions. + */ +static int mtd_parse_part(struct mtd_part *slave, const char *format) +{ + struct mtd_partitions parsed; + const char *probes[2]; + int i; + int err; + + probes[0] = format; /* Use parser with name matching the format */ + probes[1] = NULL; /* End of parsers */ + err = parse_mtd_partitions(&slave->mtd, probes, &parsed, NULL); + if (err) + return err; + else if (!parsed.nr_parts) + return -ENOENT; + + for (i = 0; i < parsed.nr_parts; i++) { + struct mtd_partition *part; + + part = (struct mtd_partition *)&parsed.parts[i]; + part->offset += slave->offset; + } + + err = add_mtd_partitions(slave->master, parsed.parts, parsed.nr_parts); + + mtd_part_parser_cleanup(&parsed); + + return err; +} + /* * This function unregisters and destroy all slave MTD objects which are * attached to the given master MTD object. @@ -724,6 +760,8 @@ int add_mtd_partitions(struct mtd_info *master, add_mtd_device(&slave->mtd); mtd_add_partition_attrs(slave); + if (parts[i].format) + mtd_parse_part(slave, parts[i].format); cur_offset = slave->offset + slave->mtd.size; } diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 06df1e06b6e0..2787e76c030f 100644 --- 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. + * format: 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. This property describes partition + * format and allows MTD core to call a proper parser. * 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 *format; /* partition format */ 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 */