[U-Boot] [PATCH 1/1] NAND Re: mtdparts fails with NAND >= 4GB
Aaron Williams
Aaron.Williams at caviumnetworks.com
Fri Jan 28 02:43:10 CET 2011
I have included my preliminary patch which seems to be working.
It has not been extensively tested yet. All of the changes were basically
making the sizes and offsets u64 instead of u32. When looking at the Linux
kernel code it looks like they also use u64. I was mistaken and our NAND
flash chip is 4GiB in size so I can't test with any larger chips.
-Aaron
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 5481c88..26d24b0 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -21,6 +21,11 @@
* $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
* Copyright 2002 SYSGO Real-Time Solutions GmbH
*
+ * (C) Copyright 2011
+ * Aaron Williams, Cavium Networks, Inc. <aaron.williams at caviumnetworks.com>
+ *
+ * Added support for partitions and flash greater than or equal to 4GiB.
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -174,7 +179,7 @@ static int device_del(struct mtd_device *dev);
* @param retptr output pointer to next char after parse completes (output)
* @return resulting unsigned int
*/
-static unsigned long memsize_parse (const char *const ptr, const char **retptr)
+static u64 memsize_parse (const char *const ptr, const char **retptr)
{
unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
@@ -207,20 +212,20 @@ static unsigned long memsize_parse (const char *const ptr, const char **retptr)
* @param buf output buffer
* @param size size to be converted to string
*/
-static void memsize_format(char *buf, u32 size)
+static void memsize_format(char *buf, u64 size)
{
#define SIZE_GB ((u32)1024*1024*1024)
#define SIZE_MB ((u32)1024*1024)
#define SIZE_KB ((u32)1024)
if ((size % SIZE_GB) == 0)
- sprintf(buf, "%ug", size/SIZE_GB);
+ sprintf(buf, "%llug", size/SIZE_GB);
else if ((size % SIZE_MB) == 0)
- sprintf(buf, "%um", size/SIZE_MB);
+ sprintf(buf, "%llum", size/SIZE_MB);
else if (size % SIZE_KB == 0)
- sprintf(buf, "%uk", size/SIZE_KB);
+ sprintf(buf, "%lluk", size/SIZE_KB);
else
- sprintf(buf, "%u", size);
+ sprintf(buf, "%llu", size);
}
/**
@@ -325,7 +330,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
{
struct mtd_info *mtd = NULL;
int i, j;
- ulong start;
+ u64 start;
if (get_mtd_info(id->type, id->num, &mtd))
return 1;
@@ -337,7 +342,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
* Only one eraseregion (NAND, OneNAND or uniform NOR),
* checking for alignment is easy here
*/
- if ((unsigned long)part->offset % mtd->erasesize) {
+ if ((u64)part->offset % mtd->erasesize) {
printf("%s%d: partition (%s) start offset"
"alignment incorrect\n",
MTD_DEV_TYPE(id->type), id->num, part->name);
@@ -412,7 +417,7 @@ static int part_validate(struct mtdids *id, struct part_info *part)
part->size = id->size - part->offset;
if (part->offset > id->size) {
- printf("%s: offset %08x beyond flash size %08x\n",
+ printf("%s: offset %08llx beyond flash size %08llx\n",
id->mtd_id, part->offset, id->size);
return 1;
}
@@ -595,8 +600,8 @@ static int part_add(struct mtd_device *dev, struct part_info *part)
static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
{
struct part_info *part;
- unsigned long size;
- unsigned long offset;
+ u64 size;
+ u64 offset;
const char *name;
int name_len;
unsigned int mask_flags;
@@ -615,7 +620,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
} else {
size = memsize_parse(p, &p);
if (size < MIN_PART_SIZE) {
- printf("partition size too small (%lx)\n", size);
+ printf("partition size too small (%llx)\n", size);
return 1;
}
}
@@ -687,14 +692,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
part->auto_name = 0;
} else {
/* auto generated name in form of size at offset */
- sprintf(part->name, "0x%08lx at 0x%08lx", size, offset);
+ sprintf(part->name, "0x%08llx at 0x%08llx", size, offset);
part->auto_name = 1;
}
part->name[name_len - 1] = '\0';
INIT_LIST_HEAD(&part->link);
- debug("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n",
+ debug("+ partition: name %-22s size 0x%08llx offset 0x%08llx mask flags %d\n",
part->name, part->size,
part->offset, part->mask_flags);
@@ -710,7 +715,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
* @param size a pointer to the size of the mtd device (output)
* @return 0 if device is valid, 1 otherwise
*/
-int mtd_device_validate(u8 type, u8 num, u32 *size)
+int mtd_device_validate(u8 type, u8 num, u64 *size)
{
struct mtd_info *mtd = NULL;
@@ -842,7 +847,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
LIST_HEAD(tmp_list);
struct list_head *entry, *n;
u16 num_parts;
- u32 offset;
+ u64 offset;
int err = 1;
debug("===device_parse===\n");
@@ -1077,15 +1082,16 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
* @param buflen buffer size
* @return 0 on success, 1 otherwise
*/
-static int generate_mtdparts(char *buf, u32 buflen)
+static int generate_mtdparts(char *buf, size_t buflen)
{
struct list_head *pentry, *dentry;
struct mtd_device *dev;
struct part_info *part, *prev_part;
char *p = buf;
char tmpbuf[32];
- u32 size, offset, len, part_cnt;
- u32 maxlen = buflen - 1;
+ u64 size, offset, len;
+ u32 part_cnt;
+ size_t maxlen = buflen - 1;
debug("--- generate_mtdparts ---\n");
@@ -1204,7 +1210,7 @@ cleanup:
* @param buflen buffer size
* @return 0 on success, 1 otherwise
*/
-static int generate_mtdparts_save(char *buf, u32 buflen)
+static int generate_mtdparts_save(char *buf, size_t buflen)
{
int ret;
@@ -1265,13 +1271,13 @@ static void print_partition_table(void)
printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\n");
list_for_each(pentry, &dev->parts) {
- u32 net_size;
+ u64 net_size;
char *size_note;
part = list_entry(pentry, struct part_info, link);
net_size = net_part_size(mtd, part);
size_note = part->size == net_size ? " " : " (!)";
- printf("%2d: %-20s0x%08x\t0x%08x%s\t0x%08x\t%d\n",
+ printf("%2d: %-20s0x%08llx\t0x%08llx%s\t0x%08llx\t%d\n",
part_num, part->name, part->size,
net_size, size_note, part->offset,
part->mask_flags);
@@ -1283,7 +1289,7 @@ static void print_partition_table(void)
list_for_each(pentry, &dev->parts) {
part = list_entry(pentry, struct part_info, link);
- printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ printf("%2d: %-20s0x%08llx\t0x%08llx\t%d\n",
part_num, part->name, part->size,
part->offset, part->mask_flags);
#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
@@ -1310,7 +1316,7 @@ static void list_partitions(void)
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",
+ printf("\nactive partition: %s%d,%d - (%s) 0x%08llx @ 0x%08llx\n",
MTD_DEV_TYPE(current_mtd_dev->id->type),
current_mtd_dev->id->num, current_mtd_partnum,
part->name, part->size, part->offset);
@@ -1410,7 +1416,7 @@ static int delete_partition(const char *id)
if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
- debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08x at 0x%08x\n",
+ debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08llx at 0x%08llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
part->name, part->size, part->offset);
@@ -1499,7 +1505,7 @@ static int spread_partitions(void)
part = list_entry(pentry, struct part_info, link);
debug("spread_partitions: device = %s%d, partition %d ="
- " (%s) 0x%08x at 0x%08x\n",
+ " (%s) 0x%08llx at 0x%08llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num,
part_num, part->name, part->size,
part->offset);
@@ -1596,7 +1602,7 @@ static int parse_mtdids(const char *const ids)
struct list_head *entry, *n;
struct mtdids *id_tmp;
u8 type, num;
- u32 size;
+ u64 size;
int ret = 1;
debug("\n---parse_mtdids---\nmtdids = %s\n\n", ids);
@@ -1670,7 +1676,7 @@ static int parse_mtdids(const char *const ids)
id->mtd_id[mtd_id_len - 1] = '\0';
INIT_LIST_HEAD(&id->link);
- debug("+ id %s%d\t%16d bytes\t%s\n",
+ debug("+ id %s%d\t%16llu bytes\t%s\n",
MTD_DEV_TYPE(id->type), id->num,
id->size, id->mtd_id);
@@ -1999,7 +2005,7 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (!strcmp(&argv[1][3], ".spread")) {
spread_partition(mtd, p, &next_offset);
- debug("increased %s to %d bytes\n", p->name, p->size);
+ debug("increased %s to %llu bytes\n", p->name, p->size);
}
#endif
diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h
index 906eb3d..dda096d 100644
--- a/include/jffs2/load_kernel.h
+++ b/include/jffs2/load_kernel.h
@@ -46,8 +46,8 @@ struct part_info {
struct list_head link;
char *name; /* partition name */
u8 auto_name; /* set to 1 for generated name */
- u32 size; /* total size of the partition */
- u32 offset; /* offset within device */
+ u64 size; /* total size of the partition */
+ u64 offset; /* offset within device */
void *jffs2_priv; /* used internaly by jffs2 */
u32 mask_flags; /* kernel MTD mask flags */
u32 sector_size; /* size of sector */
@@ -58,7 +58,7 @@ struct mtdids {
struct list_head link;
u8 type; /* device type */
u8 num; /* device number */
- u32 size; /* device size */
+ u64 size; /* device size */
char *mtd_id; /* linux kernel device id */
};
On Thursday, January 27, 2011 05:14:15 pm Aaron Williams wrote:
> I'll probably have something later today. I got it working with an earlier
> version of u-boot though it hasn't been thoroughly tested.
>
> -Aaron
>
> On Thursday, January 27, 2011 05:06:09 pm Scott Wood wrote:
> > On Thu, 27 Jan 2011 16:24:31 -0800
> >
> > Aaron Williams <Aaron.Williams at caviumnetworks.com> wrote:
> > > Hi all,
> > >
> > > It looks like the mtd partitioning code fails if the flash size exceeds
> > > a u32. I am working with an 8GB flash chip on our board and was
> > > wondering if anyone else has any experience with MTD with a chip this
> > > large?
> >
> > There's been some effort to make the U-Boot NAND code work with large
> > devices, but it's not complete. Patches to take care of the rest of
> > the problem spots are welcome, especially if you have hardware to
> > test.
> >
> > -Scott
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
More information about the U-Boot
mailing list