1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2009-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 <libgen.h> 11 #include <getopt.h> /* for getopt() */ 12 #include <netinet/in.h> 13 14 #include "buffalo-lib.h" 15 16 #define ERR(fmt, ...) do { \ 17 fflush(0); \ 18 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 19 progname, ## __VA_ARGS__ ); \ 20 } while (0) 21 22 static char *region_table[] = { 23 "JP", "US", "EU", "AP", "TW", "KR" 24 }; 25 26 #define MAX_INPUT_FILES 2 27 28 static char *progname; 29 static char *ifname[MAX_INPUT_FILES]; 30 static ssize_t fsize[MAX_INPUT_FILES]; 31 static int num_files; 32 static char *ofname; 33 static char *product; 34 static char *brand; 35 static char *language; 36 static char *hwver; 37 static char *platform; 38 static int flag; 39 static char *major; 40 static char *minor = "1.01"; 41 static int skipcrc; 42 static uint32_t base1; 43 static uint32_t base2; 44 static char *region_code; 45 static uint32_t region_mask; 46 static int num_regions; 47 static int dhp; 48 49 void usage(int status) 50 { 51 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 52 53 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 54 fprintf(stream, 55 "\n" 56 "Options:\n" 57 " -a <platform> set platform to <platform>\n" 58 " -b <brand> set brand to <brand>\n" 59 " -c <base1>\n" 60 " -d <base2>\n" 61 " -f <flag> set flag to <flag>\n" 62 " -i <file> read input from the file <file>\n" 63 " -I <file> read input from the file <file> for DHP series\n" 64 " -l <language> set language to <language>\n" 65 " -m <version> set minor version to <version>\n" 66 " -o <file> write output to the file <file>\n" 67 " -p <product> set product to <product>\n" 68 " -r <region> set image region to <region>\n" 69 " valid regions: JP, US, EU, AP, TW, KR, M_\n" 70 " -s skip CRC calculation\n" 71 " -v <version> set major version to <version>\n" 72 " -w <version> set harwdware version to <version>\n" 73 " -h show this screen\n" 74 ); 75 76 exit(status); 77 } 78 79 static int check_params(void) 80 { 81 82 #define CHECKSTR(_var, _name, _len) do { \ 83 if ((_var) == NULL) { \ 84 ERR("no %s specified", (_name)); \ 85 return -1; \ 86 } \ 87 if ((_len) > 0 && \ 88 strlen((_var)) > ((_len) - 1)) { \ 89 ERR("%s is too long", (_name)); \ 90 return -1; \ 91 } \ 92 } while (0) 93 94 if (num_files == 0) 95 ERR("no input files specified"); 96 97 CHECKSTR(ofname, "output file", 0); 98 CHECKSTR(brand, "brand", TAG_BRAND_LEN); 99 CHECKSTR(product, "product", TAG_PRODUCT_LEN); 100 CHECKSTR(platform, "platform", TAG_PLATFORM_LEN); 101 CHECKSTR(major, "major version", TAG_VERSION_LEN); 102 CHECKSTR(minor, "minor version", TAG_VERSION_LEN); 103 CHECKSTR(language, "language", TAG_LANGUAGE_LEN); 104 105 if (hwver) 106 CHECKSTR(hwver, "hardware version", 2); 107 108 if (num_regions == 0) { 109 ERR("no region code specified"); 110 return -1; 111 } 112 113 return 0; 114 115 #undef CHECKSTR 116 } 117 118 static int process_region(char *reg) 119 { 120 int i; 121 122 if (strlen(reg) != 2) { 123 ERR("invalid region code '%s'", reg); 124 return -1; 125 } 126 127 if (strcmp(reg, "M_") == 0) { 128 region_code = reg; 129 region_mask |= ~0; 130 num_regions = 32; 131 return 0; 132 } 133 134 for (i = 0; i < ARRAY_SIZE(region_table); i++) 135 if (strcmp(reg, region_table[i]) == 0) { 136 region_code = reg; 137 region_mask |= 1 << i; 138 num_regions++; 139 return 0; 140 } 141 142 ERR("unknown region code '%s'", reg); 143 return -1; 144 } 145 146 static int process_ifname(char *name) 147 { 148 if (num_files >= ARRAY_SIZE(ifname)) { 149 ERR("too many input files specified"); 150 return -1; 151 } 152 153 ifname[num_files++] = name; 154 return 0; 155 } 156 157 static void fixup_tag(unsigned char *buf, ssize_t buflen) 158 { 159 struct buffalo_tag *tag = (struct buffalo_tag *) buf; 160 161 memset(tag, '\0', sizeof(*tag)); 162 163 memcpy(tag->brand, brand, strlen(brand)); 164 memcpy(tag->product, product, strlen(product)); 165 memcpy(tag->platform, platform, strlen(platform)); 166 memcpy(tag->ver_major, major, strlen(major)); 167 memcpy(tag->ver_minor, minor, strlen(minor)); 168 memcpy(tag->language, language, strlen(language)); 169 170 if (num_regions > 1) { 171 tag->region_code[0] = 'M'; 172 tag->region_code[1] = '_'; 173 tag->region_mask = htonl(region_mask); 174 } else { 175 memcpy(tag->region_code, region_code, 2); 176 } 177 178 tag->len = htonl(buflen); 179 tag->data_len = htonl(fsize[0]); 180 tag->base1 = htonl(base1); 181 tag->base2 = htonl(base2); 182 tag->flag = flag; 183 184 if (hwver) { 185 memcpy(tag->hwv, "hwv", 3); 186 memcpy(tag->hwv_val, hwver, strlen(hwver)); 187 } 188 189 if (!skipcrc) 190 tag->crc = htonl(buffalo_crc(buf, buflen)); 191 } 192 193 static void fixup_tag2(unsigned char *buf, ssize_t buflen) 194 { 195 struct buffalo_tag2 *tag = (struct buffalo_tag2 *) buf; 196 197 memset(tag, '\0', sizeof(*tag)); 198 199 memcpy(tag->brand, brand, strlen(brand)); 200 memcpy(tag->product, product, strlen(product)); 201 memcpy(tag->platform, platform, strlen(platform)); 202 memcpy(tag->ver_major, major, strlen(major)); 203 memcpy(tag->ver_minor, minor, strlen(minor)); 204 memcpy(tag->language, language, strlen(language)); 205 206 if (num_regions > 1) { 207 tag->region_code[0] = 'M'; 208 tag->region_code[1] = '_'; 209 tag->region_mask = htonl(region_mask); 210 } else { 211 memcpy(tag->region_code, region_code, 2); 212 } 213 214 tag->total_len = htonl(buflen); 215 tag->len1 = htonl(fsize[0]); 216 tag->len2 = htonl(fsize[1]); 217 tag->flag = flag; 218 219 if (hwver) { 220 memcpy(tag->hwv, "hwv", 3); 221 memcpy(tag->hwv_val, hwver, strlen(hwver)); 222 } 223 224 if (!skipcrc) 225 tag->crc = htonl(buffalo_crc(buf, buflen)); 226 } 227 228 static void fixup_tag3(unsigned char *buf, ssize_t totlen) 229 { 230 struct buffalo_tag3 *tag = (struct buffalo_tag3 *) buf; 231 232 memset(tag, '\0', sizeof(*tag)); 233 234 memcpy(tag->brand, brand, strlen(brand)); 235 memcpy(tag->product, product, strlen(product)); 236 memcpy(tag->platform, platform, strlen(platform)); 237 memcpy(tag->ver_major, major, strlen(major)); 238 memcpy(tag->ver_minor, minor, strlen(minor)); 239 memcpy(tag->language, language, strlen(language)); 240 241 if (num_regions > 1) { 242 tag->region_code[0] = 'M'; 243 tag->region_code[1] = '_'; 244 tag->region_mask = htonl(region_mask); 245 } else { 246 memcpy(tag->region_code, region_code, 2); 247 } 248 249 tag->total_len = htonl(totlen); 250 tag->len1 = htonl(fsize[0]); 251 tag->base2 = htonl(base2); 252 253 if (hwver) { 254 memcpy(tag->hwv, "hwv", 3); 255 memcpy(tag->hwv_val, hwver, strlen(hwver)); 256 } 257 } 258 259 static int tag_file(void) 260 { 261 unsigned char *buf; 262 ssize_t offset; 263 ssize_t hdrlen; 264 ssize_t buflen; 265 int err; 266 int ret = -1; 267 int i; 268 269 if (dhp) 270 hdrlen = sizeof(struct buffalo_tag3); 271 else if (num_files == 1) 272 hdrlen = sizeof(struct buffalo_tag); 273 else 274 hdrlen = sizeof(struct buffalo_tag2); 275 276 buflen = hdrlen; 277 278 for (i = 0; i < num_files; i++) { 279 fsize[i] = get_file_size(ifname[i]); 280 if (fsize[i] < 0) { 281 ERR("unable to get size of '%s'", ifname[i]); 282 goto out; 283 } 284 buflen += fsize[i]; 285 } 286 287 buf = malloc(buflen); 288 if (!buf) { 289 ERR("no memory for buffer\n"); 290 goto out; 291 } 292 293 offset = hdrlen; 294 for (i = 0; i < num_files; i++) { 295 err = read_file_to_buf(ifname[i], buf + offset, fsize[i]); 296 if (err) { 297 ERR("unable to read from file '%s'", ifname[i]); 298 goto free_buf; 299 } 300 301 offset += fsize[i]; 302 } 303 304 if (dhp) 305 fixup_tag3(buf, fsize[0] + 200); 306 else if (num_files == 1) 307 fixup_tag(buf, buflen); 308 else 309 fixup_tag2(buf, buflen); 310 311 err = write_buf_to_file(ofname, buf, buflen); 312 if (err) { 313 ERR("unable to write to file '%s'", ofname); 314 goto free_buf; 315 } 316 317 ret = 0; 318 319 free_buf: 320 free(buf); 321 out: 322 return ret; 323 } 324 325 int main(int argc, char *argv[]) 326 { 327 int res = EXIT_FAILURE; 328 int err; 329 330 progname = basename(argv[0]); 331 332 while ( 1 ) { 333 int c; 334 335 c = getopt(argc, argv, "a:b:c:d:f:hi:l:m:o:p:r:sv:w:I:"); 336 if (c == -1) 337 break; 338 339 switch (c) { 340 case 'a': 341 platform = optarg; 342 break; 343 case 'b': 344 brand = optarg; 345 break; 346 case 'c': 347 base1 = strtoul(optarg, NULL, 16); 348 break; 349 case 'd': 350 base2 = strtoul(optarg, NULL, 16); 351 break; 352 case 'f': 353 flag = strtoul(optarg, NULL, 2); 354 break; 355 case 'I': 356 dhp = 1; 357 /* FALLTHROUGH */ 358 case 'i': 359 err = process_ifname(optarg); 360 if (err) 361 goto out; 362 break; 363 case 'l': 364 language = optarg; 365 break; 366 case 'm': 367 minor = optarg; 368 break; 369 case 'o': 370 ofname = optarg; 371 break; 372 case 'p': 373 product = optarg; 374 break; 375 case 'r': 376 err = process_region(optarg); 377 if (err) 378 goto out; 379 break; 380 case 's': 381 skipcrc = 1; 382 break; 383 case 'v': 384 major = optarg; 385 break; 386 case 'w': 387 hwver = optarg; 388 break; 389 case 'h': 390 usage(EXIT_SUCCESS); 391 break; 392 default: 393 usage(EXIT_FAILURE); 394 break; 395 } 396 } 397 398 err = check_params(); 399 if (err) 400 goto out; 401 402 err = tag_file(); 403 if (err) 404 goto out; 405 406 res = EXIT_SUCCESS; 407 408 out: 409 return res; 410 } 411
This page was automatically generated by LXR 0.3.1. • OpenWrt