1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org> 4 */ 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <unistd.h> /* for unlink() */ 10 #include <libgen.h> 11 #include <getopt.h> /* for getopt() */ 12 #include <stdarg.h> 13 #include <errno.h> 14 #include <sys/stat.h> 15 16 #include "cyg_crc.h" 17 18 #include <arpa/inet.h> 19 #include <netinet/in.h> 20 21 #define IH_MAGIC 0x27051956 /* Image Magic Number */ 22 #define IH_NMLEN 32 /* Image Name Length */ 23 24 #define UM_MAGIC 0x55525F46 25 #define UM_HEADER_LEN 12 26 27 /* 28 * all data in network byte order (aka natural aka bigendian) 29 */ 30 struct u_media_header { 31 uint32_t ih_magic; /* Image Header Magic Number */ 32 uint32_t ih_hcrc; /* Image Header CRC Checksum */ 33 uint32_t ih_time; /* Image Creation Timestamp */ 34 uint32_t ih_size; /* Image Data Size */ 35 uint32_t ih_load; /* Data Load Address */ 36 uint32_t ih_ep; /* Entry Point Address */ 37 uint32_t ih_dcrc; /* Image Data CRC Checksum */ 38 uint8_t ih_os; /* Operating System */ 39 uint8_t ih_arch; /* CPU architecture */ 40 uint8_t ih_type; /* Image Type */ 41 uint8_t ih_comp; /* Compression Type */ 42 uint8_t ih_name[IH_NMLEN - UM_HEADER_LEN]; /* Image Name */ 43 44 uint32_t ih_UMedia_magic; /* U-Media magic number */ 45 uint32_t ih_UMedia_boardID; /* U-Media board ID */ 46 uint8_t ih_UMedia_imageType; /* U-Media image type */ 47 uint8_t ih_UMedia_LoadDefault; /* U-Media load to factory default setting */ 48 uint8_t ih_UMedia_temp1; /* U-Media didn't use this tag */ 49 uint8_t ih_UMedia_temp2; /* U-Media didn't use this tag */ 50 } __attribute__ ((packed)); 51 52 struct if_info { 53 char *file_name; /* name of the file */ 54 uint32_t file_size; /* length of the file */ 55 }; 56 57 static char *progname; 58 static char *ofname; 59 static struct if_info if_info; 60 static int factory_defaults; 61 static uint32_t board_id; 62 static uint8_t image_type; 63 64 /* 65 * Message macros 66 */ 67 #define ERR(fmt, ...) do { \ 68 fflush(0); \ 69 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 70 progname, ## __VA_ARGS__ ); \ 71 } while (0) 72 73 #define ERRS(fmt, ...) do { \ 74 int save = errno; \ 75 fflush(0); \ 76 fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \ 77 progname, ## __VA_ARGS__, strerror(save)); \ 78 } while (0) 79 80 #define DBG(fmt, ...) do { \ 81 fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ 82 } while (0) 83 84 static void usage(int status) 85 { 86 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 87 88 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 89 fprintf(stream, 90 "\n" 91 "Options:\n" 92 " -B <board_id> set board ID to <board_id>\n" 93 " -i <file> read input from the file <file>\n" 94 " -F load factory defaults\n" 95 " -o <file> write output to the file <file>\n" 96 " -T <type> set image type to <type>\n" 97 " -h show this screen\n" 98 ); 99 100 exit(status); 101 } 102 103 static int str2u32(char *arg, uint32_t *val) 104 { 105 char *err = NULL; 106 uint32_t t; 107 108 errno=0; 109 t = strtoul(arg, &err, 0); 110 if (errno || (err==arg) || ((err != NULL) && *err)) { 111 return -1; 112 } 113 114 *val = t; 115 return 0; 116 } 117 118 static int str2u8(char *arg, uint8_t *val) 119 { 120 char *err = NULL; 121 uint32_t t; 122 123 errno=0; 124 t = strtoul(arg, &err, 0); 125 if (errno || (err==arg) || ((err != NULL) && *err)) { 126 return -1; 127 } 128 129 if (t > 255) 130 return -1; 131 132 *val = t; 133 return 0; 134 } 135 136 static int get_file_stat(struct if_info *fdata) 137 { 138 struct stat st; 139 int res; 140 141 if (fdata->file_name == NULL) 142 return 0; 143 144 res = stat(fdata->file_name, &st); 145 if (res){ 146 ERRS("stat failed on %s", fdata->file_name); 147 return res; 148 } 149 150 fdata->file_size = st.st_size; 151 return 0; 152 } 153 154 static int read_to_buf(struct if_info *fdata, char *buf) 155 { 156 FILE *f; 157 int ret = EXIT_FAILURE; 158 159 f = fopen(fdata->file_name, "r"); 160 if (f == NULL) { 161 ERRS("could not open \"%s\" for reading", fdata->file_name); 162 goto out; 163 } 164 165 errno = 0; 166 fread(buf, fdata->file_size, 1, f); 167 if (errno != 0) { 168 ERRS("unable to read from file \"%s\"", fdata->file_name); 169 goto out_close; 170 } 171 172 ret = EXIT_SUCCESS; 173 174 out_close: 175 fclose(f); 176 out: 177 return ret; 178 } 179 180 static int check_options(void) 181 { 182 int ret; 183 184 if (ofname == NULL) { 185 ERR("no %s specified", "output file"); 186 return -1; 187 } 188 189 if (if_info.file_name == NULL) { 190 ERR("no %s specified", "input file"); 191 return -1; 192 } 193 194 ret = get_file_stat(&if_info); 195 if (ret) 196 return ret; 197 198 return 0; 199 } 200 201 static int write_fw(char *data, int len) 202 { 203 FILE *f; 204 int ret = EXIT_FAILURE; 205 206 f = fopen(ofname, "w"); 207 if (f == NULL) { 208 ERRS("could not open \"%s\" for writing", ofname); 209 goto out; 210 } 211 212 errno = 0; 213 fwrite(data, len, 1, f); 214 if (errno) { 215 ERRS("unable to write output file"); 216 goto out_flush; 217 } 218 219 ret = EXIT_SUCCESS; 220 221 out_flush: 222 fflush(f); 223 fclose(f); 224 if (ret != EXIT_SUCCESS) { 225 unlink(ofname); 226 } 227 out: 228 return ret; 229 } 230 231 static int fix_header(void) 232 { 233 int buflen; 234 char *buf; 235 uint32_t crc, crc_orig; 236 struct u_media_header *hdr; 237 int ret = EXIT_FAILURE; 238 239 buflen = if_info.file_size; 240 if (buflen < sizeof(*hdr)) { 241 ERR("invalid input file\n"); 242 return ret; 243 } 244 245 buf = malloc(buflen); 246 if (!buf) { 247 ERR("no memory for buffer\n"); 248 goto out; 249 } 250 251 ret = read_to_buf(&if_info, buf); 252 if (ret) 253 goto out_free_buf; 254 255 hdr = (struct u_media_header *) buf; 256 if (ntohl(hdr->ih_magic) != IH_MAGIC) { 257 ERR("invalid input file, bad magic\n"); 258 goto out_free_buf; 259 } 260 261 /* verify header CRC */ 262 crc_orig = ntohl(hdr->ih_hcrc); 263 hdr->ih_hcrc = 0; 264 crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr)); 265 if (crc != crc_orig) { 266 ERR("invalid input file, bad header CRC\n"); 267 goto out_free_buf; 268 } 269 270 hdr->ih_name[IH_NMLEN - UM_HEADER_LEN - 1] = '\0'; 271 272 /* set U-Media specific fields */ 273 hdr->ih_UMedia_magic = htonl(UM_MAGIC); 274 hdr->ih_UMedia_boardID = htonl(board_id); 275 hdr->ih_UMedia_imageType = image_type; 276 hdr->ih_UMedia_LoadDefault = (factory_defaults) ? 1 : 0; 277 278 /* update header CRC */ 279 crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr)); 280 hdr->ih_hcrc = htonl(crc); 281 282 ret = write_fw(buf, buflen); 283 if (ret) 284 goto out_free_buf; 285 286 DBG("U-Media header fixed in \"%s\"", ofname); 287 288 ret = EXIT_SUCCESS; 289 290 out_free_buf: 291 free(buf); 292 out: 293 return ret; 294 } 295 296 int main(int argc, char *argv[]) 297 { 298 int ret = EXIT_FAILURE; 299 300 progname = basename(argv[0]); 301 302 while (1) { 303 int c; 304 305 c = getopt(argc, argv, "B:Fi:o:T:h"); 306 if (c == -1) 307 break; 308 309 switch (c) { 310 case 'B': 311 if (str2u32(optarg, &board_id)) { 312 ERR("%s is invalid '%s'", 313 "board ID", optarg); 314 goto out; 315 } 316 break; 317 case 'T': 318 if (str2u8(optarg, &image_type)) { 319 ERR("%s is invalid '%s'", 320 "image type", optarg); 321 goto out; 322 } 323 break; 324 case 'F': 325 factory_defaults = 1; 326 break; 327 case 'i': 328 if_info.file_name = optarg; 329 break; 330 case 'o': 331 ofname = optarg; 332 break; 333 case 'h': 334 usage(EXIT_SUCCESS); 335 break; 336 default: 337 usage(EXIT_FAILURE); 338 break; 339 } 340 } 341 342 ret = check_options(); 343 if (ret) 344 goto out; 345 346 ret = fix_header(); 347 348 out: 349 return ret; 350 } 351
This page was automatically generated by LXR 0.3.1. • OpenWrt