X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/blobdiff_plain/2cbaa8109fd7bb3668509484b469e6c41f8510f0..867564c59f3e0687e581efe822365d3ef599c76f:/flash-hmcfgusb.c diff --git a/flash-hmcfgusb.c b/flash-hmcfgusb.c index b1f554c..8c858f2 100644 --- a/flash-hmcfgusb.c +++ b/flash-hmcfgusb.c @@ -1,6 +1,6 @@ /* flasher for HM-CFG-USB * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2013-16 Michael Gernoth * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -36,12 +36,10 @@ #include #include "hexdump.h" +#include "firmware.h" #include "version.h" #include "hmcfgusb.h" -/* This might be wrong, but it works for current fw */ -#define MAX_BLOCK_LENGTH 512 - struct recv_data { int ack; }; @@ -58,29 +56,13 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) return 1; } -static uint8_t ascii_to_nibble(uint8_t a) +void flash_hmcfgusb_syntax(char *prog) { - uint8_t c = 0x00; - - if ((a >= '0') && (a <= '9')) { - c = a - '0'; - } else if ((a >= 'A') && (a <= 'F')) { - c = (a - 'A') + 10; - } else if ((a >= 'a') && (a <= 'f')) { - c = (a - 'a') + 10; - } + fprintf(stderr, "Syntax: %s [options] filename.enc\n\n", prog); + fprintf(stderr, "Possible options:\n"); + fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n"); + fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); - return c; -} - -static int validate_nibble(uint8_t a) -{ - if (((a >= '0') && (a <= '9')) || - ((a >= 'A') && (a <= 'F')) || - ((a >= 'a') && (a <= 'f'))) - return 1; - - return 0; } int main(int argc, char **argv) @@ -88,126 +70,55 @@ int main(int argc, char **argv) const char twiddlie[] = { '-', '\\', '|', '/' }; struct hmcfgusb_dev *dev; struct recv_data rdata; - struct stat stat_buf; - uint8_t buf[4096]; uint16_t len; - uint8_t **fw = NULL; - int fw_blocks = 0; + struct firmware *fw; + char *serial = NULL; + char *filename = NULL; int block; - int fd; int pfd; - int r; - int i; + int opt; int debug = 0; - printf("HM-CFG-USB flasher version " VERSION "\n\n"); - - if (argc != 2) { - if (argc == 1) - fprintf(stderr, "Missing firmware filename!\n\n"); - - fprintf(stderr, "Syntax: %s hmusbif.enc\n\n", argv[0]); - exit(EXIT_FAILURE); - } - - if (stat(argv[1], &stat_buf) == -1) { - fprintf(stderr, "Can't stat %s: %s\n", argv[1], strerror(errno)); - exit(EXIT_FAILURE); - } - - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Can't open %s: %s", argv[1], strerror(errno)); - exit(EXIT_FAILURE); - } - - printf("Reading firmware from %s...\n", argv[1]); - do { - memset(buf, 0, sizeof(buf)); - r = read(fd, buf, 4); - if (r < 0) { - perror("read"); - exit(EXIT_FAILURE); - } else if (r == 0) { - break; - } else if (r != 4) { - printf("can't get length information!\n"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < r; i++) { - if (!validate_nibble(buf[i])) { - fprintf(stderr, "Firmware file not valid!\n"); + while((opt = getopt(argc, argv, "S:V")) != -1) { + switch (opt) { + case 'S': + serial = optarg; + break; + case 'V': + printf("flash-hmcfgusb " VERSION "\n"); + printf("Copyright (c) 2013-16 Michael Gernoth\n\n"); + exit(EXIT_SUCCESS); + case 'h': + case ':': + case '?': + default: + flash_hmcfgusb_syntax(argv[0]); exit(EXIT_FAILURE); - } - } - - len = (ascii_to_nibble(buf[0]) & 0xf)<< 4; - len |= ascii_to_nibble(buf[1]) & 0xf; - len <<= 8; - len |= (ascii_to_nibble(buf[2]) & 0xf)<< 4; - len |= ascii_to_nibble(buf[3]) & 0xf; - - /* This might be wrong, but it works for current fw */ - if (len > MAX_BLOCK_LENGTH) { - fprintf(stderr, "Invalid block-length %u > %u for block %d!\n", len, MAX_BLOCK_LENGTH, fw_blocks+1); - exit(EXIT_FAILURE); - } - - fw = realloc(fw, sizeof(uint8_t*) * (fw_blocks + 1)); - if (fw == NULL) { - perror("Can't reallocate fw-blocklist"); - exit(EXIT_FAILURE); - } - - fw[fw_blocks] = malloc(len + 4); - if (fw[fw_blocks] == NULL) { - perror("Can't allocate memory for fw-block"); - exit(EXIT_FAILURE); - } - - fw[fw_blocks][0] = (fw_blocks >> 8) & 0xff; - fw[fw_blocks][1] = fw_blocks & 0xff; - fw[fw_blocks][2] = (len >> 8) & 0xff; - fw[fw_blocks][3] = len & 0xff; - - r = read(fd, buf, len * 2); - if (r < 0) { - perror("read"); - exit(EXIT_FAILURE); - } else if (r < len * 2) { - fprintf(stderr, "short read, aborting (%d < %d)\n", r, len * 2); - exit(EXIT_FAILURE); + break; } + } - for (i = 0; i < r; i+=2) { - if ((!validate_nibble(buf[i])) || - (!validate_nibble(buf[i+1]))) { - fprintf(stderr, "Firmware file not valid!\n"); - exit(EXIT_FAILURE); - } - - fw[fw_blocks][(i/2) + 4] = (ascii_to_nibble(buf[i]) & 0xf)<< 4; - fw[fw_blocks][(i/2) + 4] |= ascii_to_nibble(buf[i+1]) & 0xf; - } + if (optind == argc - 1) { + filename = argv[optind]; + } - fw_blocks++; - if (debug) - printf("Firmware block %d with length %u read.\n", fw_blocks, len); - } while(r > 0); + printf("HM-CFG-USB flasher version " VERSION "\n\n"); - if (fw_blocks == 0) { - fprintf(stderr, "Firmware file not valid!\n"); + if (!filename) { + fprintf(stderr, "Missing firmware filename!\n\n"); + flash_hmcfgusb_syntax(argv[0]); exit(EXIT_FAILURE); } - printf("Firmware with %d blocks successfully read.\n", fw_blocks); + fw = firmware_read_firmware(filename, debug); + if (!fw) + exit(EXIT_FAILURE); hmcfgusb_set_debug(debug); memset(&rdata, 0, sizeof(rdata)); - dev = hmcfgusb_init(parse_hmcfgusb, &rdata); + dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial); if (!dev) { fprintf(stderr, "Can't initialize HM-CFG-USB\n"); exit(EXIT_FAILURE); @@ -215,23 +126,22 @@ int main(int argc, char **argv) if (!dev->bootloader) { fprintf(stderr, "\nHM-CFG-USB not in bootloader mode, entering bootloader.\n"); - hmcfgusb_enter_bootloader(dev); fprintf(stderr, "\nWaiting for device to reappear...\n"); do { + if (dev) { + if (!dev->bootloader) + hmcfgusb_enter_bootloader(dev); + hmcfgusb_close(dev); + } sleep(1); - } while ((dev = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL); - - if (!dev->bootloader) { - fprintf(stderr, "Can't enter bootloader, giving up!\n"); - exit(EXIT_FAILURE); - } + } while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial)) == NULL) || (!dev->bootloader)); } printf("\nHM-CFG-USB opened.\n\n"); - printf("Flashing %d blocks", fw_blocks); + printf("Flashing %d blocks", fw->fw_blocks); if (debug) { printf("\n"); } else { @@ -239,17 +149,17 @@ int main(int argc, char **argv) fflush(stdout); } - for (block = 0; block < fw_blocks; block++) { - len = fw[block][2] << 8; - len |= fw[block][3]; + for (block = 0; block < fw->fw_blocks; block++) { + len = fw->fw[block][2] << 8; + len |= fw->fw[block][3]; len += 4; /* block nr., length */ if (debug) - hexdump(fw[block], len, "F> "); + hexdump(fw->fw[block], len, "F> "); rdata.ack = 0; - if (!hmcfgusb_send(dev, fw[block], len, 0)) { + if (!hmcfgusb_send(dev, fw->fw[block], len, 0)) { perror("\n\nhmcfgusb_send"); exit(EXIT_FAILURE); } @@ -258,10 +168,12 @@ int main(int argc, char **argv) printf("Waiting for ack...\n"); do { errno = 0; - pfd = hmcfgusb_poll(dev, 1); + pfd = hmcfgusb_poll(dev, 1000); if ((pfd < 0) && errno) { - perror("\n\nhmcfgusb_poll"); - exit(EXIT_FAILURE); + if (errno != ETIMEDOUT) { + perror("\n\nhmcfgusb_poll"); + exit(EXIT_FAILURE); + } } if (rdata.ack) { break; @@ -282,12 +194,12 @@ int main(int argc, char **argv) printf("\b%c", twiddlie[block % sizeof(twiddlie)]); fflush(stdout); } - free(fw[block]); } - free(fw); + firmware_free(fw); hmcfgusb_close(dev); + hmcfgusb_exit(); return EXIT_SUCCESS; }