X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/f0c31da5a21302a7f25fbb818d24100f0ad3d4e3..f8877972dac9f83921b8a460467a4c0caa2de4ec:/package/mtd/src/mtd.c diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c index 2639b4ebb..ff75fcb8a 100644 --- a/package/mtd/src/mtd.c +++ b/package/mtd/src/mtd.c @@ -44,10 +44,23 @@ #include "mtd-api.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! +#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 */ @@ -251,6 +264,82 @@ 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) { @@ -396,7 +485,7 @@ resume: if (!quiet) fprintf(stderr, "\b\b\b "); if (quiet < 2) - fprintf(stderr, "\nAppending jffs2 data to from %s to %s...", jffs2file, mtd); + fprintf(stderr, "\nAppending jffs2 data from %s to %s...", jffs2file, mtd); /* got an EOF marker - this is the place to add some jffs2 data */ mtd_replace_jffs2(mtd, fd, e, jffs2file); goto done; @@ -480,6 +569,7 @@ static void usage(void) " erase erase all data on device\n" " write |- write (use - for stdin) to device\n" " jffs2write append to the jffs2 partition on the device\n" + " fixtrx fix the checksum in a trx header on first boot\n" "Following options are available:\n" " -q quiet mode (once: no [w] on writing,\n" " twice: no status messages)\n" @@ -488,6 +578,7 @@ static void usage(void) " -e erase before executing the command\n" " -d directory for jffs2write, defaults to \"tmp\"\n" " -j integrate into jffs2 data when writing an image\n" + " -o offset offset of the trx header in the partition (for fixtrx)\n" #ifdef FIS_SUPPORT " -F [:[:]][,...]\n" " alter the fis partition table to create new partitions replacing\n" @@ -518,12 +609,14 @@ 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; enum { CMD_ERASE, CMD_WRITE, CMD_UNLOCK, CMD_REFRESH, - CMD_JFFS2WRITE + CMD_JFFS2WRITE, + CMD_FIXTRX, } cmd = -1; erase[0] = NULL; @@ -536,7 +629,7 @@ int main (int argc, char **argv) #ifdef FIS_SUPPORT "F:" #endif - "frqe:d:j:")) != -1) + "frqe:d:j:o:")) != -1) switch (ch) { case 'f': force = 1; @@ -561,6 +654,14 @@ int main (int argc, char **argv) case 'd': jffs2dir = optarg; break; + case 'o': + errno = 0; + offset = strtoul(optarg, 0, 0); + if (errno) { + fprintf(stderr, "-o: illegal numeric string\n"); + usage(); + } + break; #ifdef FIS_SUPPORT case 'F': fis_layout = optarg; @@ -585,6 +686,9 @@ 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)) { + cmd = CMD_FIXTRX; + device = argv[1]; } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) { cmd = CMD_WRITE; device = argv[2]; @@ -657,6 +761,9 @@ int main (int argc, char **argv) case CMD_REFRESH: mtd_refresh(device); break; + case CMD_FIXTRX: + mtd_fixtrx(device, offset); + break; } sync();