#include <jffs2/load_kernel.h>
#include <linux/list.h>
#include <linux/ctype.h>
-#include <cramfs/cramfs_fs.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
#if defined(CONFIG_CMD_NAND)
-#ifdef CONFIG_NAND_LEGACY
-#include <linux/mtd/nand_legacy.h>
-#else /* !CONFIG_NAND_LEGACY */
#include <linux/mtd/nand.h>
#include <nand.h>
-#endif /* !CONFIG_NAND_LEGACY */
#endif
#if defined(CONFIG_CMD_ONENAND)
-#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <onenand_uboot.h>
#endif
#if defined(MTDIDS_DEFAULT)
static const char *const mtdids_default = MTDIDS_DEFAULT;
#else
-#warning "MTDIDS_DEFAULT not defined!"
static const char *const mtdids_default = NULL;
#endif
#if defined(MTDPARTS_DEFAULT)
static const char *const mtdparts_default = MTDPARTS_DEFAULT;
#else
-#warning "MTDPARTS_DEFAULT not defined!"
static const char *const mtdparts_default = NULL;
#endif
struct list_head devices;
/* current active device and partition number */
-static struct mtd_device *current_dev = NULL;
-static u8 current_partnum = 0;
+struct mtd_device *current_mtd_dev = NULL;
+u8 current_mtd_partnum = 0;
static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part_num);
DEBUGF("--- index partitions ---\n");
- if (current_dev) {
+ if (current_mtd_dev) {
mtddevnum = 0;
list_for_each(dentry, &devices) {
dev = list_entry(dentry, struct mtd_device, link);
- if (dev == current_dev) {
- mtddevnum += current_partnum;
+ if (dev == current_mtd_dev) {
+ mtddevnum += current_mtd_partnum;
sprintf(buf, "%d", mtddevnum);
setenv("mtddevnum", buf);
break;
mtddevnum += dev->num_parts;
}
- part = mtd_part_info(current_dev, current_partnum);
+ part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
setenv("mtddevname", part->name);
DEBUGF("=> mtddevnum %d,\n=> mtddevname %s\n", mtddevnum, part->name);
DEBUGF("--- current_save ---\n");
- if (current_dev) {
- sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_dev->id->type),
- current_dev->id->num, current_partnum);
+ if (current_mtd_dev) {
+ sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum);
setenv("partition", buf);
strncpy(last_partition, buf, 16);
}
/**
- * Performs sanity check for supplied NOR flash partition. Table of existing
- * NOR flash devices is searched and partition device is located. Alignment
- * with the granularity of NOR flash sectors is verified.
+ * Performs sanity check for supplied flash partition.
+ * Table of existing MTD flash devices is searched and partition device
+ * is located. Alignment with the granularity of nand erasesize is verified.
*
* @param id of the parent device
* @param part partition to validate
* @return 0 if partition is valid, 1 otherwise
*/
-static int part_validate_nor(struct mtdids *id, struct part_info *part)
+static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
{
-#if defined(CONFIG_CMD_FLASH)
- /* info for FLASH chips */
- extern flash_info_t flash_info[];
- flash_info_t *flash;
- int offset_aligned;
- u32 end_offset, sector_size = 0;
- int i;
-
- flash = &flash_info[id->num];
-
- /* size of last sector */
- part->sector_size = flash->size -
- (flash->start[flash->sector_count-1] - flash->start[0]);
-
- offset_aligned = 0;
- for (i = 0; i < flash->sector_count; i++) {
- if ((flash->start[i] - flash->start[0]) == part->offset) {
- offset_aligned = 1;
- break;
- }
- }
- if (offset_aligned == 0) {
- printf("%s%d: partition (%s) start offset alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ struct mtd_info *mtd;
+ char mtd_dev[16];
+ int i, j;
+ ulong start;
+
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(id->type), id->num);
+ mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd)) {
+ printf("Partition %s not found on device %s!\n", part->name, mtd_dev);
return 1;
}
- end_offset = part->offset + part->size;
- offset_aligned = 0;
- for (i = 0; i < flash->sector_count; i++) {
- if (i) {
- sector_size = flash->start[i] - flash->start[i-1];
- if (part->sector_size < sector_size)
- part->sector_size = sector_size;
- }
- if ((flash->start[i] - flash->start[0]) == end_offset)
- offset_aligned = 1;
- }
-
- if (offset_aligned || flash->size == end_offset)
- return 0;
-
- printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
-#endif
- return 1;
-}
-
-/**
- * Performs sanity check for supplied NAND flash partition. Table of existing
- * NAND flash devices is searched and partition device is located. Alignment
- * with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_nand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_CMD_NAND)
- /* info for NAND chips */
- nand_info_t *nand;
+ part->sector_size = mtd->erasesize;
- nand = &nand_info[id->num];
+ if (!mtd->numeraseregions) {
+ /*
+ * Only one eraseregion (NAND, OneNAND or uniform NOR),
+ * checking for alignment is easy here
+ */
+ if ((unsigned long)part->offset % mtd->erasesize) {
+ printf("%s%d: partition (%s) start offset"
+ "alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
- part->sector_size = nand->erasesize;
+ if (part->size % mtd->erasesize) {
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+ } else {
+ /*
+ * Multiple eraseregions (non-uniform NOR),
+ * checking for alignment is more complex here
+ */
+
+ /* Check start alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if (part->offset == start)
+ goto start_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
- if ((unsigned long)(part->offset) % nand->erasesize) {
printf("%s%d: partition (%s) start offset alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
- return 1;
- }
-
- if (part->size % nand->erasesize) {
- printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
- }
- return 0;
-#else
- return 1;
-#endif
-}
+ start_ok:
-/**
- * Performs sanity check for supplied OneNAND flash partition.
- * Table of existing OneNAND flash devices is searched and partition device
- * is located. Alignment with the granularity of nand erasesize is verified.
- *
- * @param id of the parent device
- * @param part partition to validate
- * @return 0 if partition is valid, 1 otherwise
- */
-static int part_validate_onenand(struct mtdids *id, struct part_info *part)
-{
-#if defined(CONFIG_CMD_ONENAND)
- /* info for OneNAND chips */
- struct mtd_info *mtd;
-
- mtd = &onenand_mtd;
-
- part->sector_size = mtd->erasesize;
-
- if ((unsigned long)(part->offset) % mtd->erasesize) {
- printf("%s%d: partition (%s) start offset"
- "alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
- return 1;
- }
+ /* Check end/size alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if ((part->offset + part->size) == start)
+ goto end_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
+ /* Check last sector alignment */
+ if ((part->offset + part->size) == start)
+ goto end_ok;
- if (part->size % mtd->erasesize) {
printf("%s%d: partition (%s) size alignment incorrect\n",
- MTD_DEV_TYPE(id->type), id->num, part->name);
+ MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
+
+ end_ok:
+ return 0;
}
return 0;
-#else
- return 1;
-#endif
}
return 1;
}
- if (id->type == MTD_DEV_TYPE_NAND)
- return part_validate_nand(id, part);
- else if (id->type == MTD_DEV_TYPE_NOR)
- return part_validate_nor(id, part);
- else if (id->type == MTD_DEV_TYPE_ONENAND)
- return part_validate_onenand(id, part);
- else
- DEBUGF("part_validate: invalid dev type\n");
-
- return 1;
+ /*
+ * Now we need to check if the partition starts and ends on
+ * sector (eraseblock) regions
+ */
+ return part_validate_eraseblock(id, part);
}
/**
/* otherwise just delete this partition */
- if (dev == current_dev) {
+ if (dev == current_mtd_dev) {
/* we are modyfing partitions for the current device,
* update current */
struct part_info *curr_pi;
- curr_pi = mtd_part_info(current_dev, current_partnum);
+ curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
if (curr_pi) {
if (curr_pi == part) {
printf("current partition deleted, resetting current to 0\n");
- current_partnum = 0;
+ current_mtd_partnum = 0;
} else if (part->offset <= curr_pi->offset) {
- current_partnum--;
+ current_mtd_partnum--;
}
current_save_needed = 1;
}
}
-#ifdef CONFIG_NAND_LEGACY
- jffs2_free_cache(part);
-#endif
list_del(&part->link);
free(part);
dev->num_parts--;
list_for_each_safe(entry, n, head) {
part_tmp = list_entry(entry, struct part_info, link);
-#ifdef CONFIG_NAND_LEGACY
- jffs2_free_cache(part_tmp);
-#endif
list_del(entry);
free(part_tmp);
}
/* get current partition info if we are updating current device */
curr_pi = NULL;
- if (dev == current_dev)
- curr_pi = mtd_part_info(current_dev, current_partnum);
+ if (dev == current_mtd_dev)
+ curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
list_for_each(entry, &dev->parts) {
struct part_info *pi;
if (curr_pi && (pi->offset <= curr_pi->offset)) {
/* we are modyfing partitions for the current
* device, update current */
- current_partnum++;
+ current_mtd_partnum++;
current_save();
} else {
index_partitions();
*/
int mtd_device_validate(u8 type, u8 num, u32 *size)
{
- if (type == MTD_DEV_TYPE_NOR) {
-#if defined(CONFIG_CMD_FLASH)
- if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
- extern flash_info_t flash_info[];
- *size = flash_info[num].size;
-
- return 0;
- }
+ struct mtd_info *mtd;
+ char mtd_dev[16];
- printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
- MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
-#else
- printf("support for FLASH devices not present\n");
-#endif
- } else if (type == MTD_DEV_TYPE_NAND) {
-#if defined(CONFIG_CMD_NAND)
- if (num < CONFIG_SYS_MAX_NAND_DEVICE) {
-#ifndef CONFIG_NAND_LEGACY
- *size = nand_info[num].size;
-#else
- extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE];
- *size = nand_dev_desc[num].totlen;
-#endif
- return 0;
- }
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+ mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd)) {
+ printf("Device %s not found!\n", mtd_dev);
+ return 1;
+ }
- printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
- MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
-#else
- printf("support for NAND devices not present\n");
-#endif
- } else if (type == MTD_DEV_TYPE_ONENAND) {
-#if defined(CONFIG_CMD_ONENAND)
- *size = onenand_mtd.size;
- return 0;
-#else
- printf("support for OneNAND devices not present\n");
-#endif
- } else
- printf("Unknown defice type %d\n", type);
+ *size = mtd->size;
- return 1;
+ return 0;
}
/**
list_del(&dev->link);
free(dev);
- if (dev == current_dev) {
+ if (dev == current_mtd_dev) {
/* we just deleted current device */
if (list_empty(&devices)) {
- current_dev = NULL;
+ current_mtd_dev = NULL;
} else {
/* reset first partition from first dev from the
* devices list as current */
- current_dev = list_entry(devices.next, struct mtd_device, link);
- current_partnum = 0;
+ current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+ current_mtd_partnum = 0;
}
current_save();
return 0;
u8 current_save_needed = 0;
if (list_empty(&devices)) {
- current_dev = dev;
- current_partnum = 0;
+ current_mtd_dev = dev;
+ current_mtd_partnum = 0;
current_save_needed = 1;
}
static int mtd_devices_init(void)
{
last_parts[0] = '\0';
- current_dev = NULL;
+ current_mtd_dev = NULL;
current_save();
return device_delall(&devices);
if (list_empty(&devices))
printf("no partitions defined\n");
- /* current_dev is not NULL only when we have non empty device list */
- if (current_dev) {
- part = mtd_part_info(current_dev, current_partnum);
+ /* current_mtd_dev is not NULL only when we have non empty device list */
+ if (current_mtd_dev) {
+ part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
if (part) {
printf("\nactive partition: %s%d,%d - (%s) 0x%08x @ 0x%08x\n",
- MTD_DEV_TYPE(current_dev->id->type),
- current_dev->id->num, current_partnum,
+ MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum,
part->name, part->size, part->offset);
} else {
printf("could not get current partition info\n\n");
}
printf("\ndefaults:\n");
- printf("mtdids : %s\n", mtdids_default);
- printf("mtdparts: %s\n", mtdparts_default);
+ printf("mtdids : %s\n",
+ mtdids_default ? mtdids_default : "none");
+ printf("mtdparts: %s\n",
+ mtdparts_default ? mtdparts_default : "none");
}
/**
if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
- DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08lx@0x%08lx\n",
+ DEBUGF("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
part->name, part->size, part->offset);
strncpy(last_parts, parts, MTDPARTS_MAXLEN);
/* reset first partition from first dev from the list as current */
- current_dev = list_entry(devices.next, struct mtd_device, link);
- current_partnum = 0;
+ current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+ current_mtd_partnum = 0;
current_save();
- DEBUGF("mtdparts_init: current_dev = %s%d, current_partnum = %d\n",
- MTD_DEV_TYPE(current_dev->id->type),
- current_dev->id->num, current_partnum);
+ DEBUGF("mtdparts_init: current_mtd_dev = %s%d, current_mtd_partnum = %d\n",
+ MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum);
}
/* mtdparts variable was reset to NULL, delete all devices/partitions */
DEBUGF("--- getting current partition: %s\n", tmp_ep);
if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) {
- current_dev = cdev;
- current_partnum = pnum;
+ current_mtd_dev = cdev;
+ current_mtd_partnum = pnum;
current_save();
}
} else if (getenv("partition") == NULL) {
if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
return 1;
- current_dev = dev;
- current_partnum = pnum;
+ current_mtd_dev = dev;
+ current_mtd_partnum = pnum;
current_save();
printf("partition changed to %s%d,%d\n",
chpart, 2, 0, do_chpart,
"change active partition",
"part-id\n"
- " - change active partition (e.g. part-id = nand0,1)\n"
+ " - change active partition (e.g. part-id = nand0,1)"
);
U_BOOT_CMD(
"<size> := standard linux memsize OR '-' to denote all remaining space\n"
"<offset> := partition start offset within the device\n"
"<name> := '(' NAME ')'\n"
- "<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)\n"
+ "<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)"
);
/***************************************************/