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 <zajec5@gmail.com>

SVN-Revision: 48639
This commit is contained in:
Rafał Miłecki 2016-02-06 16:29:12 +00:00
parent 18bcbbfd45
commit b5c41ad28c
3 changed files with 60 additions and 13 deletions

View file

@ -22,6 +22,7 @@
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <byteswap.h>
#include <limits.h> #include <limits.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -50,8 +51,32 @@
#define MAX_ARGS 8 #define MAX_ARGS 8
#define JFFS2_DEFAULT_DIR "" /* directory name without /, empty means root dir */ #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 *buf = NULL;
static char *imagefile = NULL; static char *imagefile = NULL;
static enum mtd_image_format imageformat = MTD_IMAGE_FORMAT_UNKNOWN;
static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR; static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR;
static int buflen = 0; static int buflen = 0;
int quiet; int quiet;
@ -149,13 +174,39 @@ int mtd_write_buffer(int fd, const char *buf, int offset, int length)
return 0; return 0;
} }
static int static int
image_check(int imagefd, const char *mtd) image_check(int imagefd, const char *mtd)
{ {
uint32_t magic;
int ret = 1; 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; return ret;

View file

@ -3,7 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#ifdef target_brcm47xx #if defined(target_brcm47xx) || defined(target_bcm53xx)
#define target_brcm 1 #define target_brcm 1
#endif #endif

View file

@ -44,8 +44,6 @@ struct trx_header {
uint32_t offsets[3]; /* Offsets of partitions from start of header */ uint32_t offsets[3]; /* Offsets of partitions from start of header */
}; };
#define SEAMA_MAGIC 0x17a4a35e
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
#define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24)) #define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
#elif __BYTE_ORDER == __LITTLE_ENDIAN #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) if (strcmp(mtd, "firmware") != 0)
return 1; return 1;
*len = read(imagefd, buf, 32);
if (*len < 32) { if (*len < 32) {
fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len); *len += read(imagefd, buf + *len, 32 - *len);
return 0; 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 (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
if (quiet < 2) { if (quiet < 2) {
fprintf(stderr, "Bad trx header\n"); fprintf(stderr, "Bad trx header\n");