1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
4 * Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be>
21 #define ERR(fmt, ...) do { \
23 fprintf(stderr, "[%s] *** error: " fmt "\n", \
24 progname, ## __VA_ARGS__ ); \
27 #define ERRS(fmt, ...) do { \
30 fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
31 progname, ## __VA_ARGS__, strerror(save)); \
34 #define WRGG03_MAGIC 0x20080321
36 struct wrgg03_header
{
49 } __attribute__ ((packed
));
51 static char *progname
;
54 static char *signature
;
57 static uint32_t flag
= 0;
58 static uint32_t reserve
= 0;
60 static uint32_t offset
;
62 static int big_endian
;
64 void usage(int status
)
66 FILE *stream
= (status
!= EXIT_SUCCESS
) ? stderr
: stdout
;
68 fprintf(stream
, "Usage: %s [OPTIONS...]\n", progname
);
72 " -b create image in big endian format\n"
73 " -B <buildno> build number\n"
74 " -i <file> read input from the file <file>\n"
75 " -d <name> set device name to <name>\n"
76 " -m <model> model name\n"
77 " -o <file> write output to the file <file>\n"
78 " -O <offset> set offset to <offset>\n"
79 " -s <sig> set image signature to <sig>\n"
80 " -h show this screen\n"
86 static void put_u32(void *data
, uint32_t val
, int swap
)
88 unsigned char *p
= data
;
91 p
[0] = (val
>> 24) & 0xff;
92 p
[1] = (val
>> 16) & 0xff;
93 p
[2] = (val
>> 8) & 0xff;
96 p
[3] = (val
>> 24) & 0xff;
97 p
[2] = (val
>> 16) & 0xff;
98 p
[1] = (val
>> 8) & 0xff;
103 static void get_digest(struct wrgg03_header
*header
, char *data
, int size
)
109 MD5_Update(&ctx
, (char *)&header
->offset
, sizeof(header
->offset
));
110 MD5_Update(&ctx
, (char *)&header
->devname
, sizeof(header
->devname
));
111 MD5_Update(&ctx
, data
, size
);
113 MD5_Final((unsigned char *)header
->digest
, &ctx
);
116 int main(int argc
, char *argv
[])
118 struct wrgg03_header
*header
;
123 int res
= EXIT_FAILURE
;
125 FILE *outfile
, *infile
;
127 progname
= basename(argv
[0]);
132 c
= getopt(argc
, argv
, "bd:i:m:o:s:v:B:O:h");
162 offset
= strtoul(optarg
, NULL
, 0);
174 if (signature
== NULL
) {
175 ERR("no signature specified");
179 if (ifname
== NULL
) {
180 ERR("no input file specified");
184 if (ofname
== NULL
) {
185 ERR("no output file specified");
189 if (devname
== NULL
) {
190 ERR("no device name specified");
195 ERR("no model name specified");
199 if (buildno
== NULL
) {
200 ERR("no build number specified");
204 if (version
== NULL
) {
205 ERR("no version specified");
209 err
= stat(ifname
, &st
);
211 ERRS("stat failed on %s", ifname
);
215 buflen
= st
.st_size
+ sizeof(struct wrgg03_header
);
216 buf
= malloc(buflen
);
218 ERR("no memory for buffer\n");
222 infile
= fopen(ifname
, "r");
223 if (infile
== NULL
) {
224 ERRS("could not open \"%s\" for reading", ifname
);
229 fread(buf
+ sizeof(struct wrgg03_header
), st
.st_size
, 1, infile
);
231 ERRS("unable to read from file %s", ifname
);
235 header
= (struct wrgg03_header
*) buf
;
236 memset(header
, '\0', sizeof(struct wrgg03_header
));
238 strncpy(header
->signature
, signature
, sizeof(header
->signature
));
239 put_u32(&header
->magic1
, WRGG03_MAGIC
, 0);
240 put_u32(&header
->magic2
, WRGG03_MAGIC
, 0);
241 strncpy(header
->version
, version
, sizeof(header
->version
));
242 strncpy(header
->model
, model
, sizeof(header
->model
));
243 put_u32(&header
->flag
, flag
, 0);
244 put_u32(&header
->reserve
, reserve
, 0);
245 strncpy(header
->buildno
, buildno
, sizeof(header
->buildno
));
246 put_u32(&header
->size
, st
.st_size
, big_endian
);
247 put_u32(&header
->offset
, offset
, big_endian
);
248 strncpy(header
->devname
, devname
, sizeof(header
->devname
));
250 get_digest(header
, buf
+ sizeof(struct wrgg03_header
), st
.st_size
);
252 outfile
= fopen(ofname
, "w");
253 if (outfile
== NULL
) {
254 ERRS("could not open \"%s\" for writing", ofname
);
259 fwrite(buf
, buflen
, 1, outfile
);
261 ERRS("unable to write to file %s", ofname
);
271 if (res
!= EXIT_SUCCESS
)