diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/cmd_mtdparts.c | 113 | 
1 files changed, 112 insertions, 1 deletions
| diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 266844f14..347e40997 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@openmoko.org> + *   *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $   *   Copyright 2002 SYSGO Real-Time Solutions GmbH   * @@ -1424,6 +1427,101 @@ 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 partition would start on a + * good block 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, +			     uint64_t *next_offset) +{ +	uint64_t net_size, padding_size = 0; +	int truncated; + +	mtd_get_len_incl_bad(mtd, part->offset, part->size, &net_size, +			     &truncated); + +	/* +	 * Absorb bad blocks immediately following this +	 * partition also into the partition, such that +	 * the next partition starts with a good block. +	 */ +	if (!truncated) { +		mtd_get_len_incl_bad(mtd, part->offset + net_size, +				     mtd->erasesize, &padding_size, &truncated); +		if (truncated) +			padding_size = 0; +		else +			padding_size -= mtd->erasesize; +	} + +	if (truncated) { +		printf("truncated partition %s to %lld bytes\n", part->name, +		       (uint64_t) net_size + padding_size); +	} + +	part->size = net_size + padding_size; +	*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; +	uint64_t 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@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. @@ -1914,6 +2012,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);  } @@ -1937,7 +2040,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" |