From 55eb6ed0615683eb2d407794db8629e12920f58c Mon Sep 17 00:00:00 2001 From: Stijn Tintel Date: Sat, 6 Aug 2016 19:36:24 +0200 Subject: [PATCH] firmware-utils: mkwrggimg: new tool for D-Link DAP-2695 Based on mkwrgimg.c. Signed-off-by: Stijn Tintel Acked-by: John Crispin --- tools/firmware-utils/Makefile | 1 + tools/firmware-utils/src/mkwrggimg.c | 282 +++++++++++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 tools/firmware-utils/src/mkwrggimg.c diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 803ada4928..320d1db527 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -57,6 +57,7 @@ define Host/Compile $(call cc,buffalo-tag buffalo-lib, -Wall) $(call cc,buffalo-tftp buffalo-lib, -Wall) $(call cc,mkwrgimg md5, -Wall) + $(call cc,mkwrggimg md5, -Wall) $(call cc,mkedimaximg) $(call cc,mkbrncmdline) $(call cc,mkbrnimg) diff --git a/tools/firmware-utils/src/mkwrggimg.c b/tools/firmware-utils/src/mkwrggimg.c new file mode 100644 index 0000000000..a224b25b60 --- /dev/null +++ b/tools/firmware-utils/src/mkwrggimg.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2011 Gabor Juhos + * Copyright (C) 2016 Stijn Tintel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "md5.h" + +#define ERR(fmt, ...) do { \ + fflush(0); \ + fprintf(stderr, "[%s] *** error: " fmt "\n", \ + progname, ## __VA_ARGS__ ); \ +} while (0) + +#define ERRS(fmt, ...) do { \ + int save = errno; \ + fflush(0); \ + fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \ + progname, ## __VA_ARGS__, strerror(save)); \ +} while (0) + +#define WRGG03_MAGIC 0x20080321 + +struct wrgg03_header { + char signature[32]; + uint32_t magic1; + uint32_t magic2; + char version[16]; + char model[16]; + uint32_t flag[2]; + uint32_t reserve[2]; + char buildno[16]; + uint32_t size; + uint32_t offset; + char devname[32]; + char digest[16]; +} __attribute__ ((packed)); + +static char *progname; +static char *ifname; +static char *ofname; +static char *signature; +static char *version; +static char *model; +static uint32_t flag = 0; +static uint32_t reserve = 0; +static char *buildno; +static uint32_t offset; +static char *devname; +static int big_endian; + +void usage(int status) +{ + FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; + + fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); + fprintf(stream, +"\n" +"Options:\n" +" -b create image in big endian format\n" +" -B build number\n" +" -i read input from the file \n" +" -d set device name to \n" +" -m model name\n" +" -o write output to the file \n" +" -O set offset to \n" +" -s set image signature to \n" +" -h show this screen\n" + ); + + exit(status); +} + +static void put_u32(void *data, uint32_t val, int swap) +{ + unsigned char *p = data; + + if (swap) { + p[0] = (val >> 24) & 0xff; + p[1] = (val >> 16) & 0xff; + p[2] = (val >> 8) & 0xff; + p[3] = val & 0xff; + } else { + p[3] = (val >> 24) & 0xff; + p[2] = (val >> 16) & 0xff; + p[1] = (val >> 8) & 0xff; + p[0] = val & 0xff; + } +} + +static void get_digest(struct wrgg03_header *header, char *data, int size) +{ + MD5_CTX ctx; + + MD5_Init(&ctx); + + MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset)); + MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname)); + MD5_Update(&ctx, data, size); + + MD5_Final(header->digest, &ctx); +} + +int main(int argc, char *argv[]) +{ + struct wrgg03_header *header; + char *buf; + struct stat st; + int buflen; + int err; + int res = EXIT_FAILURE; + + FILE *outfile, *infile; + + progname = basename(argv[0]); + + while ( 1 ) { + int c; + + c = getopt(argc, argv, "bd:i:m:o:s:v:B:O:h"); + if (c == -1) + break; + + switch (c) { + case 'b': + big_endian = 1; + break; + case 'B': + buildno = optarg; + break; + case 'd': + devname = optarg; + break; + case 'i': + ifname = optarg; + break; + case 'm': + model = optarg; + break; + case 'o': + ofname = optarg; + break; + case 's': + signature = optarg; + break; + case 'v': + version = optarg; + break; + case 'O': + offset = strtoul(optarg, NULL, 0); + break; + case 'h': + usage(EXIT_SUCCESS); + break; + + default: + usage(EXIT_FAILURE); + break; + } + } + + if (signature == NULL) { + ERR("no signature specified"); + goto err; + } + + if (ifname == NULL) { + ERR("no input file specified"); + goto err; + } + + if (ofname == NULL) { + ERR("no output file specified"); + goto err; + } + + if (devname == NULL) { + ERR("no device name specified"); + goto err; + } + + if (model == NULL) { + ERR("no model name specified"); + goto err; + } + + if (buildno == NULL) { + ERR("no build number specified"); + goto err; + } + + if (version == NULL) { + ERR("no version specified"); + goto err; + } + + err = stat(ifname, &st); + if (err){ + ERRS("stat failed on %s", ifname); + goto err; + } + + buflen = st.st_size + sizeof(struct wrgg03_header); + buf = malloc(buflen); + if (!buf) { + ERR("no memory for buffer\n"); + goto err; + } + + infile = fopen(ifname, "r"); + if (infile == NULL) { + ERRS("could not open \"%s\" for reading", ifname); + goto err_free; + } + + errno = 0; + fread(buf + sizeof(struct wrgg03_header), st.st_size, 1, infile); + if (errno != 0) { + ERRS("unable to read from file %s", ifname); + goto close_in; + } + + header = (struct wrgg03_header *) buf; + memset(header, '\0', sizeof(struct wrgg03_header)); + + strncpy(header->signature, signature, sizeof(header->signature)); + put_u32(&header->magic1, WRGG03_MAGIC, 0); + put_u32(&header->magic2, WRGG03_MAGIC, 0); + strncpy(header->version, version, sizeof(header->version)); + strncpy(header->model, model, sizeof(header->model)); + put_u32(&header->flag, flag, 0); + put_u32(&header->reserve, reserve, 0); + strncpy(header->buildno, buildno, sizeof(header->buildno)); + put_u32(&header->size, st.st_size, big_endian); + put_u32(&header->offset, offset, big_endian); + strncpy(header->devname, devname, sizeof(header->devname)); + + get_digest(header, buf + sizeof(struct wrgg03_header), st.st_size); + + outfile = fopen(ofname, "w"); + if (outfile == NULL) { + ERRS("could not open \"%s\" for writing", ofname); + goto close_in; + } + + errno = 0; + fwrite(buf, buflen, 1, outfile); + if (errno) { + ERRS("unable to write to file %s", ofname); + goto close_out; + } + + fflush(outfile); + + res = EXIT_SUCCESS; + +close_out: + fclose(outfile); + if (res != EXIT_SUCCESS) + unlink(ofname); +close_in: + fclose(infile); +err_free: + free(buf); +err: + return res; +} -- 2.25.1