mtd: add -c option for specifying amount of data to be used for checksum
[openwrt.git] / package / system / mtd / src / trx.c
index f310f51..816f0eb 100644 (file)
@@ -36,6 +36,8 @@
 #include "crc32.h"
 
 #define TRX_MAGIC       0x30524448      /* "HDR0" */
+#define TRX_CRC32_DATA_OFFSET  12      /* First 12 bytes are not covered by CRC32 */
+#define TRX_CRC32_DATA_SIZE    16
 struct trx_header {
        uint32_t magic;         /* "HDR0" */
        uint32_t len;           /* Length of file including header */
@@ -148,8 +150,9 @@ trx_check(int imagefd, const char *mtd, char *buf, int *len)
 #endif
 
 int
-mtd_fixtrx(const char *mtd, size_t offset)
+mtd_fixtrx(const char *mtd, size_t offset, size_t data_size)
 {
+       size_t data_offset;
        int fd;
        struct trx_header *trx;
        char *first_block;
@@ -166,10 +169,16 @@ mtd_fixtrx(const char *mtd, size_t offset)
                exit(1);
        }
 
+       data_offset = offset + TRX_CRC32_DATA_OFFSET;
+       if (data_size)
+               data_size += TRX_CRC32_DATA_SIZE;
+       else
+               data_size = erasesize - TRX_CRC32_DATA_OFFSET;
+
        block_offset = offset & ~(erasesize - 1);
        offset -= block_offset;
 
-       if (block_offset + erasesize > mtdsize) {
+       if (data_offset + data_size > mtdsize) {
                fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
                exit(1);
        }
@@ -192,28 +201,28 @@ mtd_fixtrx(const char *mtd, size_t offset)
                exit(1);
        }
 
-       if (trx->len == STORE32_LE(erasesize - offset)) {
+       if (trx->len == STORE32_LE(data_size + TRX_CRC32_DATA_OFFSET)) {
                if (quiet < 2)
                        fprintf(stderr, "Header already fixed, exiting\n");
                close(fd);
                return 0;
        }
 
-       buf = malloc(erasesize);
+       buf = malloc(data_size);
        if (!buf) {
                perror("malloc");
                exit(1);
        }
 
-       res = pread(fd, buf, erasesize, block_offset);
-       if (res != erasesize) {
+       res = pread(fd, buf, data_size, data_offset);
+       if (res != data_size) {
                perror("pread");
                exit(1);
        }
 
-       trx->len = STORE32_LE(erasesize - offset);
+       trx->len = STORE32_LE(data_size + offsetof(struct trx_header, flag_version));
 
-       trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
+       trx->crc32 = STORE32_LE(crc32buf(buf, data_size));
        if (mtd_erase_block(fd, block_offset)) {
                fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
                exit(1);