mtd: fix trx_fixup
[openwrt/svn-archive/archive.git] / package / mtd / src / mtd.c
index 835cbcf4c479f6f266b8d79ab8399db747ccdbb5..18efcf57cf144d8e977995e38d1c415345b4b5c4 100644 (file)
 #include <sys/stat.h>
 #include <sys/reboot.h>
 #include <linux/reboot.h>
-#include "mtd-api.h"
+#include <mtd/mtd-user.h>
 #include "fis.h"
 #include "mtd.h"
-#include "crc32.h"
 
-#define MAX_ARGS 8
-#define JFFS2_DEFAULT_DIR      "" /* directory name without /, empty means root dir */
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define STORE32_LE(X)           ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#define STORE32_LE(X)           (X)
-#else
-#error unkown endianness!
+#ifndef MTDREFRESH
+#define MTDREFRESH     _IO('M', 50)
 #endif
 
-ssize_t pread(int fd, void *buf, size_t count, off_t offset);
-ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
-
-#define TRX_MAGIC       0x30524448      /* "HDR0" */
-struct trx_header {
-       uint32_t magic;         /* "HDR0" */
-       uint32_t len;           /* Length of file including header */
-       uint32_t crc32;         /* 32-bit CRC from flag_version to end of file */
-       uint32_t flag_version;  /* 0:15 flags, 16:31 version */
-       uint32_t offsets[3];    /* Offsets of partitions from start of header */
-};
+#define MAX_ARGS 8
+#define JFFS2_DEFAULT_DIR      "" /* directory name without /, empty means root dir */
 
 static char *buf = NULL;
 static char *imagefile = NULL;
@@ -151,9 +134,9 @@ static int
 image_check(int imagefd, const char *mtd)
 {
        int ret = 1;
-#ifdef target_brcm
-       ret = trx_check(imagefd, mtd, buf, &buflen);
-#endif
+       if (trx_check) {
+         ret = trx_check(imagefd, mtd, buf, &buflen);
+       }
        return ret;
 }
 
@@ -265,82 +248,6 @@ mtd_erase(const char *mtd)
 
 }
 
-static int
-mtd_fixtrx(const char *mtd, size_t offset)
-{
-       int fd;
-       struct trx_header *trx;
-       char *buf;
-       ssize_t res;
-       size_t block_offset;
-
-       if (quiet < 2)
-               fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
-
-       block_offset = offset & ~(erasesize - 1);
-       offset -= block_offset;
-
-       fd = mtd_check_open(mtd);
-       if(fd < 0) {
-               fprintf(stderr, "Could not open mtd device: %s\n", mtd);
-               exit(1);
-       }
-
-       if (block_offset + erasesize > mtdsize) {
-               fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
-               exit(1);
-       }
-
-       buf = malloc(erasesize);
-       if (!buf) {
-               perror("malloc");
-               exit(1);
-       }
-
-       res = pread(fd, buf, erasesize, block_offset);
-       if (res != erasesize) {
-               perror("pread");
-               exit(1);
-       }
-
-       trx = (struct trx_header *) (buf + offset);
-       if (trx->magic != STORE32_LE(0x30524448)) {
-               fprintf(stderr, "No trx magic found\n");
-               exit(1);
-       }
-
-       if (trx->len == STORE32_LE(erasesize - offset)) {
-               if (quiet < 2)
-                       fprintf(stderr, "Header already fixed, exiting\n");
-               close(fd);
-               return 0;
-       }
-
-       trx->len = STORE32_LE(erasesize - offset);
-
-       trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
-       if (mtd_erase_block(fd, block_offset)) {
-               fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
-               exit(1);
-       }
-
-       if (quiet < 2)
-               fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
-
-       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
-               fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
-               exit(1);
-       }
-
-       if (quiet < 2)
-               fprintf(stderr, "Done.\n");
-
-       close (fd);
-       sync();
-       return 0;
-
-}
-
 static int
 mtd_refresh(const char *mtd)
 {
@@ -379,7 +286,7 @@ indicate_writing(const char *mtd)
 }
 
 static int
-mtd_write(int imagefd, const char *mtd, char *fis_layout)
+mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset)
 {
        char *next = NULL;
        char *str = NULL;
@@ -387,6 +294,7 @@ mtd_write(int imagefd, const char *mtd, char *fis_layout)
        ssize_t r, w, e;
        ssize_t skip = 0;
        uint32_t offset = 0;
+       int jffs2_replaced = 0;
 
 #ifdef FIS_SUPPORT
        static struct fis_part new_parts[MAX_ARGS];
@@ -463,6 +371,11 @@ resume:
                exit(1);
        }
 
+       if (part_offset > 0) {
+               fprintf(stderr, "Seeking on mtd device '%s' to: %u\n", mtd, part_offset);
+               lseek(fd, part_offset, SEEK_SET);
+       }
+
        indicate_writing(mtd);
 
        w = e = 0;
