From 853cbce9b9a23201a048934b004ac04643f9c895 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 8 Jun 2016 20:26:47 +0200 Subject: [PATCH] flash-hmmoduart: add utility to upgrade firmware on HM-MOD-UART --- .gitignore | 3 + Makefile | 7 +- firmware.c | 2 +- flash-hmmoduart.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++ flash-ota.c | 2 +- hmsniff.c | 2 +- hmuartlgw.c | 10 ++- hmuartlgw.h | 3 +- 8 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 flash-hmmoduart.c diff --git a/.gitignore b/.gitignore index e1e2a29..eaafd80 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ culfw.o flash-hmcfgusb flash-hmcfgusb.d flash-hmcfgusb.o +flash-hmmoduart +flash-hmmoduart.d +flash-hmmoduart.o flash-ota flash-ota.d flash-ota.o diff --git a/Makefile b/Makefile index 1a29116..9693ca1 100644 --- a/Makefile +++ b/Makefile @@ -9,11 +9,12 @@ CC=gcc HMLAN_OBJS=hmcfgusb.o hmland.o util.o HMSNIFF_OBJS=hmcfgusb.o hmuartlgw.o hmsniff.o FLASH_HMCFGUSB_OBJS=hmcfgusb.o firmware.o util.o flash-hmcfgusb.o +FLASH_HMMODUART_OBJS=hmuartlgw.o firmware.o util.o flash-hmmoduart.o FLASH_OTA_OBJS=hmcfgusb.o culfw.o hmuartlgw.o firmware.o util.o flash-ota.o hm.o aes.o -OBJS=$(HMLAN_OBJS) $(HMSNIFF_OBJS) $(FLASH_HMCFGUSB_OBJS) $(FLASH_OTA_OBJS) +OBJS=$(HMLAN_OBJS) $(HMSNIFF_OBJS) $(FLASH_HMCFGUSB_OBJS) $(FLASH_HMMODUART_OBJS) $(FLASH_OTA_OBJS) -all: hmland hmsniff flash-hmcfgusb flash-ota +all: hmland hmsniff flash-hmcfgusb flash-hmmoduart flash-ota DEPEND=$(OBJS:.o=.d) -include $(DEPEND) @@ -24,6 +25,8 @@ hmsniff: $(HMSNIFF_OBJS) flash-hmcfgusb: $(FLASH_HMCFGUSB_OBJS) +flash-hmmoduart: $(FLASH_HMMODUART_OBJS) + flash-ota: $(FLASH_OTA_OBJS) clean: diff --git a/firmware.c b/firmware.c index a52bccf..6a544a3 100644 --- a/firmware.c +++ b/firmware.c @@ -37,7 +37,7 @@ #include "firmware.h" /* This might be wrong, but it works for current fw */ -#define MAX_BLOCK_LENGTH 512 +#define MAX_BLOCK_LENGTH 2048 struct firmware* firmware_read_firmware(char *filename, int debug) { diff --git a/flash-hmmoduart.c b/flash-hmmoduart.c new file mode 100644 index 0000000..9f2f29a --- /dev/null +++ b/flash-hmmoduart.c @@ -0,0 +1,200 @@ +/* flasher for HM-CFG-USB + * + * 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 + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hexdump.h" +#include "firmware.h" +#include "version.h" +#include "hmuartlgw.h" + +struct recv_data { + uint16_t ack; +}; + +static int parse_hmuartlgw(enum hmuartlgw_dst dst, uint8_t *buf, int buf_len, void *data) +{ + struct recv_data *rdata = data; + + if (buf_len != 2) + return 1; + + rdata->ack = (buf[0] << 8) | (buf[1] & 0xff); + + return 1; +} + +void flash_hmmoduart_syntax(char *prog) +{ + fprintf(stderr, "Syntax: %s [options] -U /dev/ttyAMA0 filename.eq3\n\n", prog); + fprintf(stderr, "Mandatory parameter:\n"); + fprintf(stderr, "\t-U device\tuse HM-MOD-UART on given device\n"); + fprintf(stderr, "Possible options:\n"); + fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); + +} + +int main(int argc, char **argv) +{ + const char twiddlie[] = { '-', '\\', '|', '/' }; + struct hmuartlgw_dev *dev; + uint8_t *framedata; + struct recv_data rdata; + uint16_t len; + struct firmware *fw; + char *uart = NULL; + char *filename = NULL; + int block; + int pfd; + int opt; + int debug = 0; + + while((opt = getopt(argc, argv, "U:V")) != -1) { + switch (opt) { + case 'U': + uart = 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_hmmoduart_syntax(argv[0]); + exit(EXIT_FAILURE); + break; + } + } + + if (optind == argc - 1) { + filename = argv[optind]; + } + + if (!uart) { + flash_hmmoduart_syntax(argv[0]); + exit(EXIT_FAILURE); + } + + printf("HM-MOD-UART flasher version " VERSION "\n\n"); + + if (!filename) { + fprintf(stderr, "Missing firmware filename!\n\n"); + flash_hmmoduart_syntax(argv[0]); + exit(EXIT_FAILURE); + } + + fw = firmware_read_firmware(filename, debug); + if (!fw) + exit(EXIT_FAILURE); + + hmuartlgw_set_debug(debug); + + memset(&rdata, 0, sizeof(rdata)); + + dev = hmuart_init(uart, parse_hmuartlgw, &rdata, 0); + if (!dev) { + fprintf(stderr, "Can't initialize HM-MOD-UART\n"); + exit(EXIT_FAILURE); + } + + printf("\nHM-MOD-UART opened.\n\n"); + + printf("Flashing %d blocks", fw->fw_blocks); + if (debug) { + printf("\n"); + } else { + printf(": %c", twiddlie[0]); + fflush(stdout); + } + + for (block = 0; block < fw->fw_blocks; block++) { + len = fw->fw[block][2] << 8; + len |= fw->fw[block][3]; + + len -= 1; /* + frametype, - crc crc */ + + framedata = (fw->fw[block]) + 3; + framedata[0] = HMUARTLGW_OS_UPDATE_FIRMWARE; + + if (debug) + hexdump(framedata, len, "F> "); + + rdata.ack = 0; + + if (!hmuartlgw_send(dev, framedata, len, HMUARTLGW_OS)) { + perror("\n\nhmuartlgw_send"); + exit(EXIT_FAILURE); + } + + if (debug) + printf("Waiting for ack...\n"); + do { + errno = 0; + pfd = hmuartlgw_poll(dev, 1000); + if ((pfd < 0) && errno) { + if (errno != ETIMEDOUT) { + perror("\n\nhmuartlgw_poll"); + exit(EXIT_FAILURE); + } + } + if (rdata.ack) { + break; + } + } while (pfd < 0); + + if (rdata.ack != 0x0401) { + fprintf(stderr, "\n\nError flashing block %d, status: %u\n", block, rdata.ack); + exit(EXIT_FAILURE); + } + + if (!debug) { + printf("\b%c", twiddlie[block % sizeof(twiddlie)]); + fflush(stdout); + } + } + + if (rdata.ack == 0x0401) { + printf("\n\nFirmware update successfull!\n"); + } + + + firmware_free(fw); + + hmuartlgw_close(dev); + + return EXIT_SUCCESS; +} diff --git a/flash-ota.c b/flash-ota.c index a4a0fef..2a7a815 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -705,7 +705,7 @@ int main(int argc, char **argv) hmuartlgw_set_debug(debug); - dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata); + dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata, 1); if (!dev.hmuartlgw) { fprintf(stderr, "Can't initialize HM-MOD-UART\n"); exit(EXIT_FAILURE); diff --git a/hmsniff.c b/hmsniff.c index c35b29d..01afe05 100644 --- a/hmsniff.c +++ b/hmsniff.c @@ -323,7 +323,7 @@ int main(int argc, char **argv) buf[1] = speed; hmcfgusb_send(dev.hmcfgusb, buf, 2, 1); } else { - dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata); + dev.hmuartlgw = hmuart_init(uart, parse_hmuartlgw, &rdata, 1); if (!dev.hmuartlgw) { fprintf(stderr, "Can't initialize HM-MOD-UART!\n"); exit(1); diff --git a/hmuartlgw.c b/hmuartlgw.c index 4c274cf..2fa755c 100644 --- a/hmuartlgw.c +++ b/hmuartlgw.c @@ -142,7 +142,7 @@ static int hmuartlgw_init_parse(enum hmuartlgw_dst dst, uint8_t *buf, int buf_le return 1; } -struct hmuartlgw_dev *hmuart_init(char *device, hmuartlgw_cb_fn cb, void *data) +struct hmuartlgw_dev *hmuart_init(char *device, hmuartlgw_cb_fn cb, void *data, int app) { struct hmuartlgw_dev *dev = NULL; struct termios oldtio, tio; @@ -191,7 +191,11 @@ struct hmuartlgw_dev *hmuart_init(char *device, hmuartlgw_cb_fn cb, void *data) hmuartlgw_flush(dev); - hmuartlgw_enter_app(dev); + if (app) { + hmuartlgw_enter_app(dev); + } else { + hmuartlgw_enter_bootloader(dev); + } dev->cb = cb; dev->cb_data = data; @@ -329,7 +333,7 @@ int hmuartlgw_send_raw(struct hmuartlgw_dev *dev, uint8_t *frame, int framelen) int hmuartlgw_send(struct hmuartlgw_dev *dev, uint8_t *cmd, int cmdlen, enum hmuartlgw_dst dst) { static uint8_t cnt = 0; - uint8_t frame[1024] = { 0 }; + uint8_t frame[4096] = { 0 }; uint16_t crc; frame[0] = 0xfd; diff --git a/hmuartlgw.h b/hmuartlgw.h index 09b2993..9b32428 100644 --- a/hmuartlgw.h +++ b/hmuartlgw.h @@ -25,6 +25,7 @@ #define HMUARTLGW_OS_GET_FIRMWARE 0x02 #define HMUARTLGW_OS_CHANGE_APP 0x03 #define HMUARTLGW_OS_ACK 0x04 +#define HMUARTLGW_OS_UPDATE_FIRMWARE 0x05 #define HMUARTLGW_OS_UNSOL_CREDITS 0x05 #define HMUARTLGW_OS_NORMAL_MODE 0x06 #define HMUARTLGW_OS_UPDATE_MODE 0x07 @@ -65,7 +66,7 @@ struct hmuartlgw_dev { int unescape_next; }; -struct hmuartlgw_dev *hmuart_init(char *device, hmuartlgw_cb_fn cb, void *data); +struct hmuartlgw_dev *hmuart_init(char *device, hmuartlgw_cb_fn cb, void *data, int app); struct hmuartlgw_dev *hmlgw_init(char *device, hmuartlgw_cb_fn cb, void *data); int hmuartlgw_send_raw(struct hmuartlgw_dev *dev, uint8_t *frame, int framelen); int hmuartlgw_send(struct hmuartlgw_dev *dev, uint8_t *cmd, int cmdlen, enum hmuartlgw_dst dst); -- 2.39.5