aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware-utils/src/mkheader_gemtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/firmware-utils/src/mkheader_gemtek.c')
-rw-r--r--tools/firmware-utils/src/mkheader_gemtek.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/tools/firmware-utils/src/mkheader_gemtek.c b/tools/firmware-utils/src/mkheader_gemtek.c
new file mode 100644
index 0000000000..9e618efbad
--- /dev/null
+++ b/tools/firmware-utils/src/mkheader_gemtek.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2014 Claudio Leite <leitec@staticky.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Builds a proper flash image for routers using some Gemtek
+ * OEM boards. These include the Airlink101 AR725W, the
+ * Asante SmartHub 600 (AWRT-600N), and Linksys WRT100/110.
+ *
+ * The resulting image is compatible with the factory firmware
+ * web upgrade and TFTP interface.
+ *
+ * To build:
+ * gcc -O2 -o mkheader_gemtek mkheader_gemtek.c -lz
+ *
+ * Claudio Leite <leitec@staticky.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <zlib.h> /* for crc32() */
+
+/*
+ * The header is in little-endian format. In case
+ * we are on a BE host, we need to swap binary
+ * values.
+ */
+#ifdef __APPLE__
+# include <libkern/OSByteOrder.h>
+# define le32 OSSwapHostToLittleInt32
+#else
+# if defined(__linux__)
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define CPU_BIG_ENDIAN
+# endif
+# else
+# include <sys/endian.h> /* BSD's should have this */
+# if _BYTE_ORDER == _BIG_ENDIAN
+# define CPU_BIG_ENDIAN
+# endif
+# endif
+# ifdef CPU_BIG_ENDIAN
+# define le32(x) (((x & 0xff000000) >> 24) | \
+ ((x & 0x00ff0000) >> 8) | \
+ ((x & 0x0000ff00) << 8) | \
+ ((x & 0x000000ff) << 24))
+# else
+# define le32(x) (x)
+# endif
+#endif
+
+struct gemtek_header {
+ uint8_t magic[4];
+ uint8_t version[4];
+ uint32_t product_id;
+ uint32_t imagesz;
+ uint32_t checksum;
+ uint32_t fast_checksum;
+ uint8_t build[4];
+ uint8_t lang[4];
+};
+
+#define HDRLEN sizeof(struct gemtek_header)
+
+struct machines {
+ char *desc;
+ char *id;
+ uint32_t maxsize;
+ struct gemtek_header header;
+};
+
+struct machines mach_def[] = {
+ {"Airlink101 AR725W", "ar725w", 0x340000,
+ {"GMTK", "1003", le32(0x03000001), 0, 0,
+ 0, "01\0\0", "EN\0\0"}},
+ {"Asante AWRT-600N", "awrt600n", 0x340000,
+ {"A600", "1005", le32(0x03000001), 0, 0,
+ 0, "01\0\0", "EN\0\0"}},
+ {"Linksys WRT100", "wrt100", 0x320000,
+ {"GMTK", "1007", le32(0x03040001), 0, 0,
+ 0, "2\0\0\0", "EN\0\0"}},
+ {"Linksys WRT110", "wrt110", 0x320000,
+ {"GMTK", "1007", le32(0x03040001), 0, 0,
+ 0, "2\0\0\0", "EN\0\0"}},
+ {0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ unsigned long res, flen;
+ struct gemtek_header my_hdr;
+ FILE *f, *f_out;
+ int image_type = -1, index;
+ uint8_t *buf;
+ uint32_t crc;
+
+ if (argc < 3) {
+ fprintf(stderr, "mkheader_gemtek <uImage> <webflash image> [machine ID]\n");
+ fprintf(stderr, " where [machine ID] is one of:\n");
+ for (index = 0; mach_def[index].desc != 0; index++) {
+ fprintf(stderr, " %-10s %s", mach_def[index].id, mach_def[index].desc);
+ if (index == 0)
+ fprintf(stderr, " (default)\n");
+ else
+ fprintf(stderr, "\n");
+ }
+
+ exit(-1);
+ }
+
+ if (argc == 4) {
+ for(index = 0; mach_def[index].id != 0; index++) {
+ if(strcmp(mach_def[index].id, argv[3]) == 0) {
+ image_type = index;
+ break;
+ }
+ }
+
+ if(image_type == -1) {
+ fprintf(stderr, "\nERROR: invalid machine type\n");
+ exit(-1);
+ }
+ } else
+ image_type = 0;
+
+ printf("Opening %s...\n", argv[1]);
+
+ f = fopen(argv[1], "r");
+ if(!f) {
+ fprintf(stderr, "\nERROR: couldn't open input image\n");
+ exit(-1);
+ }
+
+ fseek(f, 0, SEEK_END);
+ flen = (unsigned long) ftell(f);
+
+ printf(" %lu (0x%lX) bytes long\n", flen, flen);
+
+ if (flen > mach_def[image_type].maxsize) {
+ fprintf(stderr, "\nERROR: image exceeds maximum compatible size\n");
+ goto f_error;
+ }
+
+ buf = malloc(flen + HDRLEN);
+ if (!buf) {
+ fprintf(stderr, "\nERROR: couldn't allocate buffer\n");
+ goto f_error;
+ }
+ rewind(f);
+ res = fread(buf + HDRLEN, 1, flen, f);
+ if (res != flen) {
+ perror("Couldn't read entire file: fread()");
+ goto f_error;
+ }
+ fclose(f);
+
+ printf("\nCreating %s...\n", argv[2]);
+
+ memcpy(&my_hdr, &mach_def[image_type].header, HDRLEN);
+
+ printf(" Using %s magic\n", mach_def[image_type].desc);
+
+ my_hdr.imagesz = le32(flen + HDRLEN);
+ memcpy(my_hdr.lang, "EN", 2);
+
+ memcpy(buf, &my_hdr, HDRLEN);
+
+ crc = crc32(0, buf, flen + HDRLEN);
+ printf(" CRC32: %08X\n", crc);
+
+ my_hdr.checksum = le32(crc);
+ memcpy(buf, &my_hdr, HDRLEN);
+
+ printf(" Writing...\n");
+
+ f_out = fopen(argv[2], "w");
+ if(!f_out) {
+ fprintf(stderr, "\nERROR: couldn't open output image\n");
+ exit(-1);
+ }
+
+ fwrite(buf, 1, flen + HDRLEN, f_out);
+
+ fclose(f_out);
+
+ free(buf);
+ return 0;
+
+f_error:
+ fclose(f);
+ exit(-1);
+}
>436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509