X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=ao-tools%2Fao-usbload%2Fao-usbload.c;h=31ee138a3679584779eeda813997667b8ba3ffd9;hb=1ea6188a9c78ab0642001110cac6c3b35e8ccc88;hp=860eb8a5d4778a47f3defdb6d397941bea9c4bed;hpb=5fd0dc6f69e7614ba71bbc215b32260a11595af3;p=fw%2Faltos diff --git a/ao-tools/ao-usbload/ao-usbload.c b/ao-tools/ao-usbload/ao-usbload.c index 860eb8a5..31ee138a 100644 --- a/ao-tools/ao-usbload/ao-usbload.c +++ b/ao-tools/ao-usbload/ao-usbload.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -40,7 +41,6 @@ get_uint16(struct cc_usb *cc, uint32_t addr) { uint16_t result; result = ao_self_get_uint16(cc, addr); - printf ("read 0x%08x = 0x%04x\n", addr, result); return result; } @@ -54,7 +54,6 @@ get_uint32(struct cc_usb *cc, uint32_t addr) uint32_t result; result = ao_self_get_uint32(cc, addr); - printf ("read 0x%08x = 0x%08x\n", addr, result); return result; } @@ -82,15 +81,18 @@ check_flashed(struct cc_usb *cc) static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "raw", .has_arg = 0, .val = 'r' }, { .name = "cal", .has_arg = 1, .val = 'c' }, { .name = "serial", .has_arg = 1, .val = 's' }, { .name = "verbose", .has_arg = 1, .val = 'v' }, + { .name = "wait", .has_arg = 0, .val = 'w' }, + { .name = "force", .has_arg = 0, .val = 'f' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] file.{elf,ihx}\n", program); + fprintf(stderr, "usage: %s [--raw] [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] [--wait] [--force] file.{elf,ihx}\n", program); exit(1); } @@ -113,12 +115,55 @@ ends_with(char *whole, char *suffix) return strcmp(whole + whole_len - suffix_len, suffix) == 0; } +static int +ucs2len(uint16_t *ucs2) +{ + int len = 0; + while (*ucs2++) + len++; + return len; +} + +int +putucs4(uint32_t c, FILE *file) +{ + char d; + int bits; + + if (c < 0x80) { d = c; bits= -6; } + else if (c < 0x800) { d= ((c >> 6) & 0x1F) | 0xC0; bits= 0; } + else if (c < 0x10000) { d= ((c >> 12) & 0x0F) | 0xE0; bits= 6; } + else if (c < 0x200000) { d= ((c >> 18) & 0x07) | 0xF0; bits= 12; } + else if (c < 0x4000000) { d= ((c >> 24) & 0x03) | 0xF8; bits= 18; } + else if (c < 0x80000000) { d= ((c >> 30) & 0x01) | 0xFC; bits= 24; } + else return EOF; + + if (putc (d, file) < 0) + return EOF; + + for ( ; bits >= 0; bits-= 6) + if (putc (((c >> bits) & 0x3F) | 0x80, file) < 0) + return EOF; + + return 0; +} + +static void +putucs2str(uint16_t *ucs2str, FILE *file) +{ + uint16_t ucs2; + + while ((ucs2 = *ucs2str++) != 0) + putucs4(ucs2, file); +} + int main (int argc, char **argv) { char *device = NULL; char *filename; Elf *e; + int raw = 0; char *serial_end; unsigned int serial = 0; char *serial_ucs2; @@ -140,8 +185,11 @@ main (int argc, char **argv) int verbose = 0; struct ao_sym *file_symbols; int num_file_symbols; + uint32_t flash_base, flash_bound; + int has_flash_size = 0; + int force = 0; - while ((c = getopt_long(argc, argv, "T:D:c:s:v:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "wrfT:D:c:s:v:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -149,6 +197,12 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'r': + raw = 1; + break; + case 'w': + cc_default_timeout = -1; + break; case 'c': cal = strtoul(optarg, &cal_end, 10); if (cal_end == optarg || *cal_end != '\0') @@ -162,6 +216,9 @@ main (int argc, char **argv) case 'v': verbose++; break; + case 'f': + force = 1; + break; default: usage(argv[0]); break; @@ -184,9 +241,11 @@ main (int argc, char **argv) } else usage(argv[0]); - if (!ao_editaltos_find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) { - fprintf(stderr, "Cannot find required symbols\n"); - usage(argv[0]); + if (!raw) { + if (!ao_editaltos_find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) { + fprintf(stderr, "Cannot find required symbols\n"); + usage(argv[0]); + } } { @@ -198,7 +257,11 @@ main (int argc, char **argv) if (!this_tty) this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash"); if (!this_tty) - this_tty = cc_usbdevs_find_by_arg(device, "MegaMetrum"); + this_tty = cc_usbdevs_find_by_arg(device, "TeleMega"); + if (!this_tty) + this_tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); + if (!this_tty) + this_tty = cc_usbdevs_find_by_arg(device, "TeleGPS"); if (!this_tty) this_tty = getenv("ALTOS_TTY"); if (!this_tty) @@ -215,6 +278,14 @@ main (int argc, char **argv) cc_usb_getline(cc, line, sizeof(line)); if (!strncmp(line, "altos-loader", 12)) is_loader = 1; + if (!strncmp(line, "flash-range", 11)) { + int i; + for (i = 11; i < strlen(line); i++) + if (line[i] != ' ') + break; + if (sscanf(line + i, "%x %x", &flash_base, &flash_bound) == 2) + has_flash_size = 1; + } if (!strncmp(line, "software-version", 16)) break; } @@ -255,38 +326,98 @@ main (int argc, char **argv) #endif } - /* Go fetch existing config values - * if available + /* If the device can tell us the size of flash, make sure + * the image fits in that */ - was_flashed = check_flashed(cc); - - if (!serial) { - if (!was_flashed) { - fprintf (stderr, "Must provide serial number\n"); - done(cc, 1); - } - serial = get_uint16(cc, AO_SERIAL_NUMBER); - if (!serial || serial == 0xffff) { - fprintf (stderr, "Invalid existing serial %d\n", serial); + if (has_flash_size) { + if (load->address < flash_base || + load->address + load->length > flash_bound) + { + fprintf(stderr, "Image does not fit on device.\n"); + fprintf(stderr, " Image base: %08x bounds %08x\n", + load->address, load->address + load->length); + fprintf(stderr, " Device base: %08x bounds %08x\n", + flash_base, flash_bound); done(cc, 1); } } - if (!cal && AO_RADIO_CAL && was_flashed) { - cal = get_uint32(cc, AO_RADIO_CAL); - if (!cal || cal == 0xffffffff) { - fprintf (stderr, "Invalid existing rf cal %d\n", cal); - done(cc, 1); + if (!raw) { + /* Go fetch existing config values + * if available + */ + was_flashed = check_flashed(cc); + + if (!serial) { + if (!was_flashed) { + fprintf (stderr, "Must provide serial number\n"); + done(cc, 1); + } + serial = get_uint16(cc, AO_SERIAL_NUMBER); + if (!serial || serial == 0xffff) { + fprintf (stderr, "Invalid existing serial %d\n", serial); + done(cc, 1); + } } - } - if (!ao_editaltos(load, serial, cal)) - done(cc, 1); + if (!cal && AO_RADIO_CAL && was_flashed) { + cal = get_uint32(cc, AO_RADIO_CAL); + if (!cal || cal == 0xffffffff) { + fprintf (stderr, "Invalid existing rf cal %d\n", cal); + done(cc, 1); + } + } + + if (!force && was_flashed) { + struct ao_usb_id new_id, old_id; + uint16_t *new_product, *old_product; + int new_len, old_len; + + if (!ao_heximage_usb_id(load, &new_id)) { + fprintf(stderr, "Can't get new USB id\n"); + done(cc, 1); + } + + if (!ao_self_get_usb_id(cc, &old_id)) { + fprintf(stderr, "Can't get old USB id\n"); + done(cc, 1); + } + if (new_id.vid != old_id.vid || new_id.pid != old_id.pid) { + fprintf(stderr, "USB ID mismatch (device is %04x/%04x image is %04x/%04x)\n", + old_id.vid, old_id.pid, new_id.vid, new_id.pid); + done(cc, 1); + } + + new_product = ao_heximage_usb_product(load); + if (!new_product) { + fprintf(stderr, "Can't get new USB product name\n"); + done(cc, 1); + } + old_product = ao_self_get_usb_product(cc); + if (!old_product) { + fprintf(stderr, "Can't get existing USB product name\n"); + done(cc, 1); + } + new_len = ucs2len(new_product); + old_len = ucs2len(old_product); + if (new_len != old_len || memcmp(new_product, old_product, new_len * 2) != 0) { + fprintf(stderr, "USB product mismatch (device is "); + putucs2str(old_product, stderr); + fprintf(stderr, ", image is "); + putucs2str(new_product, stderr); + fprintf(stderr, ")\n"); + done(cc, 1); + } + } + + if (!ao_editaltos(load, serial, cal)) + done(cc, 1); + } /* And flash the resulting image to the device */ success = ao_self_write(cc, load); - + if (!success) { fprintf (stderr, "\"%s\": Write failed\n", filename); done(cc, 1);