From: Rafał Miłecki Date: Sat, 6 Feb 2016 16:29:12 +0000 (+0000) Subject: mtd: detect image format when writing X-Git-Tag: reboot~506 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=b5c41ad28c31d61d6eb9a0c0f3550e75ea74e09f;p=oweals%2Fopenwrt.git mtd: detect image format when writing 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 SVN-Revision: 48639 --- diff --git a/package/system/mtd/src/mtd.c b/package/system/mtd/src/mtd.c index 02476306f6..03ee5671d5 100644 --- a/package/system/mtd/src/mtd.c +++ b/package/system/mtd/src/mtd.c @@ -22,6 +22,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -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 fb37b8b9fa..751b0d09f6 100644 --- a/package/system/mtd/src/mtd.h +++ b/package/system/mtd/src/mtd.h @@ -3,7 +3,7 @@ #include -#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 5763917827..00c4d6c0b5 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");