X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/2c2e02d72979e9d2865a400068abc4262bf88074..d7f545f983573bd54a40c1ba65c5f2c6ea8b87df:/package/mtd/src/mtd.c

diff --git a/package/mtd/src/mtd.c b/package/mtd/src/mtd.c
index bd966ab7d..5fa260b91 100644
--- a/package/mtd/src/mtd.c
+++ b/package/mtd/src/mtd.c
@@ -41,26 +41,19 @@
 #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"
 
 #define MAX_ARGS 8
 #define JFFS2_DEFAULT_DIR	"" /* directory name without /, empty means root dir */
 
-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 */
-};
-
 static char *buf = NULL;
 static char *imagefile = NULL;
 static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
 static int buflen = 0;
 int quiet;
+int no_erase;
 int mtdsize = 0;
 int erasesize = 0;
 
@@ -98,13 +91,13 @@ int mtd_check_open(const char *mtd)
 	fd = mtd_open(mtd, false);
 	if(fd < 0) {
 		fprintf(stderr, "Could not open mtd device: %s\n", mtd);
-		return 0;
+		return -1;
 	}
 
 	if(ioctl(fd, MEMGETINFO, &mtdInfo)) {
 		fprintf(stderr, "Could not get MTD device info from %s\n", mtd);
 		close(fd);
-		return 0;
+		return -1;
 	}
 	mtdsize = mtdInfo.size;
 	erasesize = mtdInfo.erasesize;
@@ -137,9 +130,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;
 }
 
@@ -162,7 +155,7 @@ static int mtd_check(const char *mtd)
 		}
 
 		fd = mtd_check_open(mtd);
-		if (!fd)
+		if (fd < 0)
 			return 0;
 
 		if (!buf)
@@ -199,7 +192,7 @@ mtd_unlock(const char *mtd)
 		}
 
 		fd = mtd_check_open(mtd);
