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

Sources/firmware-utils/src/mkwrgimg.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt