mtd: fix up error messages
[openwrt/openwrt.git] / package / system / mtd / src / trx.c
index 65c24404c2c1fe771acf0f78936b7bbe187a944c..1f5c52914c453786dde689ac3a1a01bead30982a 100644 (file)
@@ -2,7 +2,7 @@
  * trx.c
  *
  * Copyright (C) 2005 Mike Baker
- * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,6 +26,7 @@
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <endian.h>
 #include <string.h>
 #include <errno.h>
 
@@ -35,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 */
@@ -78,6 +81,7 @@ trx_fixup(int fd, const char *name)
        ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0);
        if (!ptr || (ptr == (void *) -1)) {
                perror("mmap");
+               fprintf(stderr, "Mapping the TRX header failed\n");
                goto err1;
        }
 
@@ -97,23 +101,25 @@ trx_fixup(int fd, const char *name)
 err1:
        close(bfd);
 err:
-       fprintf(stderr, "Error fixing up TRX header\n");
        return -1;
 }
 
+#ifndef target_ar71xx
 int
 trx_check(int imagefd, const char *mtd, char *buf, int *len)
 {
        const struct trx_header *trx = (const struct trx_header *) buf;
        int fd;
 
-       if (strcmp(mtd, "linux") != 0)
+       if (strcmp(mtd, "firmware") != 0)
                return 1;
 
-       *len = read(imagefd, buf, 32);
        if (*len < 32) {
-               fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
-               return 0;
+               *len += read(imagefd, buf + *len, 32 - *len);
+               if (*len < 32) {
+                       fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
+                       return 0;
+               }
        }
 
        if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
@@ -141,12 +147,15 @@ trx_check(int imagefd, const char *mtd, char *buf, int *len)
        close(fd);
        return 1;
 }
+#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;
        char *buf;
        ssize_t res;
        size_t block_offset;
@@ -160,42 +169,60 @@ 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);
        }
 
-       buf = malloc(erasesize);
-       if (!buf) {
+       first_block = malloc(erasesize);
+       if (!first_block) {
                perror("malloc");
                exit(1);
        }
 
-       res = pread(fd, buf, erasesize, block_offset);
+       res = pread(fd, first_block, erasesize, block_offset);
        if (res != erasesize) {
                perror("pread");
                exit(1);
        }
 
-       trx = (struct trx_header *) (buf + offset);
+       trx = (struct trx_header *)(first_block + offset);
        if (trx->magic != STORE32_LE(0x30524448)) {
                fprintf(stderr, "No trx magic found\n");
                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;
        }
 
-       trx->len = STORE32_LE(erasesize - offset);
+       buf = malloc(data_size);
+       if (!buf) {
+               perror("malloc");
+               exit(1);
+       }
+
+       res = pread(fd, buf, data_size, data_offset);
+       if (res != data_size) {
+               perror("pread");
+               exit(1);
+       }
+
+       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);
@@ -204,7 +231,7 @@ mtd_fixtrx(const char *mtd, size_t offset)
        if (quiet < 2)
                fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
 
-       if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+       if (pwrite(fd, first_block, erasesize, block_offset) != erasesize) {
                fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
                exit(1);
        }