From fb9a672c788eeb0e77cfd227d425c1cc6468b923 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 31 May 2011 22:53:21 +0000 Subject: tools/firmware-utils: add buffalo specific fw tools SVN-Revision: 27050 --- tools/firmware-utils/src/buffalo-tag.c | 300 +++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 tools/firmware-utils/src/buffalo-tag.c (limited to 'tools/firmware-utils/src/buffalo-tag.c') diff --git a/tools/firmware-utils/src/buffalo-tag.c b/tools/firmware-utils/src/buffalo-tag.c new file mode 100644 index 0000000..e3f7625 --- /dev/null +++ b/tools/firmware-utils/src/buffalo-tag.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2009-2011 Gabor Juhos + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include /* for getopt() */ +#include + +#include "buffalo-lib.h" + +#define ERR(fmt, ...) do { \ + fflush(0); \ + fprintf(stderr, "[%s] *** error: " fmt "\n", \ + progname, ## __VA_ARGS__ ); \ +} while (0) + +static char *region_table[] = { + "JP", "US", "EU", "AP", "TW", "KR" +}; + +static char *progname; +static char *ifname; +static char *ofname; +static char *product; +static char *brand; +static char *language; +static char *hwver; +static char *platform; +static int flag; +static char *major; +static char *minor = "1.01"; +static int skipcrc; +static uint32_t base1; +static uint32_t base2; +static char *region_code; +static uint32_t region_mask; +static int num_regions; + +void usage(int status) +{ + FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; + + fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); + fprintf(stream, +"\n" +"Options:\n" +" -a set platform to \n" +" -b set brand to \n" +" -c \n" +" -d \n" +" -f set flag to \n" +" -i read input from the file \n" +" -l set language to \n" +" -m set minor version to \n" +" -o write output to the file \n" +" -p set product to \n" +" -r set image region to \n" +" valid regions: JP, US, EU, AP, TW, KR, M_\n" +" -s skip CRC calculation\n" +" -v set major version to \n" +" -w set harwdware version to \n" +" -h show this screen\n" + ); + + exit(status); +} + +static int check_params(void) +{ + +#define CHECKSTR(_var, _name, _len) do { \ + if ((_var) == NULL) { \ + ERR("no %s specified", (_name)); \ + return -1; \ + } \ + if ((_len) > 0 && \ + strlen((_var)) > ((_len) - 1)) { \ + ERR("%s is too long", (_name)); \ + return -1; \ + } \ +} while (0) + + CHECKSTR(ifname, "input file", 0); + CHECKSTR(ofname, "output file", 0); + CHECKSTR(brand, "brand", TAG_BRAND_LEN); + CHECKSTR(product, "product", TAG_PRODUCT_LEN); + CHECKSTR(platform, "platform", TAG_PLATFORM_LEN); + CHECKSTR(major, "major version", TAG_VERSION_LEN); + CHECKSTR(minor, "minor version", TAG_VERSION_LEN); + CHECKSTR(language, "language", TAG_LANGUAGE_LEN); + CHECKSTR(hwver, "hardware version", 2); + + if (num_regions == 0) { + ERR("no region code specified"); + return -1; + } + + return 0; + +#undef CHECKSTR +} + +static int process_region(char *reg) +{ + int i; + + if (strlen(reg) != 2) { + ERR("invalid region code '%s'", reg); + return -1; + } + + if (strcmp(reg, "M_") == 0) { + region_code = reg; + region_mask |= ~0; + num_regions = 32; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(region_table); i++) + if (strcmp(reg, region_table[i]) == 0) { + region_code = reg; + region_mask |= 1 << i; + num_regions++; + return 0; + } + + ERR("unknown region code '%s'", reg); + return -1; +} + +static void fixup_tag(unsigned char *buf, ssize_t buflen, ssize_t datalen) +{ + struct buffalo_tag *tag = (struct buffalo_tag *) buf; + + memset(tag, '\0', sizeof(*tag)); + + memcpy(tag->brand, brand, strlen(brand)); + memcpy(tag->product, product, strlen(product)); + memcpy(tag->platform, platform, strlen(platform)); + memcpy(tag->ver_major, major, strlen(major)); + memcpy(tag->ver_minor, minor, strlen(minor)); + memcpy(tag->language, language, strlen(language)); + + if (num_regions > 1) { + tag->region_code[0] = 'M'; + tag->region_code[1] = '_'; + tag->region_mask = htonl(region_mask); + } else { + memcpy(tag->region_code, region_code, 2); + } + + tag->len = htonl(buflen); + tag->data_len = htonl(datalen); + tag->base1 = htonl(base1); + tag->base2 = htonl(base2); + tag->flag = flag; + + if (hwver) { + memcpy(tag->hwv, "hwv", 3); + memcpy(tag->hwv_val, hwver, strlen(hwver)); + } + + if (!skipcrc) + tag->crc = htonl(buffalo_crc(buf, buflen)); +} + +static int tag_file(void) +{ + unsigned char *buf; + ssize_t fsize; + ssize_t buflen; + int err; + int ret = -1; + + fsize = get_file_size(ifname); + if (fsize < 0) { + ERR("unable to get size of '%s'", ifname); + goto out; + } + + buflen = fsize + sizeof(struct buffalo_tag); + buf = malloc(buflen); + if (!buf) { + ERR("no memory for buffer\n"); + goto out; + } + + err = read_file_to_buf(ifname, buf + sizeof(struct buffalo_tag), + fsize); + if (err) { + ERR("unable to read from file '%s'", ifname); + goto free_buf; + } + + fixup_tag(buf, buflen, fsize); + + err = write_buf_to_file(ofname, buf, buflen); + if (err) { + ERR("unable to write to file '%s'", ofname); + goto free_buf; + } + + ret = 0; + +free_buf: + free(buf); +out: + return ret; +} + +int main(int argc, char *argv[]) +{ + int res = EXIT_FAILURE; + int err; + + progname = basename(argv[0]); + + while ( 1 ) { + int c; + + c = getopt(argc, argv, "a:b:c:d:f:hi:l:m:o:p:r:sv:w:"); + if (c == -1) + break; + + switch (c) { + case 'a': + platform = optarg; + break; + case 'b': + brand = optarg; + break; + case 'c': + base1 = strtoul(optarg, NULL, 16); + break; + case 'd': + base2 = strtoul(optarg, NULL, 16); + break; + case 'f': + flag = strtoul(optarg, NULL, 2); + break; + case 'i': + ifname = optarg; + break; + case 'l': + language = optarg; + break; + case 'm': + minor = optarg; + break; + case 'o': + ofname = optarg; + break; + case 'p': + product = optarg; + break; + case 'r': + err = process_region(optarg); + if (err) + goto out; + break; + case 's': + skipcrc = 1; + break; + case 'v': + major = optarg; + break; + case 'w': + hwver = optarg; + break; + case 'h': + usage(EXIT_SUCCESS); + break; + default: + usage(EXIT_FAILURE); + break; + } + } + + err = check_params(); + if (err) + goto out; + + err = tag_file(); + if (err) + goto out; + + res = EXIT_SUCCESS; + +out: + return res; +} -- cgit v1.1