From f792b86e1f89dd6ba1210625fd23b2bb8d6a90b5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 2 Apr 2021 13:59:02 +0200 Subject: [PATCH] firmware-utils: bcm4908img: detect Netgear vendor firmware MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Netgear uses CHK header which needs to be skipped when validating BCM4908 image. Detect it directly in the bcm4908img tool. Dealing with binary structs and endianess is way simpler in C. Signed-off-by: Rafał Miłecki --- src/bcm4908img.c | 58 +++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/bcm4908img.c b/src/bcm4908img.c index 9e81ca1..9cb16a1 100644 --- a/src/bcm4908img.c +++ b/src/bcm4908img.c @@ -20,9 +20,13 @@ #if __BYTE_ORDER == __BIG_ENDIAN #define cpu_to_le32(x) bswap_32(x) #define le32_to_cpu(x) bswap_32(x) +#define cpu_to_be32(x) (x) +#define be32_to_cpu(x) (x) #elif __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le32(x) (x) #define le32_to_cpu(x) (x) +#define cpu_to_be32(x) bswap_32(x) +#define be32_to_cpu(x) bswap_32(x) #else #error "Unsupported endianness" #endif @@ -52,13 +56,12 @@ struct bcm4908img_tail { /* Info about BCM4908 image */ struct bcm4908img_info { size_t file_size; + size_t vendor_header_size; /* Vendor header size */ uint32_t crc32; /* Calculated checksum */ struct bcm4908img_tail tail; }; char *pathname; -static size_t prefix_len; -static size_t suffix_len; static inline size_t bcm4908img_min(size_t x, size_t y) { return x < y ? x : y; @@ -149,8 +152,22 @@ uint32_t bcm4908img_crc32(uint32_t crc, uint8_t *buf, size_t len) { * Existing firmware parser **************************************************/ +struct chk_header { + uint32_t magic; + uint32_t header_len; + uint8_t reserved[8]; + uint32_t kernel_chksum; + uint32_t rootfs_chksum; + uint32_t kernel_len; + uint32_t rootfs_len; + uint32_t image_chksum; + uint32_t header_chksum; + char board_id[0]; +}; + static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) { struct bcm4908img_tail *tail = &info->tail; + struct chk_header *chk; struct stat st; uint8_t buf[1024]; size_t length; @@ -168,12 +185,23 @@ static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) { } info->file_size = st.st_size; + /* Vendor formats */ + + rewind(fp); + if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) { + fprintf(stderr, "Failed to read file header\n"); + return -EIO; + } + chk = (void *)buf; + if (be32_to_cpu(chk->magic) == 0x2a23245e) + info->vendor_header_size = be32_to_cpu(chk->header_len); + /* CRC32 */ - fseek(fp, prefix_len, SEEK_SET); + fseek(fp, info->vendor_header_size, SEEK_SET); info->crc32 = 0xffffffff; - length = info->file_size - prefix_len - sizeof(*tail) - suffix_len; + length = info->file_size - info->vendor_header_size - sizeof(*tail); while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) { info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes); length -= bytes; @@ -204,21 +232,6 @@ static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) { * Check **************************************************/ -static void bcm4908img_check_parse_options(int argc, char **argv) { - int c; - - while ((c = getopt(argc, argv, "p:s:")) != -1) { - switch (c) { - case 'p': - prefix_len = atoi(optarg); - break; - case 's': - suffix_len = atoi(optarg); - break; - } - } -} - static int bcm4908img_check(int argc, char **argv) { struct bcm4908img_info info; FILE *fp; @@ -231,9 +244,6 @@ static int bcm4908img_check(int argc, char **argv) { } pathname = argv[2]; - optind = 3; - bcm4908img_check_parse_options(argc, argv); - fp = fopen(pathname, "r"); if (!fp) { fprintf(stderr, "Failed to open %s\n", pathname); @@ -399,9 +409,7 @@ static void usage() { printf("Usage:\n"); printf("\n"); printf("Checking a BCM4908 image:\n"); - printf("\tbcm4908img check [options]\tcheck if images is valid\n"); - printf("\t-p prefix\t\t\tlength of custom header to skip (default: 0)\n"); - printf("\t-s suffix\t\t\tlength of custom tail to skip (default: 0)\n"); + printf("\tbcm4908img check \t\t\tcheck if images is valid\n"); printf("\n"); printf("Creating a new BCM4908 image:\n"); printf("\tbcm4908img create [options]\n"); -- 2.30.2