a28ee316fac74137293d8b7251783438b784ea04
[librecmc/librecmc.git] /
1 From 1a0915be192606fee64830b9c5d70b7ed59426b6 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Wed, 21 Jun 2017 08:26:46 +0200
4 Subject: [PATCH] mtd: partitions: add support for partition parsers
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Some devices have partitions that are kind of containers with extra
10 subpartitions / volumes instead of e.g. a simple filesystem data. To
11 support such cases we need to first create normal flash device
12 partitions and then take care of these special ones.
13
14 It's very common case for home routers. Depending on the vendor there
15 are formats like TRX, Seama, TP-Link, WRGG & more. All of them are used
16 to embed few partitions into a single one / single firmware file.
17
18 Ideally all vendors would use some well documented / standardized format
19 like UBI (and some probably start doing so), but there are still
20 countless devices on the market using these poor vendor specific
21 formats.
22
23 This patch extends MTD subsystem by allowing to specify list of parsers
24 that should be tried for a given partition. Supporting such poor formats
25 is highly unlikely to be the top priority so these changes try to
26 minimize maintenance cost to the minimum. It reuses existing code for
27 these new parsers and just adds a one property and one new function.
28
29 This implementation requires setting partition parsers in a flash
30 parser. A proper change of bcm47xxpart will follow and in the future we
31 will hopefully also find a solution for doing it with ofpart
32 ("fixed-partitions").
33
34 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
35 Signed-off-by: Brian Norris <computersforpeace@gmail.com>
36 ---
37  drivers/mtd/mtdpart.c          | 31 +++++++++++++++++++++++++++++++
38  include/linux/mtd/partitions.h |  7 +++++++
39  2 files changed, 38 insertions(+)
40
41 --- a/drivers/mtd/mtdpart.c
42 +++ b/drivers/mtd/mtdpart.c
43 @@ -369,6 +369,35 @@ static inline void free_partition(struct
44         kfree(p);
45  }
46  
47 +/**
48 + * mtd_parse_part - parse MTD partition looking for subpartitions
49 + *
50 + * @slave: part that is supposed to be a container and should be parsed
51 + * @types: NULL-terminated array with names of partition parsers to try
52 + *
53 + * Some partitions are kind of containers with extra subpartitions (volumes).
54 + * There can be various formats of such containers. This function tries to use
55 + * specified parsers to analyze given partition and registers found
56 + * subpartitions on success.
57 + */
58 +static int mtd_parse_part(struct mtd_part *slave, const char *const *types)
59 +{
60 +       struct mtd_partitions parsed;
61 +       int err;
62 +
63 +       err = parse_mtd_partitions(&slave->mtd, types, &parsed, NULL);
64 +       if (err)
65 +               return err;
66 +       else if (!parsed.nr_parts)
67 +               return -ENOENT;
68 +
69 +       err = add_mtd_partitions(&slave->mtd, parsed.parts, parsed.nr_parts);
70 +
71 +       mtd_part_parser_cleanup(&parsed);
72 +
73 +       return err;
74 +}
75 +
76  static struct mtd_part *allocate_partition(struct mtd_info *parent,
77                         const struct mtd_partition *part, int partno,
78                         uint64_t cur_offset)
79 @@ -758,6 +787,8 @@ int add_mtd_partitions(struct mtd_info *
80  
81                 add_mtd_device(&slave->mtd);
82                 mtd_add_partition_attrs(slave);
83 +               if (parts[i].types)
84 +                       mtd_parse_part(slave, parts[i].types);
85  
86                 cur_offset = slave->offset + slave->mtd.size;
87         }
88 --- a/include/linux/mtd/partitions.h
89 +++ b/include/linux/mtd/partitions.h
90 @@ -20,6 +20,12 @@
91   *
92   * For each partition, these fields are available:
93   * name: string that will be used to label the partition's MTD device.
94 + * types: some partitions can be containers using specific format to describe
95 + *     embedded subpartitions / volumes. E.g. many home routers use "firmware"
96 + *     partition that contains at least kernel and rootfs. In such case an
97 + *     extra parser is needed that will detect these dynamic partitions and
98 + *     report them to the MTD subsystem. If set this property stores an array
99 + *     of parser names to use when looking for subpartitions.
100   * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
101   *     will extend to the end of the master MTD device.
102   * offset: absolute starting position within the master MTD device; if
103 @@ -38,6 +44,7 @@
104  
105  struct mtd_partition {
106         const char *name;               /* identifier string */
107 +       const char *const *types;       /* names of parsers to use if any */
108         uint64_t size;                  /* partition size */
109         uint64_t offset;                /* offset within the master MTD space */
110         uint32_t mask_flags;            /* master MTD flags to mask out for this partition */