[OpenWrt-Devel] [PATCH] mtd: detect image format when writing

Rafał Miłecki zajec5 at gmail.com
Wed Feb 3 16:38:25 EST 2016


Recently TRX checking code was changed to detect Seama format and don't
abort whole writing operation because of it. This isn't a good long-term
solution. It's a poor idea to teach every format handler recognizing all
possible formats. Instead it should be handled in a generic code which
should run check depending on the detected format.

This will also allow further improvements like fixing formats other than
TRX after replacing JFFS2.

Signed-off-by: Rafał Miłecki <zajec5 at gmail.com>
---
 package/system/mtd/src/mtd.c | 57 +++++++++++++++++++++++++++++++++++++++++---
 package/system/mtd/src/mtd.h |  2 +-
 package/system/mtd/src/trx.c | 14 ++++-------
 3 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/package/system/mtd/src/mtd.c b/package/system/mtd/src/mtd.c
index 0247630..03ee567 100644
--- a/package/system/mtd/src/mtd.c
+++ b/package/system/mtd/src/mtd.c
@@ -22,6 +22,7 @@
  */
 
 #define _GNU_SOURCE
+#include <byteswap.h>
 #include <limits.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -50,8 +51,32 @@
 #define MAX_ARGS 8
 #define JFFS2_DEFAULT_DIR	"" /* directory name without /, empty means root dir */
 
+#define TRX_MAGIC		0x48445230	/* "HDR0" */
+#define SEAMA_MAGIC		0x5ea3a417
+
+#if !defined(__BYTE_ORDER)
+#error "Unknown byte order"
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_be32(x)	(x)
+#define be32_to_cpu(x)	(x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_be32(x)	bswap_32(x)
+#define be32_to_cpu(x)	bswap_32(x)
+#else
+#error "Unsupported endianness"
+#endif
+
+enum mtd_image_format {
+	MTD_IMAGE_FORMAT_UNKNOWN,
+	MTD_IMAGE_FORMAT_TRX,
+	MTD_IMAGE_FORMAT_SEAMA,
+};
+
 static char *buf = NULL;
 static char *imagefile = NULL;
+static enum mtd_image_format imageformat = MTD_IMAGE_FORMAT_UNKNOWN;
 static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
 static int buflen = 0;
 int quiet;
@@ -149,13 +174,39 @@ int mtd_write_buffer(int fd, const char *buf, int offset, int length)
 	return 0;
 }
 
-
 static int
 image_check(int imagefd, const char *mtd)
 {
+	uint32_t magic;
 	int ret = 1;
-	if (trx_check) {
-	  ret = trx_check(imagefd, mtd, buf, &buflen);
+
+	if (buflen < sizeof(magic)) {
+		buflen += read(imagefd, buf + buflen, sizeof(magic) - buflen);
+		if (buflen < sizeof(magic)) {
+			fprintf(stdout, "Could not get image magic\n");
+			return 0;
+		}
+	}
+	magic = ((uint32_t *)buf)[0];
+
+	if (be32_to_cpu(magic) == TRX_MAGIC)
+		imageformat = MTD_IMAGE_FORMAT_TRX;
+	else if (be32_to_cpu(magic) == SEAMA_MAGIC)
+		imageformat = MTD_IMAGE_FORMAT_SEAMA;
+
+	switch (imageformat) {
+	case MTD_IMAGE_FORMAT_TRX:
+		if (trx_check)
+			ret = trx_check(imagefd, mtd, buf, &buflen);
+		break;
+	case MTD_IMAGE_FORMAT_SEAMA:
+		break;
+	default:
+#ifdef target_brcm
+		if (!strcmp(mtd, "firmware"))
+			ret = 0;
+#endif
+		break;
 	}
 
 	return ret;
diff --git a/package/system/mtd/src/mtd.h b/package/system/mtd/src/mtd.h
index fb37b8b..751b0d0 100644
--- a/package/system/mtd/src/mtd.h
+++ b/package/system/mtd/src/mtd.h
@@ -3,7 +3,7 @@
 
 #include <stdbool.h>
 
-#ifdef target_brcm47xx
+#if defined(target_brcm47xx) || defined(target_bcm53xx)
 #define target_brcm 1
 #endif
 
diff --git a/package/system/mtd/src/trx.c b/package/system/mtd/src/trx.c
index 5763917..00c4d6c 100644
--- a/package/system/mtd/src/trx.c
+++ b/package/system/mtd/src/trx.c
@@ -44,8 +44,6 @@ struct trx_header {
 	uint32_t offsets[3];    /* Offsets of partitions from start of header */
 };
 
-#define SEAMA_MAGIC	0x17a4a35e
-
 #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
@@ -114,16 +112,14 @@ trx_check(int imagefd, const char *mtd, char *buf, int *len)
 	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;
+		}
 	}
 
-	/* Allow writing Seama files to firmware without an extra validation */
-	if (trx->magic == SEAMA_MAGIC)
-		return 1;
-
 	if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
 		if (quiet < 2) {
 			fprintf(stderr, "Bad trx header\n");
-- 
1.8.4.5
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list