2 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
3 * Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation.
25 #define ERR(fmt, ...) do { \
27 fprintf(stderr, "[%s] *** error: " fmt "\n", \
28 progname, ## __VA_ARGS__ ); \
31 #define ERRS(fmt, ...) do { \
34 fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
35 progname, ## __VA_ARGS__, strerror(save)); \
38 #define WRGG03_MAGIC 0x20080321
40 struct wrgg03_header {
53 } __attribute__ ((packed));
55 static char *progname;
58 static char *signature;
61 static uint32_t flag = 0;
62 static uint32_t reserve = 0;
64 static uint32_t offset;
66 static int big_endian;
68 void usage(int status)
70 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
72 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
76 " -b create image in big endian format\n"
77 " -B <buildno> build number\n"
78 " -i <file> read input from the file <file>\n"
79 " -d <name> set device name to <name>\n"
80 " -m <model> model name\n"
81 " -o <file> write output to the file <file>\n"
82 " -O <offset> set offset to <offset>\n"
83 " -s <sig> set image signature to <sig>\n"
84 " -h show this screen\n"
90 static void put_u32(void *data, uint32_t val, int swap)
92 unsigned char *p = data;
95 p[0] = (val >> 24) & 0xff;
96 p[1] = (val >> 16) & 0xff;
97 p[2] = (val >> 8) & 0xff;
100 p[3] = (val >> 24) & 0xff;
101 p[2] = (val >> 16) & 0xff;
102 p[1] = (val >> 8) & 0xff;
107 static void get_digest(struct wrgg03_header *header, char *data, int size)
113 MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset));
114 MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname));
115 MD5_Update(&ctx, data, size);
117 MD5_Final(header->digest, &ctx);
120 int main(int argc, char *argv[])
122 struct wrgg03_header *header;
127 int res = EXIT_FAILURE;
129 FILE *outfile, *infile;
131 progname = basename(argv[0]);
136 c = getopt(argc, argv, "bd:i:m:o:s:v:B:O:h");
166 offset = strtoul(optarg, NULL, 0);
178 if (signature == NULL) {
179 ERR("no signature specified");
183 if (ifname == NULL) {
184 ERR("no input file specified");
188 if (ofname == NULL) {
189 ERR("no output file specified");
193 if (devname == NULL) {
194 ERR("no device name specified");
199 ERR("no model name specified");
203 if (buildno == NULL) {
204 ERR("no build number specified");
208 if (version == NULL) {
209 ERR("no version specified");
213 err = stat(ifname, &st);
215 ERRS("stat failed on %s", ifname);
219 buflen = st.st_size + sizeof(struct wrgg03_header);
220 buf = malloc(buflen);
222 ERR("no memory for buffer\n");
226 infile = fopen(ifname, "r");
227 if (infile == NULL) {
228 ERRS("could not open \"%s\" for reading", ifname);
233 fread(buf + sizeof(struct wrgg03_header), st.st_size, 1, infile);
235 ERRS("unable to read from file %s", ifname);
239 header = (struct wrgg03_header *) buf;
240 memset(header, '\0', sizeof(struct wrgg03_header));
242 strncpy(header->signature, signature, sizeof(header->signature));
243 put_u32(&header->magic1, WRGG03_MAGIC, 0);
244 put_u32(&header->magic2, WRGG03_MAGIC, 0);
245 strncpy(header->version, version, sizeof(header->version));
246 strncpy(header->model, model, sizeof(header->model));
247 put_u32(&header->flag, flag, 0);
248 put_u32(&header->reserve, reserve, 0);
249 strncpy(header->buildno, buildno, sizeof(header->buildno));
250 put_u32(&header->size, st.st_size, big_endian);
251 put_u32(&header->offset, offset, big_endian);
252 strncpy(header->devname, devname, sizeof(header->devname));
254 get_digest(header, buf + sizeof(struct wrgg03_header), st.st_size);
256 outfile = fopen(ofname, "w");
257 if (outfile == NULL) {
258 ERRS("could not open \"%s\" for writing", ofname);
263 fwrite(buf, buflen, 1, outfile);
265 ERRS("unable to write to file %s", ofname);
275 if (res != EXIT_SUCCESS)