@@ -505,6 +418,10 @@ resume:
                                        fprintf(stderr, "\nAppending jffs2 data from %s to %s...", jffs2file, mtd);
                                /* got an EOF marker - this is the place to add some jffs2 data */
                                skip = mtd_replace_jffs2(mtd, fd, e, jffs2file);
+                               jffs2_replaced = 1;
+
+                               /* don't add it again */
+                               jffs2file = NULL;
 
                                w += skip;
                                e += skip;
@@ -567,6 +484,10 @@ resume:
                offset = 0;
        }
 
+       if (jffs2_replaced && trx_fixup) {
+               trx_fixup(fd, mtd);
+       }
+
        if (!quiet)
                fprintf(stderr, "\b\b\b\b    ");
 
@@ -594,8 +515,12 @@ static void usage(void)
        "        refresh                 refresh mtd partition\n"
        "        erase                   erase all data on device\n"
        "        write <imagefile>|-     write <imagefile> (use - for stdin) to device\n"
-       "        jffs2write <file>       append <file> to the jffs2 partition on the device\n"
-       "        fixtrx                  fix the checksum in a trx header on first boot\n"
+       "        jffs2write <file>       append <file> to the jffs2 partition on the device\n");
+       if (mtd_fixtrx) {
+           fprintf(stderr,
+       "        fixtrx                  fix the checksum in a trx header on first boot\n");
+       }
+    fprintf(stderr,
        "Following options are available:\n"
        "        -q                      quiet mode (once: no [w] on writing,\n"
        "                                           twice: no status messages)\n"
@@ -605,7 +530,12 @@ static void usage(void)
        "        -e <device>             erase <device> before executing the command\n"
        "        -d <name>               directory for jffs2write, defaults to \"tmp\"\n"
        "        -j <name>               integrate <file> into jffs2 data when writing an image\n"
-       "        -o offset               offset of the trx header in the partition (for fixtrx)\n"
+       "        -p                      write beginning at partition offset\n");
+       if (mtd_fixtrx) {
+           fprintf(stderr,
+       "        -o offset               offset of the image header in the partition(for fixtrx)\n");
+    }
+       fprintf(stderr,
 #ifdef FIS_SUPPORT
        "        -F <part>[:<size>[:<entrypoint>]][,<part>...]\n"
        "                                alter the fis partition table to create new partitions replacing\n"
@@ -636,7 +566,7 @@ int main (int argc, char **argv)
        int ch, i, boot, imagefd = 0, force, unlocked;
        char *erase[MAX_ARGS], *device = NULL;
        char *fis_layout = NULL;
-       size_t offset = 0;
+       size_t offset = 0, part_offset = 0;
        enum {
                CMD_ERASE,
                CMD_WRITE,
@@ -651,13 +581,13 @@ int main (int argc, char **argv)
        force = 0;
        buflen = 0;
        quiet = 0;
-  no_erase = 0;
+       no_erase = 0;
 
        while ((ch = getopt(argc, argv,
 #ifdef FIS_SUPPORT
                        "F:"
 #endif
-                       "frnqe:d:j:o:")) != -1)
+                       "frnqe:d:j:p:o:")) != -1)
                switch (ch) {
                        case 'f':
                                force = 1;
@@ -685,7 +615,19 @@ int main (int argc, char **argv)
                        case 'd':
                                jffs2dir = optarg;
                                break;
+                       case 'p':
+                               errno = 0;
+                               part_offset = strtoul(optarg, 0, 0);
+                               if (errno) {
+                                       fprintf(stderr, "-p: illegal numeric string\n");
+                                       usage();
+                               }
+                               break;
                        case 'o':
+                               if (!mtd_fixtrx) {
+                                       fprintf(stderr, "-o: is not available on this platform\n");
+                                       usage();
+                               }
                                errno = 0;
                                offset = strtoul(optarg, 0, 0);
                                if (errno) {
@@ -717,7 +659,7 @@ int main (int argc, char **argv)
        } else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
                cmd = CMD_ERASE;
                device = argv[1];
-       } else if ((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) {
+       } else if (((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) && mtd_fixtrx) {
                cmd = CMD_FIXTRX;
                device = argv[1];
        } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
@@ -782,7 +724,7 @@ int main (int argc, char **argv)
                case CMD_WRITE:
                        if (!unlocked)
                                mtd_unlock(device);
-                       mtd_write(imagefd, device, fis_layout);
+                       mtd_write(imagefd, device, fis_layout, part_offset);
                        break;
                case CMD_JFFS2WRITE:
                        if (!unlocked)
@@ -793,7 +735,9 @@ int main (int argc, char **argv)
                        mtd_refresh(device);
                        break;
                case CMD_FIXTRX:
-                       mtd_fixtrx(device, offset);
+                   if (mtd_fixtrx) {
+                           mtd_fixtrx(device, offset);
+            }
                        break;
        }