diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/firmware-utils/Makefile | 1 | ||||
-rw-r--r-- | tools/firmware-utils/src/mkwrgimg.c | 240 |
2 files changed, 241 insertions, 0 deletions
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index ebec10b02..da6980514 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -52,6 +52,7 @@ define Host/Compile $(call cc,xorimage) $(call cc,buffalo-enc buffalo-lib, -Wall) $(call cc,buffalo-tag buffalo-lib, -Wall) + $(call cc,mkwrgimg md5, -Wall) endef define Host/Install diff --git a/tools/firmware-utils/src/mkwrgimg.c b/tools/firmware-utils/src/mkwrgimg.c new file mode 100644 index 000000000..052c4f981 --- /dev/null +++ b/tools/firmware-utils/src/mkwrgimg.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * 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 WRG_MAGIC 0x20040220 + +struct wrg_header { + char signature[32]; + uint32_t magic1; + uint32_t magic2; + 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 *devname; +static uint32_t offset; +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" +" -i <file> read input from the file <file>\n" +" -d <name> set device name to <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) +{ + unsigned char *p = data; + + if (big_endian) { + 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 wrg_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 wrg_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:o:s:O:h"); + if (c == -1) + break; + + switch (c) { + case 'b': + big_endian = 1; + break; + case 'd': + devname = optarg; + break; + case 'i': + ifname = optarg; + break; + case 'o': + ofname = optarg; + break; + case 's': + signature = 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; + } + + err = stat(ifname, &st); + if (err){ + ERRS("stat failed on %s", ifname); + goto err; + } + + buflen = st.st_size + sizeof(struct wrg_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 wrg_header), st.st_size, 1, infile); + if (errno != 0) { + ERRS("unable to read from file %s", ifname); + goto close_in; + } + + header = (struct wrg_header *) buf; + memset(header, '\0', sizeof(struct wrg_header)); + + strncpy(header->signature, signature, sizeof(header->signature)); + strncpy(header->devname, devname, sizeof(header->signature)); + put_u32(&header->magic1, WRG_MAGIC); + put_u32(&header->magic2, WRG_MAGIC); + put_u32(&header->size, st.st_size); + put_u32(&header->offset, offset); + + get_digest(header, buf + sizeof(struct wrg_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; +} |