diff options
author | Stijn Tintel <stijn@linux-ipv6.be> | 2016-08-06 19:36:24 +0200 |
---|---|---|
committer | Stijn Tintel <stijn@linux-ipv6.be> | 2016-10-27 01:50:42 +0300 |
commit | 55eb6ed0615683eb2d407794db8629e12920f58c (patch) | |
tree | b85701bcd0c2056a78ca31f2aefbba0faa21aa61 /tools/firmware-utils/src | |
parent | a35f9bbc43c3da06eed042f80dc09e8c1da681b4 (diff) | |
download | upstream-55eb6ed0615683eb2d407794db8629e12920f58c.tar.gz upstream-55eb6ed0615683eb2d407794db8629e12920f58c.tar.bz2 upstream-55eb6ed0615683eb2d407794db8629e12920f58c.zip |
firmware-utils: mkwrggimg: new tool for D-Link DAP-2695
Based on mkwrgimg.c.
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
Acked-by: John Crispin <john@phrozen.org>
Diffstat (limited to 'tools/firmware-utils/src')
-rw-r--r-- | tools/firmware-utils/src/mkwrggimg.c | 282 |
1 files changed, 282 insertions, 0 deletions
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 <juhosg@openwrt.org> + * Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be> + * + * 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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <libgen.h> +#include <getopt.h> +#include <stdarg.h> +#include <errno.h> +#include <sys/stat.h> + +#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 <buildno> build number\n" +" -i <file> read input from the file <file>\n" +" -d <name> set device name to <name>\n" +" -m <model> model name\n" +" -o <file> write output to the file <file>\n" +" -O <offset> set offset to <offset>\n" +" -s <sig> set image signature to <sig>\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; +} |