Currently, a fill-up partition (indicated by '-') must be the last
partition, and no other partitions can go after it.  Change the
cmdlinepart parsing code to allow a fill-up partition at any point.
This is useful, for example, if you want to reserve a partition at the
end of the flash where the bad block table will go.

Signed-off-by: Ben Shelton <ben.shel...@ni.com>
---
 drivers/mtd/cmdlinepart.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index c850300..2d0eda2 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -97,6 +97,7 @@ static struct mtd_partition * newpart(char *s,
                                      char **retptr,
                                      int *num_parts,
                                      int this_part,
+                                     int size_remaining_found,
                                      unsigned char **extra_mem_ptr,
                                      int extra_mem_size)
 {
@@ -110,9 +111,16 @@ static struct mtd_partition * newpart(char *s,
 
        /* fetch the partition size */
        if (*s == '-') {
+               if (size_remaining_found) {
+                       printk(KERN_ERR ERRP
+                              "more than one '-' partition specified\n");
+                       return ERR_PTR(-EINVAL);
+               }
+
                /* assign all remaining space to this partition */
                size = SIZE_REMAINING;
                s++;
+               size_remaining_found = 1;
        } else {
                size = memparse(s, &s);
                if (size < PAGE_SIZE) {
@@ -169,13 +177,10 @@ static struct mtd_partition * newpart(char *s,
 
        /* test if more partitions are following */
        if (*s == ',') {
-               if (size == SIZE_REMAINING) {
-                       printk(KERN_ERR ERRP "no partitions allowed after a 
fill-up partition\n");
-                       return ERR_PTR(-EINVAL);
-               }
                /* more partitions follow, parse them */
                parts = newpart(s + 1, &s, num_parts, this_part + 1,
-                               &extra_mem, extra_mem_size);
+                               size_remaining_found, &extra_mem,
+                               extra_mem_size);
                if (IS_ERR(parts))
                        return parts;
        } else {
@@ -252,6 +257,7 @@ static int mtdpart_setup_real(char *s)
                                &s,             /* out: updated cmdline ptr */
                                &num_parts,     /* out: number of parts */
                                0,              /* first partition */
+                               0,              /* size_remaining not found */
                                (unsigned char**)&this_mtd, /* out: extra mem */
                                mtd_id_len + 1 + sizeof(*this_mtd) +
                                sizeof(void*)-1 /*alignment*/);
@@ -313,6 +319,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
        int i, err;
        struct cmdline_mtd_partition *part;
        const char *mtd_id = master->name;
+       int sr_part_num = -1;
 
        /* parse command line */
        if (!cmdline_parsed) {
@@ -339,8 +346,10 @@ static int parse_cmdline_partitions(struct mtd_info 
*master,
                else
                        offset = part->parts[i].offset;
 
-               if (part->parts[i].size == SIZE_REMAINING)
-                       part->parts[i].size = master->size - offset;
+               if (part->parts[i].size == SIZE_REMAINING) {
+                       sr_part_num = i;
+                       continue;
+               }
 
                if (offset + part->parts[i].size > master->size) {
                        printk(KERN_WARNING ERRP
@@ -361,6 +370,16 @@ static int parse_cmdline_partitions(struct mtd_info 
*master,
                }
        }
 
+       /* if a partition was marked as SIZE_REMAINING */
+       if (sr_part_num != -1) {
+               /* fix up the size of the SIZE_REMAINING partition */
+               part->parts[sr_part_num].size = master->size - offset;
+
+               /* fix up the offsets of the subsequent partitions */
+               for (i = (sr_part_num + 1); i < part->num_parts; i++)
+                       part->parts[i].offset += part->parts[sr_part_num].size;
+       }
+
        *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts,
                          GFP_KERNEL);
        if (!*pparts)
-- 
2.4.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to