X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=ao-tools%2Fao-stmload%2Fao-stmload.c;h=b6b4abc63720c2be99a518d21f9913ad81a317e2;hp=a471dcc47358b6d54a1dcefaae6769d73b750946;hb=5fd0dc6f69e7614ba71bbc215b32260a11595af3;hpb=b635cb26ba54c8f5c6a958e0ab0bc4d34d33b635 diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index a471dcc4..b6b4abc6 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -25,277 +25,51 @@ #include #include #include +#include #include "stlink-common.h" +#include "ao-elf.h" +#include "ccdbg.h" +#include "cc.h" +#include "ao-stmload.h" +#include "ao-selfload.h" +#include "ao-verbose.h" +#include "ao-editaltos.h" -#define AO_USB_DESC_STRING 3 - -struct sym { - unsigned addr; - char *name; - int required; -} ao_symbols[] = { - - { 0, "ao_romconfig_version", 1 }, -#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) - - { 0, "ao_romconfig_check", 1 }, -#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr) - - { 0, "ao_serial_number", 1 }, -#define AO_SERIAL_NUMBER (ao_symbols[2].addr) - - { 0, "ao_usb_descriptors", 0 }, -#define AO_USB_DESCRIPTORS (ao_symbols[3].addr) - - { 0, "ao_radio_cal", 0 }, -#define AO_RADIO_CAL (ao_symbols[4].addr) -}; - -#define NUM_SYMBOLS 5 -#define NUM_REQUIRED_SYMBOLS 3 /* - * Look through the Elf file for the AltOS symbols - * that can be adjusted before the image is written - * to the device - */ -static int -find_symbols (Elf *e) -{ - Elf_Scn *scn; - Elf_Data *symbol_data = NULL; - GElf_Shdr shdr; - GElf_Sym sym; - int i, symbol_count, s; - int required = 0; - char *symbol_name; - - /* - * Find the symbols - */ - - scn = NULL; - while ((scn = elf_nextscn(e, scn)) != NULL) { - if (gelf_getshdr(scn, &shdr) != &shdr) - return 0; - - if (shdr.sh_type == SHT_SYMTAB) { - symbol_data = elf_getdata(scn, NULL); - symbol_count = shdr.sh_size / shdr.sh_entsize; - break; - } - } - - if (!symbol_data) - return 0; - - for (i = 0; i < symbol_count; i++) { - gelf_getsym(symbol_data, i, &sym); - - symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); - - for (s = 0; s < NUM_SYMBOLS; s++) - if (!strcmp (ao_symbols[s].name, symbol_name)) { - int t; - ao_symbols[s].addr = sym.st_value; - if (ao_symbols[s].required) - ++required; - } - } - - return required >= NUM_REQUIRED_SYMBOLS; -} - -struct load { - uint32_t addr; - uint32_t len; - uint8_t buf[0]; -}; - -uint32_t round4(uint32_t a) { - return (a + 3) & ~3; -} - -struct load * -new_load (uint32_t addr, uint32_t len) -{ - struct load *new; - - len = round4(len); - new = calloc (1, sizeof (struct load) + len); - if (!new) - abort(); - - new->addr = addr; - new->len = len; - return new; -} - -void -load_paste(struct load *into, struct load *from) -{ - if (from->addr < into->addr || into->addr + into->len < from->addr + from->len) - abort(); - - memcpy(into->buf + from->addr - into->addr, from->buf, from->len); -} - -/* - * Make a new load structure large enough to hold the old one and - * the new data + * Read a 16-bit value from the target device with arbitrary + * alignment */ -struct load * -expand_load(struct load *from, uint32_t addr, uint32_t len) +static uint16_t +get_uint16_sl(stlink_t *sl, uint32_t addr) { - struct load *new; - - if (from) { - uint32_t from_last = from->addr + from->len; - uint32_t last = addr + len; - - if (addr > from->addr) - addr = from->addr; - if (last < from_last) - last = from_last; - - len = last - addr; - - if (addr == from->addr && len == from->len) - return from; - } - new = new_load(addr, len); - if (from) { - load_paste(new, from); - free (from); - } - return new; -} + const uint8_t *data = sl->q_buf; + uint32_t actual_addr; + int off; + uint16_t result; -/* - * Create a new load structure with data from the existing one - * and the new data - */ -struct load * -load_write(struct load *from, uint32_t addr, uint32_t len, void *data) -{ - struct load *new; + sl->q_len = 0; - new = expand_load(from, addr, len); - memcpy(new->buf + addr - new->addr, data, len); - return new; -} -/* - * Construct a large in-memory block for all - * of the loaded sections of the program - */ -static struct load * -get_load(Elf *e) -{ - Elf_Scn *scn; - size_t shstrndx; - GElf_Shdr shdr; - Elf_Data *data; - uint8_t *buf; - char *got_name; - size_t nphdr; - int p; - GElf_Phdr phdr; - struct load *load = NULL; + actual_addr = addr & ~3; - if (elf_getshdrstrndx(e, &shstrndx) < 0) - return 0; - - if (elf_getphdrnum(e, &nphdr) < 0) - return 0; - - /* - * As far as I can tell, all of the phdr sections should - * be flashed to memory - */ - for (p = 0; p < nphdr; p++) { - - /* Find this phdr */ - gelf_getphdr(e, p, &phdr); - - /* Get the associated file section */ - scn = gelf_offscn(e, phdr.p_offset); - - if (gelf_getshdr(scn, &shdr) != &shdr) - abort(); - - data = elf_getdata(scn, NULL); - - /* Write the section data into the memory block */ - load = load_write(load, phdr.p_paddr, phdr.p_filesz, data->d_buf); - } - return load; -} - -/* - * Edit the to-be-written memory block - */ -static int -rewrite(struct load *load, unsigned addr, uint8_t *data, int len) -{ - int i; + stlink_read_mem32(sl, actual_addr, 8); - if (addr < load->addr || load->addr + load->len < addr + len) - return 0; + if (sl->q_len != 8) + abort(); - printf("rewrite %04x:", addr); - for (i = 0; i < len; i++) - printf (" %02x", load->buf[addr - load->addr + i]); - printf(" ->"); - for (i = 0; i < len; i++) - printf (" %02x", data[i]); - printf("\n"); - memcpy(load->buf + addr - load->addr, data, len); + off = addr & 3; + result = data[off] | (data[off + 1] << 8); + return result; } -/* - * Open the specified ELF file and - * check for the symbols we need - */ - -Elf * -ao_open_elf(char *name) +static uint16_t +get_uint16(stlink_t *sl, uint32_t addr) { - int fd; - Elf *e; - Elf_Scn *scn; - Elf_Data *symbol_data = NULL; - GElf_Shdr shdr; - GElf_Sym sym; - size_t n, shstrndx, sz; - int i, symbol_count, s; - int required = 0; - - if (elf_version(EV_CURRENT) == EV_NONE) - return NULL; - - fd = open(name, O_RDONLY, 0); - - if (fd < 0) - return NULL; - - e = elf_begin(fd, ELF_C_READ, NULL); - - if (!e) - return NULL; - - if (elf_kind(e) != ELF_K_ELF) - return NULL; - - if (elf_getshdrstrndx(e, &shstrndx) != 0) - return NULL; - - if (!find_symbols(e)) { - fprintf (stderr, "Cannot find required symbols\n"); - return NULL; - } - - return e; + uint16_t result; + result = get_uint16_sl(sl, addr); + printf ("read 0x%08x = 0x%04x\n", addr, result); + return result; } /* @@ -303,7 +77,7 @@ ao_open_elf(char *name) * alignment */ static uint32_t -get_uint32(stlink_t *sl, uint32_t addr) +get_uint32_sl(stlink_t *sl, uint32_t addr) { const uint8_t *data = sl->q_buf; uint32_t actual_addr; @@ -323,35 +97,20 @@ get_uint32(stlink_t *sl, uint32_t addr) off = addr & 3; result = data[off] | (data[off + 1] << 8) | (data[off+2] << 16) | (data[off+3] << 24); - printf ("read 0x%08x = 0x%08x\n", addr, result); return result; } /* - * Read a 16-bit value from the target device with arbitrary + * Read a 32-bit value from the target device with arbitrary * alignment */ -static uint16_t -get_uint16(stlink_t *sl, uint32_t addr) +static uint32_t +get_uint32(stlink_t *sl, uint32_t addr) { - const uint8_t *data = sl->q_buf; - uint32_t actual_addr; - int off; - uint16_t result; - - sl->q_len = 0; - - - actual_addr = addr & ~3; - - stlink_read_mem32(sl, actual_addr, 8); - - if (sl->q_len != 8) - abort(); + uint32_t result; - off = addr & 3; - result = data[off] | (data[off + 1] << 8); - printf ("read 0x%08x = 0x%04x\n", addr, result); + result = get_uint32_sl(sl, addr); + printf ("read 0x%08x = 0x%08x\n", addr, result); return result; } @@ -377,30 +136,41 @@ check_flashed(stlink_t *sl) } static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, { .name = "cal", .has_arg = 1, .val = 'c' }, { .name = "serial", .has_arg = 1, .val = 's' }, + { .name = "verbose", .has_arg = 1, .val = 'v' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--cal=] [--serial=] file.elf\n", program); + fprintf(stderr, "usage: %s [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] file.{elf,ihx}\n", program); exit(1); } void done(stlink_t *sl, int code) { - if (sl) { - stlink_reset(sl); - stlink_run(sl); - stlink_exit_debug_mode(sl); - stlink_close(sl); - } + stlink_reset(sl); + stlink_run(sl); + stlink_exit_debug_mode(sl); + stlink_close(sl); exit (code); } +static int +ends_with(char *whole, char *suffix) +{ + int whole_len = strlen(whole); + int suffix_len = strlen(suffix); + + if (suffix_len > whole_len) + return 0; + return strcmp(whole + whole_len - suffix_len, suffix) == 0; +} + int main (int argc, char **argv) { @@ -419,12 +189,21 @@ main (int argc, char **argv) char cal_int[4]; char *cal_end; int c; - stlink_t *sl; + stlink_t *sl = NULL; int was_flashed = 0; - struct load *load; - - while ((c = getopt_long(argc, argv, "D:c:s:", options, NULL)) != -1) { + struct ao_hex_image *load; + int tries; + char *tty = NULL; + int success; + int verbose = 0; + struct ao_sym *file_symbols; + int num_file_symbols; + + while ((c = getopt_long(argc, argv, "T:D:c:s:v:", options, NULL)) != -1) { switch (c) { + case 'T': + tty = optarg; + break; case 'D': device = optarg; break; @@ -438,59 +217,68 @@ main (int argc, char **argv) if (serial_end == optarg || *serial_end != '\0') usage(argv[0]); break; + case 'v': + verbose++; + break; default: usage(argv[0]); break; } } + ao_verbose = verbose; + + if (verbose > 1) + ccdbg_add_debug(CC_DEBUG_BITBANG); + filename = argv[optind]; if (filename == NULL) usage(argv[0]); - /* - * Open the source file and load the symbols and - * flash data - */ - - e = ao_open_elf(filename); - if (!e) { - fprintf(stderr, "Cannot open file \"%s\"\n", filename); - exit(1); - } + if (ends_with (filename, ".elf")) { + load = ao_load_elf(filename, &file_symbols, &num_file_symbols); + } else if (ends_with (filename, ".ihx")) { + load = ao_hex_load(filename, &file_symbols, &num_file_symbols); + } else + usage(argv[0]); - if (!find_symbols(e)) { - fprintf(stderr, "Cannot find symbols in \"%s\"\n", filename); - exit(1); + 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 (!(load = get_load(e))) { - fprintf(stderr, "Cannot find program data in \"%s\"\n", filename); - exit(1); - } - /* Connect to the programming dongle */ - if (device) { - sl = stlink_v1_open(50); - } else { - sl = stlink_open_usb(50); + for (tries = 0; tries < 3; tries++) { + if (device) { + sl = stlink_v1_open(50); + } else { + sl = stlink_open_usb(50); + } + if (!sl) { + fprintf (stderr, "No STLink devices present\n"); + done (sl, 1); + } + + if (sl->chip_id != 0) + break; + stlink_reset(sl); + stlink_close(sl); + sl = NULL; } if (!sl) { - fprintf (stderr, "No STLink devices present\n"); - done (sl, 1); + fprintf (stderr, "Debugger connection failed\n"); + exit(1); } - sl->verbose = 50; - /* Verify that the loaded image fits entirely within device flash */ - if (load->addr < sl->flash_base || - sl->flash_base + sl->flash_size < load->addr + load->len) { + if (load->address < sl->flash_base || + sl->flash_base + sl->flash_size < load->address + load->length) { fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename, - load->addr, load->addr + load->len); + load->address, load->address + load->length); done(sl, 1); } @@ -527,69 +315,15 @@ main (int argc, char **argv) } } - /* Write the config values into the flash image - */ - - serial_int[0] = serial & 0xff; - serial_int[1] = (serial >> 8) & 0xff; - - if (!rewrite(load, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) { - fprintf(stderr, "Cannot rewrite serial integer at %08x\n", - AO_SERIAL_NUMBER); + if (!ao_editaltos(load, serial, cal)) done(sl, 1); - } - - if (AO_USB_DESCRIPTORS) { - unsigned usb_descriptors; - usb_descriptors = AO_USB_DESCRIPTORS - load->addr; - string_num = 0; - - while (load->buf[usb_descriptors] != 0 && usb_descriptors < load->len) { - if (load->buf[usb_descriptors+1] == AO_USB_DESC_STRING) { - ++string_num; - if (string_num == 4) - break; - } - usb_descriptors += load->buf[usb_descriptors]; - } - if (usb_descriptors >= load->len || load->buf[usb_descriptors] == 0 ) { - fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS); - done(sl, 1); - } - - serial_ucs2_len = load->buf[usb_descriptors] - 2; - serial_ucs2 = malloc(serial_ucs2_len); - if (!serial_ucs2) { - fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); - done(sl, 1); - } - s = serial; - for (i = serial_ucs2_len / 2; i; i--) { - serial_ucs2[i * 2 - 1] = 0; - serial_ucs2[i * 2 - 2] = (s % 10) + '0'; - s /= 10; - } - if (!rewrite(load, usb_descriptors + 2 + load->addr, serial_ucs2, serial_ucs2_len)) { - fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS); - done(sl, 1); - } - } - - if (cal && AO_RADIO_CAL) { - cal_int[0] = cal & 0xff; - cal_int[1] = (cal >> 8) & 0xff; - cal_int[2] = (cal >> 16) & 0xff; - cal_int[3] = (cal >> 24) & 0xff; - - if (!rewrite(load, AO_RADIO_CAL, cal_int, sizeof (cal_int))) { - fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL); - exit(1); - } - } /* And flash the resulting image to the device */ - if (stlink_write_flash(sl, load->addr, load->buf, load->len) < 0) { + + success = (stlink_write_flash(sl, load->address, load->data, load->length) >= 0); + + if (!success) { fprintf (stderr, "\"%s\": Write failed\n", filename); done(sl, 1); }