• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mkwrggimg.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
  4  *  Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be>
  5  */
  6 
  7 #define _ANSI_SOURCE
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <stdint.h>
 11 #include <string.h>
 12 #include <unistd.h>
 13 #include <libgen.h>
 14 #include <getopt.h>
 15 #include <stdarg.h>
 16 #include <errno.h>
 17 #include <sys/stat.h>
 18 
 19 #include "md5.h"
 20 
 21 #define ERR(fmt, ...) do { \
 22         fflush(0); \
 23         fprintf(stderr, "[%s] *** error: " fmt "\n", \
 24                         progname, ## __VA_ARGS__ ); \
 25 } while (0)
 26 
 27 #define ERRS(fmt, ...) do { \
 28         int save = errno; \
 29         fflush(0); \
 30         fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
 31                         progname, ## __VA_ARGS__, strerror(save)); \
 32 } while (0)
 33 
 34 #define WRGG03_MAGIC    0x20080321
 35 
 36 struct wrgg03_header {
 37         char            signature[32];
 38         uint32_t        magic1;
 39         uint32_t        magic2;
 40         char            version[16];
 41         char            model[16];
 42         uint32_t        flag[2];
 43         uint32_t        reserve[2];
 44         char            buildno[16];
 45         uint32_t        size;
 46         uint32_t        offset;
 47         char            devname[32];
 48         char            digest[16];
 49 } __attribute__ ((packed));
 50 
 51 static char *progname;
 52 static char *ifname;
 53 static char *ofname;
 54 static char *signature;
 55 static char *version;
 56 static char *model;
 57 static uint32_t flag = 0;
 58 static uint32_t reserve = 0;
 59 static char *buildno;
 60 static uint32_t offset;
 61 static char *devname;
 62 static int big_endian;
 63 
 64 void usage(int status)
 65 {
 66         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
 67 
 68         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
 69         fprintf(stream,
 70 "\n"
 71 "Options:\n"
 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"
 81         );
 82 
 83         exit(status);
 84 }
 85 
 86 static void put_u32(void *data, uint32_t val, int swap)
 87 {
 88         unsigned char *p = data;
 89 
 90         if (swap) {
 91                 p[0] = (val >> 24) & 0xff;
 92                 p[1] = (val >> 16) & 0xff;
 93                 p[2] = (val >> 8) & 0xff;
 94                 p[3] = val & 0xff;
 95         } else {
 96                 p[3] = (val >> 24) & 0xff;
 97                 p[2] = (val >> 16) & 0xff;
 98                 p[1] = (val >> 8) & 0xff;
 99                 p[0] = val & 0xff;
100         }
101 }
102 
103 static void get_digest(struct wrgg03_header *header, char *data, int size)
104 {
105         MD5_CTX ctx;
106 
107         MD5_Init(&ctx);
108 
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);
112 
113         MD5_Final((unsigned char *)header->digest, &ctx);
114 }
115 
116 int main(int argc, char *argv[])
117 {
118         struct wrgg03_header *header;
119         char *buf;
120         struct stat st;
121         int buflen;
122         int err;
123         int res = EXIT_FAILURE;
124 
125         FILE *outfile, *infile;
126 
127         progname = basename(argv[0]);
128 
129         while ( 1 ) {
130                 int c;
131 
132                 c = getopt(argc, argv, "bd:i:m:o:s:v:B:O:h");
133                 if (c == -1)
134                         break;
135 
136                 switch (c) {
137                 case 'b':
138                         big_endian = 1;
139                         break;
140                 case 'B':
141                         buildno = optarg;
142                         break;
143                 case 'd':
144                         devname = optarg;
145                         break;
146                 case 'i':
147                         ifname = optarg;
148                         break;
149                 case 'm':
150                         model = optarg;
151                         break;
152                 case 'o':
153                         ofname = optarg;
154                         break;
155                 case 's':
156                         signature = optarg;
157                         break;
158                 case 'v':
159                         version = optarg;
160                         break;
161                 case 'O':
162                         offset = strtoul(optarg, NULL, 0);
163                         break;
164                 case 'h':
165                         usage(EXIT_SUCCESS);
166                         break;
167 
168                 default:
169                         usage(EXIT_FAILURE);
170                         break;
171                 }
172         }
173 
174         if (signature == NULL) {
175                 ERR("no signature specified");
176                 goto err;
177         }
178 
179         if (ifname == NULL) {
180                 ERR("no input file specified");
181                 goto err;
182         }
183 
184         if (ofname == NULL) {
185                 ERR("no output file specified");
186                 goto err;
187         }
188 
189         if (devname == NULL) {
190                 ERR("no device name specified");
191                 goto err;
192         }
193 
194         if (model == NULL) {
195                 ERR("no model name specified");
196                 goto err;
197         }
198 
199         if (buildno == NULL) {
200                 ERR("no build number specified");
201                 goto err;
202         }
203 
204         if (version == NULL) {
205                 ERR("no version specified");
206                 goto err;
207         }
208 
209         err = stat(ifname, &st);
210         if (err){
211                 ERRS("stat failed on %s", ifname);
212                 goto err;
213         }
214 
215         buflen = st.st_size + sizeof(struct wrgg03_header);
216         buf = malloc(buflen);
217         if (!buf) {
218                 ERR("no memory for buffer\n");
219                 goto err;
220         }
221 
222         infile = fopen(ifname, "r");
223         if (infile == NULL) {
224                 ERRS("could not open \"%s\" for reading", ifname);
225                 goto err_free;
226         }
227 
228         errno = 0;
229         fread(buf + sizeof(struct wrgg03_header), st.st_size, 1, infile);
230         if (errno != 0) {
231                 ERRS("unable to read from file %s", ifname);
232                 goto close_in;
233         }
234 
235         header = (struct wrgg03_header *) buf;
236         memset(header, '\0', sizeof(struct wrgg03_header));
237 
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));
249 
250         get_digest(header, buf + sizeof(struct wrgg03_header), st.st_size);
251 
252         outfile = fopen(ofname, "w");
253         if (outfile == NULL) {
254                 ERRS("could not open \"%s\" for writing", ofname);
255                 goto close_in;
256         }
257 
258         errno = 0;
259         fwrite(buf, buflen, 1, outfile);
260         if (errno) {
261                 ERRS("unable to write to file %s", ofname);
262                 goto close_out;
263         }
264 
265         fflush(outfile);
266 
267         res = EXIT_SUCCESS;
268 
269 close_out:
270         fclose(outfile);
271         if (res != EXIT_SUCCESS)
272                 unlink(ofname);
273 close_in:
274         fclose(infile);
275 err_free:
276         free(buf);
277 err:
278         return res;
279 }
280 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt