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