-		if(fd <= 0) {
+		if(fd < 0) {
 			fprintf(stderr, "Could not open mtd device: %s\n", mtd);
 			exit(1);
 		}
@@ -230,7 +223,7 @@ mtd_erase(const char *mtd)
 		fprintf(stderr, "Erasing %s ...\n", mtd);
 
 	fd = mtd_check_open(mtd);
-	if(fd <= 0) {
+	if(fd < 0) {
 		fprintf(stderr, "Could not open mtd device: %s\n", mtd);
 		exit(1);
 	}
@@ -260,7 +253,7 @@ mtd_refresh(const char *mtd)
 		fprintf(stderr, "Refreshing mtd partition %s ... ", mtd);
 
 	fd = mtd_check_open(mtd);
-	if(fd <= 0) {
+	if(fd < 0) {
 		fprintf(stderr, "Could not open mtd device: %s\n", mtd);
 		exit(1);
 	}
@@ -278,6 +271,16 @@ mtd_refresh(const char *mtd)
 	return 0;
 }
 
+static void
+indicate_writing(const char *mtd)
+{
+	if (quiet < 2)
+		fprintf(stderr, "\nWriting from %s to %s ... ", imagefile, mtd);
+
+	if (!quiet)
+		fprintf(stderr, " [ ]");
+}
+
 static int
 mtd_write(int imagefd, const char *mtd, char *fis_layout)
 {
@@ -285,6 +288,7 @@ mtd_write(int imagefd, const char *mtd, char *fis_layout)
 	char *str = NULL;
 	int fd, result;
 	ssize_t r, w, e;
+	ssize_t skip = 0;
 	uint32_t offset = 0;
 
 #ifdef FIS_SUPPORT
@@ -362,13 +366,9 @@ resume:
 		exit(1);
 	}
 
-	if (quiet < 2)
-		fprintf(stderr, "Writing from %s to %s ... ", imagefile, mtd);
+	indicate_writing(mtd);
 
 	w = e = 0;
-	if (!quiet)
-		fprintf(stderr, " [ ]");
-
 	for (;;) {
 		/* buffer may contain data already (from trx check or last mtd partition write attempt) */
 		while (buflen < erasesize) {
@@ -391,15 +391,33 @@ resume:
 		if (buflen == 0)
 			break;
 
+		if (skip > 0) {
+			skip -= buflen;
+			buflen = 0;
+			if (skip <= 0)
+				indicate_writing(mtd);
+
+			continue;
+		}
+
 		if (jffs2file) {
 			if (memcmp(buf, JFFS2_EOF, sizeof(JFFS2_EOF) - 1) == 0) {
 				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;
+				skip = mtd_replace_jffs2(mtd, fd, e, jffs2file);
+
+				/* don't add it again */
+				jffs2file = NULL;
+
+				w += skip;
+				e += skip;
+				skip -= buflen;
+				buflen = 0;
+				offset = 0;
+				continue;
 			}
 			/* no EOF marker, make sure we figure out the last inode number
 			 * before appending some data */
@@ -407,31 +425,34 @@ resume:
 		}
 
 		/* need to erase the next block before writing data to it */
-		while (w + buflen > e) {
-			if (!quiet)
-				fprintf(stderr, "\b\b\b[e]");
-
-
-			if (mtd_erase_block(fd, e) < 0) {
-				if (next) {
-					if (w < e) {
-						write(fd, buf + offset, e - w);
-						offset = e - w;
+		if(!no_erase)
+		{
+			while (w + buflen > e) {
+				if (!quiet)
+					fprintf(stderr, "\b\b\b[e]");
+
+
+				if (mtd_erase_block(fd, e) < 0) {
+					if (next) {
+						if (w < e) {
+							write(fd, buf + offset, e - w);
+							offset = e - w;
+						}
+						w = 0;
+						e = 0;
+						close(fd);
+						mtd = next;
+						fprintf(stderr, "\b\b\b   \n");
+						goto resume;
+					} else {
+						fprintf(stderr, "Failed to erase block\n");
+						exit(1);
 					}
-					w = 0;
-					e = 0;
-					close(fd);
-					mtd = next;
-					fprintf(stderr, "\b\b\b   \n");
-					goto resume;
-				} else {
-					fprintf(stderr, "Failed to erase block\n");
-					exit(1);
 				}
-			}
 
-			/* erase the chunk */
-			e += erasesize;
+				/* erase the chunk */
+				e += erasesize;
+			}
 		}
 
 		if (!quiet)
@@ -479,15 +500,26 @@ 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"
+	"        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"
+	"        -n                      write without first erasing the blocks\n"
 	"        -r                      reboot after successful command\n"
 	"        -f                      force write without trx checks\n"
 	"        -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"
+	"        -j <name>               integrate <file> into jffs2 data when writing an image\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"
@@ -518,12 +550,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;
@@ -531,12 +565,13 @@ int main (int argc, char **argv)
 	force = 0;
 	buflen = 0;
 	quiet = 0;
+  no_erase = 0;
 
 	while ((ch = getopt(argc, argv,
 #ifdef FIS_SUPPORT
 			"F:"
 #endif
-			"frqe:d:j:")) != -1)
+			"frnqe:d:j:o:")) != -1)
 		switch (ch) {
 			case 'f':
 				force = 1;
@@ -544,6 +579,9 @@ int main (int argc, char **argv)
 			case 'r':
 				boot = 1;
 				break;
+			case 'n':
+				no_erase = 1;
+				break;
 			case 'j':
 				jffs2file = optarg;
 				break;
@@ -561,6 +599,18 @@ int main (int argc, char **argv)
 			case 'd':
 				jffs2dir = optarg;
 				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) {
+					fprintf(stderr, "-o: illegal numeric string\n");
+					usage();
+				}
+				break;
 #ifdef FIS_SUPPORT
 			case 'F':
 				fis_layout = optarg;
@@ -585,6 +635,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)) && mtd_fixtrx) {
+		cmd = CMD_FIXTRX;
+		device = argv[1];
 	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
 		cmd = CMD_WRITE;
 		device = argv[2];
@@ -657,6 +710,11 @@ int main (int argc, char **argv)
 		case CMD_REFRESH:
 			mtd_refresh(device);
 			break;
+		case CMD_FIXTRX:
+		    if (mtd_fixtrx) {
+			    mtd_fixtrx(device, offset);
+            }
+			break;
 	}
 
 	sync();