Patches fstools to identify a jffs2 partition on nand by looking
for the cleanmarker in the oob instead of at the start of an erase
block.

Signed-off-by: Ben Mulvihill <ben.mulvih...@gmail.com>

---
 lib/mtd.c |   82 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 80 insertions(+), 2 deletions(-)

--- a/lib/mtd.c 2014-03-22 13:41:42.218663752 +0100
+++ b/lib/mtd.c 2014-03-23 15:49:00.549010963 +0100
@@ -158,12 +158,75 @@ mtd_write_buffer(int fd, void *buf, int
        return 0;
 }
 
+
+static __u8
+mtd_type(int fd)
+{
+       struct mtd_info_user mtdInfo;
+
+       if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+               fprintf(stderr, "ioctl(%d, MEMGETINFO) failed: %s\n", fd,
strerror(errno));
+               return -1;
+       }
+
+       return mtdInfo.type;
+}
+
+static int
+mtd_cleanmarker_nand(int fd)
+{
+       struct mtd_info_user mtdInfo;
+
+       unsigned char oob[64];
+       struct mtd_oob_buf oobBuf = {0, 16, oob};
+       int i;
+       __u16 jffs2;
+
+       if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
+               fprintf(stderr, "ioctl(%d, MEMGETINFO) failed: %s\n", fd,
strerror(errno));
+               return -1;
+       }
+
+       /* Read the real oob length */
+       oobBuf.length = mtdInfo.oobsize;
+       if (oobBuf.length > sizeof (oob)) {
+               fprintf(stderr, "mtd_cleanmarker_nand(): oob too long");
+               return -1;
+       }
+
+       /* Read OOB data and exit on failure */
+       oobBuf.start = 0;
+       if (ioctl(fd, MEMREADOOB, &oobBuf) != 0) {
+               fprintf(stderr, "ioctl(%d, MEMREADOOB) failed: %s\n", fd,
strerror(errno));
+               return -1;
+       }
+
+       /*
+       The only way of finding out from userspace where the cleanmarker is
+       located within the oob seems to be to use an ioctl marked as obsolete.
+       So let's just search.
+       */
+
+       for (i = 0; i < oobBuf.length - 1; i++)
+       {
+               jffs2 = *(__u16 *)&oob[i];
+               jffs2 = __be16_to_cpu(jffs2);
+               if (jffs2 == 0x1985) {
+                       fprintf(stderr, "Cleanmarker found in oob at offset 
%d\n", i);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
 int
 mtd_identify(char *mtd)
 {
        int fd = mtd_load(mtd);
        __u32 deadc0de;
        __u16 jffs2;
+       __u8 type;
+
        size_t sz;
 
        if (!fd) {
@@ -172,30 +235,45 @@ mtd_identify(char *mtd)
        }
 
        sz = read(fd, &deadc0de, sizeof(deadc0de));
-       close(fd);
 
        if (sz != sizeof(deadc0de)) {
                fprintf(stderr, "reading %s failed: %s\n", mtd, 
strerror(errno));
+               close(fd);
                return -1;
        }
 
-       if (deadc0de == 0x4f575254)
+       if (deadc0de == 0x4f575254) {
+               close(fd);
                return FS_SNAPSHOT;
+       }
 
        deadc0de = __be32_to_cpu(deadc0de);
        jffs2 = __be16_to_cpu(deadc0de >> 16);
 
        if (jffs2 == 0x1985) {
                fprintf(stderr, "jffs2 is ready\n");
+               close(fd);
                return FS_JFFS2;
        }
 
        if (deadc0de == 0xdeadc0de) {
                fprintf(stderr, "jffs2 is not ready - marker found\n");
+               close(fd);
                return FS_DEADCODE;
        }
 
+       type = mtd_type (fd);
+
+       if ((type == MTD_NANDFLASH) || (type == MTD_MLCNANDFLASH)) {
+               if (!mtd_cleanmarker_nand (fd)) {
+                       fprintf(stderr, "jffs2 is ready\n");
+                       close(fd);
+                       return FS_JFFS2;
+               }
+       }
+
        fprintf(stderr, "No jffs2 marker was found\n");
 
+       close(fd);
        return FS_NONE;
 }
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to