/*
- * $Id: redboot.c,v 1.11 2003/05/21 10:39:26 dwmw2 Exp $
+ * $Id: redboot.c,v 1.15 2004/08/10 07:55:16 dwmw2 Exp $
*
* Parse RedBoot-style Flash Image System (FIS) tables and
* produce a Linux partition array to match.
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
char *names;
char *nullname;
int namelen = 0;
+ int nulllen = 0;
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
static char nullstring[] = "unallocated";
+#endif
- buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ buf = vmalloc(master->erasesize);
if (!buf)
return -ENOMEM;
/* Read the start of the last erase block */
ret = master->read(master, master->size - master->erasesize,
- PAGE_SIZE, &retlen, (void *)buf);
+ master->erasesize, &retlen, (void *)buf);
if (ret)
goto out;
- if (retlen != PAGE_SIZE) {
+ if (retlen != master->erasesize) {
ret = -EIO;
goto out;
}
goto out;
}
- for (i = 0; i < PAGE_SIZE / sizeof(struct fis_image_desc); i++) {
+ for (i = 0; i < master->erasesize / sizeof(struct fis_image_desc); i++) {
struct fis_list *new_fl, **prev;
if (buf[i].name[0] == 0xff)
nrparts++;
}
- if (fl->img->flash_base)
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ if (fl->img->flash_base) {
nrparts++;
+ nulllen = sizeof(nullstring);
+ }
for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
- if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base)
+ if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize <= tmp_fl->next->img->flash_base) {
nrparts++;
+ nulllen = sizeof(nullstring);
+ }
}
- parts = kmalloc(sizeof(*parts)*nrparts + sizeof(nullstring) + namelen, GFP_KERNEL);
+#endif
+ parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
if (!parts) {
ret = -ENOMEM;
goto out;
}
- memset(parts, 0, sizeof(*parts)*nrparts + namelen);
+ memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
- /* FIXME: Include nullname only if it's used */
nullname = (char *)&parts[nrparts];
- sprintf(nullname, nullstring);
- names = nullname + sizeof(nullstring);
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ if (nulllen > 0) {
+ strcpy(nullname, nullstring);
+ }
+#endif
+ names = nullname + nulllen;
i=0;
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
if (fl->img->flash_base) {
parts[0].name = nullname;
parts[0].size = fl->img->flash_base;
parts[0].offset = 0;
+ i++;
}
+#endif
for ( ; i<nrparts; i++) {
parts[i].size = fl->img->size;
parts[i].offset = fl->img->flash_base;
parts[i].name = names;
strcpy(names, fl->img->name);
+#ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY
+ if (!memcmp(names, "RedBoot", 8) ||
+ !memcmp(names, "RedBoot config", 15) ||
+ !memcmp(names, "FIS directory", 14)) {
+ parts[i].mask_flags = MTD_WRITEABLE;
+ }
+#endif
names += strlen(names)+1;
- if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) {
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
i++;
parts[i].offset = parts[i-1].size + parts[i-1].offset;
parts[i].size = fl->next->img->flash_base - parts[i].offset;
parts[i].name = nullname;
}
+#endif
tmp_fl = fl;
fl = fl->next;
kfree(tmp_fl);
fl = fl->next;
kfree(old);
}
- kfree(buf);
+ vfree(buf);
return ret;
}