[U-Boot] [PATCH v4 3/4] mtdparts: add new sub-command "spread"

Ben Gardiner bengardiner at nanometrics.ca
Mon Aug 9 22:43:59 CEST 2010


This patch introduces the 'spread' sub-command of the mtdparts command.
This command will modify the existing mtdparts variable by increasing
the size of the partitions such that 1) each partition's net size is at
least as large as the size specified in the mtdparts variable and 2)
each partition starts on a good block.

The new subcommand is implemented by iterating over the mtd device
partitions and collecting a bad blocks count in each -- including any
trailing bad blocks -- and then modifying that partitions's part_info
structure and checking if the modification affects the next partition.

This patch is based on a port of the 'dynnamic partitions' feature by
Harald Welte <laforge at gnumonks.org>; ported from commit
e05835df019027391f58f9d8ce5e1257d6924798 of
git://git.openmoko.org/u-boot.git. Whereas Harald's feature used a
compile-time array to specify partitions, the feature introduced by
this patch uses the mtdparts environment variable.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
Signed-off-by: Harald Welte <laforge at gnumonks.org>
CC: Wolfgang Denk <wd at denx.de>

---

V2:
 * formatting: spaces after 'if' and 'for'
 * trailing whitespace removed
 * check for null mtd->block_isbad before dereferencing

V3:
 * rebased to 54841ab50c20d6fa6c9cc3eb826989da3a22d934 of
   git://git.denx.de/u-boot.git
 * fix more checkpatch errors
 * update copyright statement of cmd_mtdparts.c to include openmoko's
   copyright of the 'dynamic partitions' functionality using commit
   e05835df019027391f58f9d8ce5e1257d6924798 of
   git://git.openmoko.org/u-boot.git as reference.

V4:
 * rebased to b417260d871d4d8d336c160d95ed40cc8c0fb0fa of
   git://git.denx.de/u-boot.git
 * fixed multi-line comment style
 * removed changelog and my (C) from file header
 * added source of port to the commit message
 * fixed multi-line comment style
 * indentation only by tabs
---
 common/cmd_mtdparts.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 116 insertions(+), 1 deletions(-)

diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 500a38e..7e2e232 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -15,6 +15,9 @@
  *   Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
  *   kernel tree.
  *
+ * (C) Copyright 2008
+ * Harald Welte, OpenMoko, Inc., Harald Welte <laforge at openmoko.org>
+ *
  *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
  *   Copyright 2002 SYSGO Real-Time Solutions GmbH
  *
@@ -1430,6 +1433,105 @@ static int delete_partition(const char *id)
 	return 1;
 }
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * Increase the size of the given partition so that it's net size is at least
+ * as large as the size member and such that the next parition would start on a
+ * good blcok if it were adjacent to this partition.
+ *
+ * @param mtd the mtd device
+ * @param part the partition
+ * @param next_offset pointer to the offset of the next partition after this
+ *                    partition's size has been modified (output)
+ */
+static void spread_partition(struct mtd_info *mtd, struct part_info *part,
+							 u32 *next_offset)
+{
+	if (!mtd->block_isbad)
+		goto out;
+
+	u32 i, bb_delta = 0;
+
+	for (i = part->offset; i - bb_delta < part->offset + part->size;
+						i += mtd->erasesize) {
+		if (mtd->block_isbad(mtd, i))
+			bb_delta += mtd->erasesize;
+	}
+
+	/*
+	 * Absorb bad blocks immeadiately following this
+	 * partition also into the partition, such that
+	 * the next partition starts with a good block.
+	 */
+	while (i < mtd->size && mtd->block_isbad(mtd, i)) {
+		bb_delta += mtd->erasesize;
+		i += mtd->erasesize;
+	}
+
+	if (part->offset + part->size + bb_delta > mtd->size) {
+		part->size = mtd->size - part->offset - bb_delta;
+		printf("truncated partition %s to %d bytes\n", part->name,
+							      part->size);
+	}
+
+	part->size += bb_delta;
+
+out:
+	*next_offset = part->offset + part->size;
+}
+
+/**
+ * Adjust all of the partition sizes, such that all partitions are at least
+ * as big as their mtdparts environment variable sizes and they each start
+ * on a good block.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int spread_partitions(void)
+{
+	struct list_head *dentry, *pentry;
+	struct mtd_device *dev;
+	struct part_info *part;
+	struct mtd_info *mtd;
+	int part_num;
+	u32 cur_offs;
+
+	list_for_each(dentry, &devices) {
+		dev = list_entry(dentry, struct mtd_device, link);
+
+		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+			return 1;
+
+		part_num = 0;
+		cur_offs = 0;
+		list_for_each(pentry, &dev->parts) {
+			part = list_entry(pentry, struct part_info, link);
+
+			debug("spread_partitions: device = %s%d, partition %d ="
+				" (%s) 0x%08x at 0x%08x\n",
+				MTD_DEV_TYPE(dev->id->type), dev->id->num,
+				part_num, part->name, part->size,
+						    part->offset);
+
+			if (cur_offs > part->offset)
+				part->offset = cur_offs;
+
+			spread_partition(mtd, part, &cur_offs);
+
+			part_num++;
+		}
+	}
+
+	index_partitions();
+
+	if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+		printf("generated mtdparts too long, reseting to null\n");
+		return 1;
+	}
+	return 0;
+}
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
 /**
  * Accept character string describing mtd partitions and call device_parse()
  * for each entry. Add created devices to the global devices list.
@@ -1920,6 +2022,11 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return delete_partition(argv[2]);
 	}
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+	if ((argc == 2) && (strcmp(argv[1], "spread") == 0))
+		return spread_partitions();
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
 	return cmd_usage(cmdtp);
 }
 
@@ -1943,7 +2050,15 @@ U_BOOT_CMD(
 	"mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
 	"    - add partition\n"
 	"mtdparts default\n"
-	"    - reset partition table to defaults\n\n"
+	"    - reset partition table to defaults\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+	"mtdparts spread\n"
+	"    - adjust the sizes of the partitions so they are\n"
+	"      at least as big as the mtdparts variable specifies\n"
+	"      and they each start on a good block\n\n"
+#else
+	"\n"
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
 	"-----\n\n"
 	"this command uses three environment variables:\n\n"
 	"'partition' - keeps current partition identifier\n\n"
-- 
1.7.0.4



More information about the U-Boot mailing list