1 // SPDX-License-Identifier: GPL-2.0-only
3 * add_header.c - partially based on OpenWrt's motorola-bin.c
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 * Gabor Juhos <juhosg@openwrt.org>
10 * The add_header utility used by various vendors preprends the buf
11 * image with a header containing a CRC32 value which is generated for the
12 * model id + reserved space for CRC32 + buf, then replaces the reserved
13 * area with the actual CRC32. This replacement tool mimics this behavior.
24 #include <netinet/in.h>
27 #define BPB 8 /* bits/byte */
29 static uint32_t crc32
[1<<BPB
];
31 static void init_crc32()
33 const uint32_t poly
= ntohl(0x2083b8ed);
36 for (n
= 0; n
< 1<<BPB
; n
++) {
40 for (bit
= 0; bit
< BPB
; bit
++)
41 crc
= (crc
& 1) ? (poly
^ (crc
>> 1)) : (crc
>> 1);
46 static uint32_t crc32buf(unsigned char *buf
, size_t len
)
48 uint32_t crc
= 0xFFFFFFFF;
50 for (; len
; len
--, buf
++)
51 crc
= crc32
[(uint8_t)crc
^ *buf
] ^ (crc
>> BPB
);
60 static void usage(const char *) __attribute__ (( __noreturn__
));
62 static void usage(const char *mess
)
64 fprintf(stderr
, "Error: %s\n", mess
);
65 fprintf(stderr
, "Usage: add_header model_id input_file output_file\n");
66 fprintf(stderr
, "\n");
70 int main(int argc
, char **argv
)
72 off_t len
; // of original buf
73 off_t buflen
; // of the output file
75 void *input_file
; // pointer to the input file (mmmapped)
77 unsigned char *buf
; // pointer to prefix + copy of original buf
82 usage("wrong number of arguments");
85 if ((fd
= open(argv
[2], O_RDONLY
)) < 0
86 || (len
= lseek(fd
, 0, SEEK_END
)) < 0
87 || (input_file
= mmap(0, len
, PROT_READ
, MAP_SHARED
, fd
, 0)) == (void *) (-1)
90 fprintf(stderr
, "Error loading file %s: %s\n", argv
[2], strerror(errno
));
94 buflen
= len
+ sizeof(header
);
98 // copy model name into header
99 strncpy(header
.model
, argv
[1], sizeof(header
.model
));
102 // create a firmware image in memory and copy the input_file to it
103 buf
= malloc(buflen
);
104 memcpy(buf
, &header
, sizeof(header
));
105 memcpy(&buf
[sizeof(header
)], input_file
, len
);
107 // CRC of temporary header + buf
108 header
.crc
= htonl(crc32buf(buf
, buflen
));
110 memcpy(buf
, &header
, sizeof(header
));
113 if ((fd
= open(argv
[3], O_CREAT
|O_WRONLY
|O_TRUNC
,0644)) < 0
114 || write(fd
, buf
, buflen
) != buflen
117 fprintf(stderr
, "Error storing file %s: %s\n", argv
[3], strerror(errno
));
123 munmap(input_file
,len
);