1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2014 Claudio Leite <leitec@staticky.com>
7 * Builds a proper flash image for routers using some Gemtek
8 * OEM boards. These include the Airlink101 AR725W, the
9 * Asante SmartHub 600 (AWRT-600N), and Linksys WRT100/110.
11 * The resulting image is compatible with the factory firmware
12 * web upgrade and TFTP interface.
15 * gcc -O2 -o mkheader_gemtek mkheader_gemtek.c -lz
17 * Claudio Leite <leitec@staticky.com>
25 #include <zlib.h> /* for crc32() */
28 * The header is in little-endian format. In case
29 * we are on a BE host, we need to swap binary
33 # include <libkern/OSByteOrder.h>
34 # define le32 OSSwapHostToLittleInt32
36 # if defined(__linux__)
38 # if __BYTE_ORDER == __BIG_ENDIAN
39 # define CPU_BIG_ENDIAN
42 # include <sys/endian.h> /* BSD's should have this */
43 # if _BYTE_ORDER == _BIG_ENDIAN
44 # define CPU_BIG_ENDIAN
47 # ifdef CPU_BIG_ENDIAN
48 # define le32(x) (((x & 0xff000000) >> 24) | \
49 ((x & 0x00ff0000) >> 8) | \
50 ((x & 0x0000ff00) << 8) | \
51 ((x & 0x000000ff) << 24))
57 struct gemtek_header
{
63 uint32_t fast_checksum
;
68 #define HDRLEN sizeof(struct gemtek_header)
74 struct gemtek_header header
;
77 struct machines mach_def
[] = {
78 {"Airlink101 AR725W", "ar725w", 0x340000,
79 {"GMTK", "1003", le32(0x03000001), 0, 0,
80 0, "01\0\0", "EN\0\0"}},
81 {"Asante AWRT-600N", "awrt600n", 0x340000,
82 {"A600", "1005", le32(0x03000001), 0, 0,
83 0, "01\0\0", "EN\0\0"}},
84 {"Linksys WRT100", "wrt100", 0x320000,
85 {"GMTK", "1007", le32(0x03040001), 0, 0,
86 0, "2\0\0\0", "EN\0\0"}},
87 {"Linksys WRT110", "wrt110", 0x320000,
88 {"GMTK", "1007", le32(0x03040001), 0, 0,
89 0, "2\0\0\0", "EN\0\0"}},
94 main(int argc
, char *argv
[])
96 unsigned long res
, flen
;
97 struct gemtek_header my_hdr
;
99 int image_type
= -1, index
;
104 fprintf(stderr
, "mkheader_gemtek <uImage> <webflash image> [machine ID]\n");
105 fprintf(stderr
, " where [machine ID] is one of:\n");
106 for (index
= 0; mach_def
[index
].desc
!= 0; index
++) {
107 fprintf(stderr
, " %-10s %s", mach_def
[index
].id
, mach_def
[index
].desc
);
109 fprintf(stderr
, " (default)\n");
111 fprintf(stderr
, "\n");
118 for(index
= 0; mach_def
[index
].id
!= 0; index
++) {
119 if(strcmp(mach_def
[index
].id
, argv
[3]) == 0) {
125 if(image_type
== -1) {
126 fprintf(stderr
, "\nERROR: invalid machine type\n");
132 printf("Opening %s...\n", argv
[1]);
134 f
= fopen(argv
[1], "r");
136 fprintf(stderr
, "\nERROR: couldn't open input image\n");
140 fseek(f
, 0, SEEK_END
);
141 flen
= (unsigned long) ftell(f
);
143 printf(" %lu (0x%lX) bytes long\n", flen
, flen
);
145 if (flen
> mach_def
[image_type
].maxsize
) {
146 fprintf(stderr
, "\nERROR: image exceeds maximum compatible size\n");
150 buf
= malloc(flen
+ HDRLEN
);
152 fprintf(stderr
, "\nERROR: couldn't allocate buffer\n");
156 res
= fread(buf
+ HDRLEN
, 1, flen
, f
);
158 perror("Couldn't read entire file: fread()");
163 printf("\nCreating %s...\n", argv
[2]);
165 memcpy(&my_hdr
, &mach_def
[image_type
].header
, HDRLEN
);
167 printf(" Using %s magic\n", mach_def
[image_type
].desc
);
169 my_hdr
.imagesz
= le32(flen
+ HDRLEN
);
170 memcpy(my_hdr
.lang
, "EN", 2);
172 memcpy(buf
, &my_hdr
, HDRLEN
);
174 crc
= crc32(0, buf
, flen
+ HDRLEN
);
175 printf(" CRC32: %08X\n", crc
);
177 my_hdr
.checksum
= le32(crc
);
178 memcpy(buf
, &my_hdr
, HDRLEN
);
180 printf(" Writing...\n");
182 f_out
= fopen(argv
[2], "w");
184 fprintf(stderr
, "\nERROR: couldn't open output image\n");
188 fwrite(buf
, 1, flen
+ HDRLEN
, f_out
);