aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware-utils/src
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2021-04-02 13:59:02 +0200
committerRafał Miłecki <rafal@milecki.pl>2021-04-08 13:16:11 +0200
commitc251ec739f67e75a3ed25ad7c4a9478cd1ff4454 (patch)
treeb019d050495b6738fadcc949466b49d8220caef3 /tools/firmware-utils/src
parent9db0cc5787b2eec6adeb54ae8ecf17eb2a688922 (diff)
downloadupstream-c251ec739f67e75a3ed25ad7c4a9478cd1ff4454.tar.gz
upstream-c251ec739f67e75a3ed25ad7c4a9478cd1ff4454.tar.bz2
upstream-c251ec739f67e75a3ed25ad7c4a9478cd1ff4454.zip
firmware-utils: bcm4908img: detect Netgear vendor firmware
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 <rafal@milecki.pl> (cherry picked from commit a39f85d8b66125f07c4bcbea46b296946de60dc7)
Diffstat (limited to 'tools/firmware-utils/src')
-rw-r--r--tools/firmware-utils/src/bcm4908img.c58
1 files changed, 33 insertions, 25 deletions
diff --git a/tools/firmware-utils/src/bcm4908img.c b/tools/firmware-utils/src/bcm4908img.c
index 9e81ca1b11..9cb16a12ee 100644
--- a/tools/firmware-utils/src/bcm4908img.c
+++ b/tools/firmware-utils/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 <file> [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 <file>\t\t\tcheck if images is valid\n");
printf("\n");
printf("Creating a new BCM4908 image:\n");
printf("\tbcm4908img create <file> [options]\n");