1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2011 Vasilis Tsiligiannis <b_tsiligiannis@silverton.gr> 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <byteswap.h> 10 #include <libgen.h> 11 #include <getopt.h> 12 #include <errno.h> 13 #include <sys/stat.h> 14 #include <endian.h> /* for __BYTE_ORDER */ 15 16 #define FALSE 0 17 #define TRUE 1 18 19 #if (__BYTE_ORDER == __LITTLE_ENDIAN) 20 # define HOST_TO_LE16(x) (x) 21 # define HOST_TO_LE32(x) (x) 22 # define HOST_TO_BE16(x) bswap_16(x) 23 # define HOST_TO_BE32(x) bswap_32(x) 24 #else 25 # define HOST_TO_LE16(x) bswap_16(x) 26 # define HOST_TO_LE32(x) bswap_32(x) 27 # define HOST_TO_BE16(x) (x) 28 # define HOST_TO_BE32(x) (x) 29 #endif 30 31 struct header 32 { 33 unsigned char sign[4]; 34 unsigned int start; 35 unsigned int flash; 36 unsigned char model[4]; 37 unsigned int size; 38 } __attribute__ ((packed)); 39 40 struct finfo 41 { 42 char *name; 43 off_t size; 44 }; 45 46 struct buf 47 { 48 char *start; 49 size_t size; 50 }; 51 52 static char *progname; 53 static int force_be = FALSE; 54 55 static void usage(int status) 56 { 57 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 58 59 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 60 fprintf(stream, 61 "\n" 62 "Options:\n" 63 " -s <sig> set image signature to <sig>\n" 64 " -m <model> set model to <model>\n" 65 " -i <file> read input from file <file>\n" 66 " -o <file> write output to file <file>\n" 67 " -f <flash> set flash address to <flash>\n" 68 " -S <start> set start address to <start>\n" 69 " -b big-endianness mode\n"); 70 71 exit(status); 72 } 73 74 static int strtou32(char *arg, unsigned int *val) 75 { 76 char *endptr = NULL; 77 78 errno = 0; 79 *val = strtoul(arg, &endptr, 0); 80 if (errno || (endptr == arg) || (*endptr && (endptr != NULL))) { 81 return EXIT_SUCCESS; 82 } 83 84 return EXIT_FAILURE; 85 } 86 87 static unsigned short fwcsum (struct buf *buf) { 88 int i; 89 unsigned short ret = 0; 90 91 for (i = 0; i < buf->size / 2; i++) { 92 if (force_be == FALSE) 93 ret -= ((unsigned short *) buf->start)[i]; 94 else 95 ret -= HOST_TO_BE16(((unsigned short *) buf->start)[i]); 96 } 97 98 return ret; 99 } 100 101 static int fwread(struct finfo *finfo, struct buf *buf) 102 { 103 FILE *f; 104 105 f = fopen(finfo->name, "r"); 106 if (!f) { 107 fprintf(stderr, "could not open \"%s\" for reading\n", finfo->name); 108 usage(EXIT_FAILURE); 109 } 110 111 buf->size = fread(buf->start, 1, finfo->size, f); 112 if (buf->size != finfo->size) { 113 fprintf(stderr, "unable to read from file \"%s\"\n", finfo->name); 114 usage(EXIT_FAILURE); 115 } 116 117 fclose(f); 118 119 return EXIT_SUCCESS; 120 } 121 122 static int fwwrite(struct finfo *finfo, struct buf *buf) 123 { 124 FILE *f; 125 126 f = fopen(finfo->name, "w"); 127 if (!f) { 128 fprintf(stderr, "could not open \"%s\" for writing\n", finfo->name); 129 usage(EXIT_FAILURE); 130 } 131 132 buf->size = fwrite(buf->start, 1, finfo->size, f); 133 if (buf->size != finfo->size) { 134 fprintf(stderr, "unable to write to file \"%s\"\n", finfo->name); 135 usage(EXIT_FAILURE); 136 } 137 138 fclose(f); 139 140 return EXIT_SUCCESS; 141 } 142 143 int main(int argc, char **argv) 144 { 145 struct stat st; 146 struct header header; 147 struct buf ibuf, obuf; 148 struct finfo ifinfo, ofinfo; 149 unsigned short csum; 150 int c; 151 152 ifinfo.name = ofinfo.name = NULL; 153 header.flash = header.size = header.start = 0; 154 progname = basename(argv[0]); 155 156 while((c = getopt(argc, argv, "i:o:m:s:f:S:h:b")) != -1) { 157 switch (c) { 158 case 'i': 159 ifinfo.name = optarg; 160 break; 161 case 'o': 162 ofinfo.name = optarg; 163 break; 164 case 'm': 165 if (strlen(optarg) != 4) { 166 fprintf(stderr, "model must be 4 characters long\n"); 167 usage(EXIT_FAILURE); 168 } 169 memcpy(header.model, optarg, 4); 170 break; 171 case 's': 172 if (strlen(optarg) != 4) { 173 fprintf(stderr, "signature must be 4 characters long\n"); 174 usage(EXIT_FAILURE); 175 } 176 memcpy(header.sign, optarg, 4); 177 break; 178 case 'h': 179 usage(EXIT_SUCCESS); 180 break; 181 case 'f': 182 if (!strtou32(optarg, &header.flash)) { 183 fprintf(stderr, "invalid flash address specified\n"); 184 usage(EXIT_FAILURE); 185 } 186 break; 187 case 'S': 188 if (!strtou32(optarg, &header.start)) { 189 fprintf(stderr, "invalid start address specified\n"); 190 usage(EXIT_FAILURE); 191 } 192 break; 193 case 'b': 194 force_be = TRUE; 195 break; 196 default: 197 usage(EXIT_FAILURE); 198 break; 199 } 200 } 201 202 if (ifinfo.name == NULL) { 203 fprintf(stderr, "no input file specified\n"); 204 usage(EXIT_FAILURE); 205 } 206 207 if (ofinfo.name == NULL) { 208 fprintf(stderr, "no output file specified\n"); 209 usage(EXIT_FAILURE); 210 } 211 212 if (stat(ifinfo.name, &st)) { 213 fprintf(stderr, "stat failed on %s\n", ifinfo.name); 214 usage(EXIT_FAILURE); 215 } 216 217 if (header.sign == NULL) { 218 fprintf(stderr, "no signature specified\n"); 219 usage(EXIT_FAILURE); 220 } 221 222 if (header.model == NULL) { 223 fprintf(stderr, "no model specified\n"); 224 usage(EXIT_FAILURE); 225 } 226 227 if (!header.flash) { 228 fprintf(stderr, "no flash address specified\n"); 229 usage(EXIT_FAILURE); 230 } 231 232 if (!header.start) { 233 fprintf(stderr, "no start address specified\n"); 234 usage(EXIT_FAILURE); 235 } 236 237 ifinfo.size = st.st_size; 238 239 obuf.size = ifinfo.size + sizeof(struct header) + sizeof(unsigned short); 240 if (obuf.size % sizeof(unsigned short)) 241 obuf.size++; 242 243 obuf.start = malloc(obuf.size); 244 if (!obuf.start) { 245 fprintf(stderr, "no memory for buffer\n"); 246 usage(EXIT_FAILURE); 247 } 248 memset(obuf.start, 0, obuf.size); 249 250 ibuf.size = ifinfo.size; 251 ibuf.start = obuf.start + sizeof(struct header); 252 253 if (fwread(&ifinfo, &ibuf)) 254 usage(EXIT_FAILURE); 255 256 if (force_be == FALSE) { 257 header.flash = HOST_TO_LE32(header.flash); 258 header.size = HOST_TO_LE32(obuf.size - sizeof(struct header)); 259 header.start = HOST_TO_LE32(header.start); 260 } else { 261 header.flash = HOST_TO_BE32(header.flash); 262 header.size = HOST_TO_BE32(obuf.size - sizeof(struct header)); 263 header.start = HOST_TO_BE32(header.start); 264 } 265 266 memcpy (obuf.start, &header, sizeof(struct header)); 267 268 if (force_be == FALSE) 269 csum = HOST_TO_LE16(fwcsum(&ibuf)); 270 else 271 csum = HOST_TO_BE16(fwcsum(&ibuf)); 272 273 memcpy(obuf.start + obuf.size - sizeof(unsigned short), 274 &csum, sizeof(unsigned short)); 275 276 ofinfo.size = obuf.size; 277 278 if (fwwrite(&ofinfo, &obuf)) 279 usage(EXIT_FAILURE); 280 281 return EXIT_SUCCESS; 282 } 283
This page was automatically generated by LXR 0.3.1. • OpenWrt