From 8083aa731c99d09bdd4a8c216bb11f846734d7df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 18:57:58 -0600 Subject: ao-tools: Add ao-mega tool to parse TeleMega eeprom files Signed-off-by: Keith Packard --- ao-tools/lib/Makefile.am | 1 + ao-tools/lib/cc-mega.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 ao-tools/lib/cc-mega.c (limited to 'ao-tools/lib') diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index 1f8f2e42..fd4dab25 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -21,6 +21,7 @@ libao_tools_a_SOURCES = \ cc-convert.c \ cc-dsp.c \ cc-integrate.c \ + cc-mega.c \ cc-period.c \ cc-process.c \ cc-usb.c \ diff --git a/ao-tools/lib/cc-mega.c b/ao-tools/lib/cc-mega.c new file mode 100644 index 00000000..3aa24a6d --- /dev/null +++ b/ao-tools/lib/cc-mega.c @@ -0,0 +1,160 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "cc.h" +#include +#include + +static const char * +parse_hex(const char *data, int *result) +{ + char d[12]; + int x; + int i; + + while (isspace (*data)) + data++; + for (i = 0; i < sizeof (d) - 1 && isxdigit(*data); i++) + d[i] = *data++; + d[i] = '\0'; + if (sscanf(d, "%x", &x) != 1) + return NULL; + *result = x; + return data; +} + +static const char * +parse_uint16(const char *data, uint16_t *result) +{ + int x; + data = parse_hex(data, &x); + *result =x; + return data; +} + +static const char * +parse_uint8(const char *data, uint8_t *result) +{ + int x; + data = parse_hex(data, &x); + *result =x; + return data; +} + +static int +parse_eeprom(const char *input_line, struct ao_log_mega *l) { + const char *line; + int b; + + if (input_line[1] != ' ') + return 0; + if (!isupper(input_line[0])) + return 0; + + l->type = input_line[0]; + l->is_config = 0; + line = input_line + 2; + + line = parse_uint16(line, &l->tick); + for (b = 0; b < 28; b++) { + if (!line) + return 0; + line = parse_uint8(line, &l->u.bytes[b]); + } + return 1; +} + +#define YUP(t) do { \ + l->u.config_int.kind = (t); \ + l->is_config = 1; \ + return 1; \ + } while (0); + +static int +parse_config(const char *input_line, struct ao_log_mega *l) { + if (sscanf (input_line, "Config version: %d.%d", + &l->u.config_int.data[0], + &l->u.config_int.data[1])) + YUP(AO_CONFIG_CONFIG); + if (sscanf (input_line, "Main deploy: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MAIN); + if (sscanf (input_line, "Apogee delay: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_APOGEE); + if (sscanf (input_line, "Apogee lockout: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_LOCKOUT); + if (sscanf (input_line, "Frequency: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_FREQUENCY); + if (sscanf (input_line, "Radio enable: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_RADIO_ENABLE); + if (sscanf (input_line, "Accel cal +1g: %d -1g: %d", + &l->u.config_int.data[0], + &l->u.config_int.data[1])) + YUP(AO_CONFIG_ACCEL_CAL); + if (sscanf (input_line, "Radio cal: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_RADIO_CAL); + if (sscanf (input_line, "Max flight log: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MAX_LOG); + if (sscanf (input_line, "Ignite mode: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_IGNITE_MODE); + if (sscanf (input_line, "Pad orientation: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_PAD_ORIENTATION); + if (sscanf (input_line, "serial-number %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_SERIAL_NUMBER); + if (sscanf (input_line, "log-format %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_LOG_FORMAT); + if (sscanf (input_line, "ms5607 reserved: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_RESERVED); + if (sscanf (input_line, "ms5607 sens: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_SENS); + if (sscanf (input_line, "ms5607 off: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_OFF); + if (sscanf (input_line, "ms5607 tcs: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_TCS); + if (sscanf (input_line, "ms5607 tco: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_TCO); + if (sscanf (input_line, "ms5607 tref: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_TREF); + if (sscanf (input_line, "ms5607 tempsens: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_TEMPSENS); + if (sscanf (input_line, "ms5607 crc: %d", + &l->u.config_int.data[0])) + YUP(AO_CONFIG_MS5607_CRC); + return 0; +} + +int +cc_mega_parse(const char *input_line, struct ao_log_mega *l) { + return parse_eeprom(input_line, l) || parse_config(input_line, l); +} -- cgit v1.2.3 From b1408c13f176f3f021e9face48c4cd33528ee96c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 18:58:41 -0600 Subject: ao-tools/ao-mega: Dump 'pyro' state from mega log Signed-off-by: Keith Packard --- ao-tools/ao-mega/ao-mega.c | 1 + ao-tools/lib/cc.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-mega/ao-mega.c b/ao-tools/ao-mega/ao-mega.c index e06df88d..523229e6 100644 --- a/ao-tools/ao-mega/ao-mega.c +++ b/ao-tools/ao-mega/ao-mega.c @@ -126,6 +126,7 @@ main (int argc, char **argv) printf (" s%d %6d", j, log.u.volt.sense[j]); } + printf ("pyro %04x\n", log.u.volt.pyro); printf ("\n"); break; default: diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 625540bb..c07f8cd0 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -306,7 +306,8 @@ struct ao_log_mega { int16_t v_pbatt; /* 6 */ int16_t n_sense; /* 8 */ int16_t sense[10]; /* 10 */ - } volt; /* 30 */ + uint16_t pyro; /* 30 */ + } volt; /* 32 */ /* AO_LOG_GPS_TIME */ struct { int32_t latitude; /* 4 */ -- cgit v1.2.3 From 7314bf807544eecf2fd970e93c752ff15688bb42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Sep 2013 22:56:57 -0700 Subject: ao-tools/ao-telem: Parse new TM v2 packets Signed-off-by: Keith Packard --- ao-tools/ao-telem/ao-telem.c | 20 +++++++++++++ ao-tools/lib/cc-telemetry.h | 69 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c index d2dae5a7..893e2340 100644 --- a/ao-tools/ao-telem/ao-telem.c +++ b/ao-tools/ao-telem/ao-telem.c @@ -194,6 +194,26 @@ main (int argc, char **argv) telem.mega_data.height); break; + case AO_TELEMETRY_METRUM_SENSOR: + printf ("state %1d accel %5d pres %9d temp %6.2f acceleration %6.2f speed %6.2f height %5d v_batt %5d sense_a %5d sense_m %5d\n", + telem.metrum_sensor.state, + telem.metrum_sensor.accel, + telem.metrum_sensor.pres, + telem.metrum_sensor.temp / 100.0, + telem.metrum_sensor.acceleration / 16.0, + telem.metrum_sensor.speed / 16.0, + telem.metrum_sensor.height, + telem.metrum_sensor.v_batt, + telem.metrum_sensor.sense_a, + telem.metrum_sensor.sense_m); + break; + case AO_TELEMETRY_METRUM_DATA: + printf ("ground_pres %9d ground_accel %5d accel_plus %5d accel_minus %5d\n", + telem.metrum_data.ground_pres, + telem.metrum_data.ground_accel, + telem.metrum_data.accel_plus_g, + telem.metrum_data.accel_minus_g); + break; default: printf("\n"); } diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h index 9a5be49f..c28aceb8 100644 --- a/ao-tools/lib/cc-telemetry.h +++ b/ao-tools/lib/cc-telemetry.h @@ -201,6 +201,72 @@ struct ao_telemetry_mega_data { /* 32 */ }; +#define AO_TELEMETRY_METRUM_SENSOR 0x0A + +struct ao_telemetry_metrum_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t acceleration; /* 14 m/s² * 16 */ + int16_t speed; /* 16 m/s * 16 */ + int16_t height; /* 18 m */ + + int16_t v_batt; /* 20 battery voltage */ + int16_t sense_a; /* 22 apogee continuity sense */ + int16_t sense_m; /* 24 main continuity sense */ + + uint8_t pad[6]; /* 26 */ + /* 32 */ +}; + +#define AO_TELEMETRY_METRUM_DATA 0x0B + +struct ao_telemetry_metrum_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + int32_t ground_pres; /* 8 average pres on pad */ + int16_t ground_accel; /* 12 average accel on pad */ + int16_t accel_plus_g; /* 14 accel calibration at +1g */ + int16_t accel_minus_g; /* 16 accel calibration at -1g */ + + uint8_t pad[14]; /* 18 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MINI 0x10 + +struct ao_telemetry_mini { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t v_batt; /* 6 battery voltage */ + int16_t sense_a; /* 8 apogee continuity */ + int16_t sense_m; /* 10 main continuity */ + + int32_t pres; /* 12 Pa * 10 */ + int16_t temp; /* 16 °C * 100 */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int32_t ground_pres; /* 24 average pres on pad */ + + int32_t pad28; /* 28 */ + /* 32 */ +}; + /* #define AO_SEND_ALL_BARO */ #define AO_TELEMETRY_BARO 0x80 @@ -234,6 +300,9 @@ union ao_telemetry_all { struct ao_telemetry_companion companion; struct ao_telemetry_mega_sensor mega_sensor; struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_metrum_sensor metrum_sensor; + struct ao_telemetry_metrum_data metrum_data; + struct ao_telemetry_mini mini; struct ao_telemetry_baro baro; }; -- cgit v1.2.3 From 95a8180f3d7929dbad65c80421f99c925f245af0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Nov 2013 13:59:06 -0800 Subject: ao-tools: Create general elf and hex library routines Pulls the elf stuff out of ao-stmload, change the hex stuff into ao_ routines. Signed-off-by: Keith Packard --- ao-tools/ao-dbg/ao-dbg-command.c | 24 +-- ao-tools/ao-load/ao-load.c | 14 +- ao-tools/ao-rawload/ao-rawload.c | 12 +- ao-tools/ao-stmload/Makefile.am | 2 +- ao-tools/ao-stmload/ao-elf.c | 303 ------------------------------ ao-tools/ao-stmload/ao-elf.h | 24 --- ao-tools/ao-stmload/ao-selfload.c | 8 +- ao-tools/ao-stmload/ao-stmload.c | 14 +- ao-tools/ao-stmload/ao-stmload.h | 13 +- ao-tools/lib/Makefile.am | 7 +- ao-tools/lib/ao-elf.c | 293 +++++++++++++++++++++++++++++ ao-tools/lib/ao-elf.h | 39 ++++ ao-tools/lib/ao-hex.c | 384 ++++++++++++++++++++++++++++++++++++++ ao-tools/lib/ao-hex.h | 68 +++++++ ao-tools/lib/ccdbg-command.c | 2 +- ao-tools/lib/ccdbg-flash.c | 2 +- ao-tools/lib/ccdbg-hex.c | 381 ------------------------------------- ao-tools/lib/ccdbg-memory.c | 8 +- ao-tools/lib/ccdbg-rom.c | 8 +- ao-tools/lib/ccdbg.h | 56 +----- 20 files changed, 847 insertions(+), 815 deletions(-) delete mode 100644 ao-tools/ao-stmload/ao-elf.c delete mode 100644 ao-tools/ao-stmload/ao-elf.h create mode 100644 ao-tools/lib/ao-elf.c create mode 100644 ao-tools/lib/ao-elf.h create mode 100644 ao-tools/lib/ao-hex.c create mode 100644 ao-tools/lib/ao-hex.h delete mode 100644 ao-tools/lib/ccdbg-hex.c (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-dbg/ao-dbg-command.c b/ao-tools/ao-dbg/ao-dbg-command.c index eab7bc68..11c521e8 100644 --- a/ao-tools/ao-dbg/ao-dbg-command.c +++ b/ao-tools/ao-dbg/ao-dbg-command.c @@ -202,8 +202,8 @@ command_dump (int argc, char **argv) enum command_result command_file (int argc, char **argv) { - struct hex_file *hex; - struct hex_image *image; + struct ao_hex_file *hex; + struct ao_hex_image *image; FILE *file; if (argc != 2) @@ -211,16 +211,16 @@ command_file (int argc, char **argv) file = fopen (argv[1], "r"); if (!file) return command_error; - hex = ccdbg_hex_file_read(file, argv[1]); + hex = ao_hex_file_read(file, argv[1]); fclose(file); if (!hex) return command_error; if (hex->nrecord == 0) { - ccdbg_hex_file_free(hex); + ao_hex_file_free(hex); return command_error; } - image = ccdbg_hex_image_create(hex); - ccdbg_hex_file_free(hex); + image = ao_hex_image_create(hex); + ao_hex_file_free(hex); start_address = image->address; ccdbg_set_rom(s51_dbg, image); return command_success; @@ -495,8 +495,8 @@ command_load (int argc, char **argv) { char *filename = argv[1]; FILE *file; - struct hex_file *hex; - struct hex_image *image; + struct ao_hex_file *hex; + struct ao_hex_image *image; if (!filename) return command_error; @@ -505,13 +505,13 @@ command_load (int argc, char **argv) perror(filename); return command_error; } - hex = ccdbg_hex_file_read(file, filename); + hex = ao_hex_file_read(file, filename); fclose(file); if (!hex) { return command_error; } - image = ccdbg_hex_image_create(hex); - ccdbg_hex_file_free(hex); + image = ao_hex_image_create(hex); + ao_hex_file_free(hex); if (!image) { fprintf(stderr, "image create failed\n"); return command_error; @@ -523,7 +523,7 @@ command_load (int argc, char **argv) } else { fprintf(stderr, "Can only load to RAM\n"); } - ccdbg_hex_image_free(image); + ao_hex_image_free(image); return command_success; } diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index e3cef4a5..c1f55149 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -80,7 +80,7 @@ find_symbols(FILE *map) } static int -rewrite(struct hex_image *image, unsigned addr, char *data, int len) +rewrite(struct ao_hex_image *image, unsigned addr, char *data, int len) { int i; if (addr < image->address || image->address + image->length < addr + len) @@ -114,8 +114,8 @@ main (int argc, char **argv) struct ccdbg *dbg; uint8_t status; uint16_t pc; - struct hex_file *hex; - struct hex_image *image; + struct ao_hex_file *hex; + struct ao_hex_image *image; char *filename; FILE *file; FILE *map; @@ -182,18 +182,18 @@ main (int argc, char **argv) } fclose(map); - hex = ccdbg_hex_file_read(file, filename); + hex = ao_hex_file_read(file, filename); fclose(file); if (!hex) { perror(filename); exit (1); } - image = ccdbg_hex_image_create(hex); + image = ao_hex_image_create(hex); if (!image) { fprintf(stderr, "image create failed\n"); exit (1); } - ccdbg_hex_file_free(hex); + ao_hex_file_free(hex); serial = strtoul(serial_string, NULL, 0); if (!serial) @@ -276,7 +276,7 @@ main (int argc, char **argv) } else { printf("Cannot load code to 0x%04x\n", image->address); - ccdbg_hex_image_free(image); + ao_hex_image_free(image); ccdbg_close(dbg); exit(1); } diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index a4746b19..17ed73ca 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -40,8 +40,8 @@ main (int argc, char **argv) struct ccdbg *dbg; uint8_t status; uint16_t pc; - struct hex_file *hex; - struct hex_image *image; + struct ao_hex_file *hex; + struct ao_hex_image *image; char *filename; FILE *file; char *tty = NULL; @@ -75,17 +75,17 @@ main (int argc, char **argv) perror(filename); exit(1); } - hex = ccdbg_hex_file_read(file, filename); + hex = ao_hex_file_read(file, filename); fclose(file); if (!hex) exit (1); - image = ccdbg_hex_image_create(hex); + image = ao_hex_image_create(hex); if (!image) { fprintf(stderr, "image create failed\n"); exit (1); } - ccdbg_hex_file_free(hex); + ao_hex_file_free(hex); if (!tty) tty = cc_usbdevs_find_by_arg(device, "TIDongle"); dbg = ccdbg_open(tty); @@ -107,7 +107,7 @@ main (int argc, char **argv) } else { printf("Cannot load code to 0x%04x\n", image->address); - ccdbg_hex_image_free(image); + ao_hex_image_free(image); ccdbg_close(dbg); exit(1); } diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am index 4eaf699c..68b518f1 100644 --- a/ao-tools/ao-stmload/Makefile.am +++ b/ao-tools/ao-stmload/Makefile.am @@ -11,7 +11,7 @@ ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS) ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf -ao_stmload_SOURCES=ao-stmload.c ao-elf.c ao-stmload.h ao-selfload.c +ao_stmload_SOURCES=ao-stmload.c ao-stmload.h ao-selfload.c man_MANS = ao-stmload.1 diff --git a/ao-tools/ao-stmload/ao-elf.c b/ao-tools/ao-stmload/ao-elf.c deleted file mode 100644 index dad8fb80..00000000 --- a/ao-tools/ao-stmload/ao-elf.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao-elf.h" -#include -#include -#include -#include -#include -#include -#include -#include "ccdbg.h" -#include "ao-stmload.h" - -/* - * 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; - char *section_name; - size_t shstrndx; - - if (elf_getshdrstrndx(e, &shstrndx) < 0) - return 0; - - /* - * 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 < ao_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 >= ao_num_required_symbols; -} - -uint32_t round4(uint32_t a) { - return (a + 3) & ~3; -} - -struct hex_image * -new_load (uint32_t addr, uint32_t len) -{ - struct hex_image *new; - - len = round4(len); - new = calloc (1, sizeof (struct hex_image) + len); - if (!new) - abort(); - - new->address = addr; - new->length = len; - return new; -} - -void -load_paste(struct hex_image *into, struct hex_image *from) -{ - if (from->address < into->address || into->address + into->length < from->address + from->length) - abort(); - - memcpy(into->data + from->address - into->address, from->data, from->length); -} - -/* - * Make a new load structure large enough to hold the old one and - * the new data - */ -struct hex_image * -expand_load(struct hex_image *from, uint32_t address, uint32_t length) -{ - struct hex_image *new; - - if (from) { - uint32_t from_last = from->address + from->length; - uint32_t last = address + length; - - if (address > from->address) - address = from->address; - if (last < from_last) - last = from_last; - - length = last - address; - - if (address == from->address && length == from->length) - return from; - } - new = new_load(address, length); - if (from) { - load_paste(new, from); - free (from); - } - return new; -} - -/* - * Create a new load structure with data from the existing one - * and the new data - */ -struct hex_image * -load_write(struct hex_image *from, uint32_t address, uint32_t length, void *data) -{ - struct hex_image *new; - - new = expand_load(from, address, length); - memcpy(new->data + address - new->address, data, length); - return new; -} - -/* - * Construct a large in-memory block for all - * of the loaded sections of the program - */ -static struct hex_image * -get_load(Elf *e) -{ - Elf_Scn *scn; - size_t shstrndx; - GElf_Shdr shdr; - Elf_Data *data; - char *got_name; - size_t nphdr; - size_t p; - GElf_Phdr phdr; - GElf_Addr p_paddr; - GElf_Off p_offset; - GElf_Addr sh_paddr; - struct hex_image *load = NULL; - char *section_name; - size_t nshdr; - size_t s; - - if (elf_getshdrstrndx(e, &shstrndx) < 0) - return 0; - - if (elf_getphdrnum(e, &nphdr) < 0) - return 0; - - if (elf_getshdrnum(e, &nshdr) < 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); - - if (phdr.p_type != PT_LOAD) - continue; - - p_offset = phdr.p_offset; - /* Get the associated file section */ - -#if 0 - printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", - (uint32_t) phdr.p_offset, - (uint32_t) phdr.p_vaddr, - (uint32_t) phdr.p_paddr, - (uint32_t) phdr.p_filesz, - (uint32_t) phdr.p_memsz); -#endif - - for (s = 0; s < nshdr; s++) { - scn = elf_getscn(e, s); - - if (!scn) { - printf ("getscn failed\n"); - abort(); - } - if (gelf_getshdr(scn, &shdr) != &shdr) { - printf ("gelf_getshdr failed\n"); - abort(); - } - - section_name = elf_strptr(e, shstrndx, shdr.sh_name); - - if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { - - if (shdr.sh_size == 0) - continue; - - sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; - - printf ("\tsize %08x rom %08x exec %08x %s\n", - (uint32_t) shdr.sh_size, - (uint32_t) sh_paddr, - (uint32_t) shdr.sh_addr, - section_name); - - data = elf_getdata(scn, NULL); - - /* Write the section data into the memory block */ - load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf); - } - } - } - return load; -} - -/* - * Open the specified ELF file and - * check for the symbols we need - */ - -struct hex_image * -ao_load_elf(char *name) -{ - 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; - struct hex_image *image; - - 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; - } - - image = get_load(e); - if (!image) { - fprintf (stderr, "Cannot create memory image from file\n"); - return NULL; - } - - return image; -} diff --git a/ao-tools/ao-stmload/ao-elf.h b/ao-tools/ao-stmload/ao-elf.h deleted file mode 100644 index 4303d5ca..00000000 --- a/ao-tools/ao-stmload/ao-elf.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_ELF_H_ -#define _AO_ELF_H_ - -struct hex_image * -ao_load_elf(char *name); - -#endif diff --git a/ao-tools/ao-stmload/ao-selfload.c b/ao-tools/ao-stmload/ao-selfload.c index 95667dca..dee1c3cb 100644 --- a/ao-tools/ao-stmload/ao-selfload.c +++ b/ao-tools/ao-stmload/ao-selfload.c @@ -64,16 +64,16 @@ ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]) } } -struct hex_image * +struct ao_hex_image * ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) { - struct hex_image *image; + struct ao_hex_image *image; int pages; int page; uint32_t base = address & ~0xff; uint32_t bound = (address + length + 0xff) & ~0xff; - image = calloc(sizeof (struct hex_image) + (bound - base), 1); + image = calloc(sizeof (struct ao_hex_image) + (bound - base), 1); image->address = base; image->length = bound - base; pages = image->length / 0x100; @@ -83,7 +83,7 @@ ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) } int -ao_self_write(struct cc_usb *cc, struct hex_image *image) +ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) { uint8_t block[256]; uint8_t check[256]; diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index dd25f07f..6e3906fd 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -34,7 +34,7 @@ #define AO_USB_DESC_STRING 3 -struct sym ao_symbols[] = { +struct ao_elf_sym ao_symbols[] = { { 0, AO_BOOT_APPLICATION_BASE + 0x100, "ao_romconfig_version", 1 }, #define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) @@ -62,7 +62,7 @@ int ao_num_required_symbols = NUM_REQUIRED_SYMBOLS; * Edit the to-be-written memory block */ static int -rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length) +rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length) { int i; @@ -86,7 +86,7 @@ rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length) static uint16_t get_uint16_cc(struct cc_usb *cc, uint32_t addr) { - struct hex_image *hex = ao_self_read(cc, addr, 2); + struct ao_hex_image *hex = ao_self_read(cc, addr, 2); uint16_t v; uint8_t *data; @@ -101,7 +101,7 @@ get_uint16_cc(struct cc_usb *cc, uint32_t addr) static uint32_t get_uint32_cc(struct cc_usb *cc, uint32_t addr) { - struct hex_image *hex = ao_self_read(cc, addr, 4); + struct ao_hex_image *hex = ao_self_read(cc, addr, 4); uint32_t v; uint8_t *data; @@ -281,7 +281,7 @@ main (int argc, char **argv) int c; stlink_t *sl = NULL; int was_flashed = 0; - struct hex_image *load; + struct ao_hex_image *load; int tries; struct cc_usb *cc = NULL; int use_stlink = 0; @@ -329,10 +329,10 @@ main (int argc, char **argv) usage(argv[0]); if (ends_with (filename, ".elf")) { - load = ao_load_elf(filename); + load = ao_load_elf(filename, ao_symbols, ao_num_symbols); } else if (ends_with (filename, ".ihx")) { int i; - load = ccdbg_hex_load(filename); + load = ao_hex_load(filename); for (i = 0; i < ao_num_symbols; i++) ao_symbols[i].addr = ao_symbols[i].default_addr; } else diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h index 98884535..28c2dda4 100644 --- a/ao-tools/ao-stmload/ao-stmload.h +++ b/ao-tools/ao-stmload/ao-stmload.h @@ -18,16 +18,11 @@ #ifndef _AO_STMLOAD_H_ #define _AO_STMLOAD_H_ -struct sym { - unsigned addr; - unsigned default_addr; - char *name; - int required; -}; +#include "ao-elf.h" #define AO_BOOT_APPLICATION_BASE 0x08001000 -extern struct sym ao_symbols[]; +extern struct ao_elf_sym ao_symbols[]; extern int ao_num_symbols; extern int ao_num_required_symbols; @@ -38,11 +33,11 @@ ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]); void ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]); -struct hex_image * +struct ao_hex_image * ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length); int -ao_self_write(struct cc_usb *cc, struct hex_image *image); +ao_self_write(struct cc_usb *cc, struct ao_hex_image *image); extern int ao_self_verbose; diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index fd4dab25..868b64f1 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -11,7 +11,6 @@ libao_tools_a_SOURCES = \ ccdbg-debug.h \ ccdbg-flash.c \ ccdbg.h \ - ccdbg-hex.c \ ccdbg-io.c \ ccdbg-manual.c \ ccdbg-memory.c \ @@ -40,4 +39,8 @@ libao_tools_a_SOURCES = \ i0.c \ chbevl.c \ mconf.h \ - cephes.h + cephes.h \ + ao-hex.c \ + ao-hex.h \ + ao-elf.c \ + ao-elf.h diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c new file mode 100644 index 00000000..932dc853 --- /dev/null +++ b/ao-tools/lib/ao-elf.c @@ -0,0 +1,293 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ao-elf.h" +#include "ao-hex.h" + +/* + * Look through the Elf file for symbols that can be adjusted before + * the image is written to the device + */ +static bool +find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols) +{ + Elf_Scn *scn; + Elf_Data *symbol_data = NULL; + GElf_Shdr shdr; + GElf_Sym sym; + int i, symbol_count, s; + char *symbol_name; + size_t shstrndx; + + if (elf_getshdrstrndx(e, &shstrndx) < 0) + return false; + + /* + * Find the symbols + */ + + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + + if (gelf_getshdr(scn, &shdr) != &shdr) + return false; + + 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 false; + + 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 (symbols[s].name, symbol_name)) { + symbols[s].addr = sym.st_value; + symbols[s].found = true; + } + } + for (s = 0; s < num_symbols; s++) + if (symbols[s].required && !symbols[s].found) + return false; + return true; +} + +static uint32_t +round4(uint32_t a) { + return (a + 3) & ~3; +} + +static struct ao_hex_image * +new_load (uint32_t addr, uint32_t len) +{ + struct ao_hex_image *new; + + len = round4(len); + new = calloc (1, sizeof (struct ao_hex_image) + len); + if (!new) + abort(); + + new->address = addr; + new->length = len; + return new; +} + +static void +load_paste(struct ao_hex_image *into, struct ao_hex_image *from) +{ + if (from->address < into->address || into->address + into->length < from->address + from->length) + abort(); + + memcpy(into->data + from->address - into->address, from->data, from->length); +} + +/* + * Make a new load structure large enough to hold the old one and + * the new data + */ +static struct ao_hex_image * +expand_load(struct ao_hex_image *from, uint32_t address, uint32_t length) +{ + struct ao_hex_image *new; + + if (from) { + uint32_t from_last = from->address + from->length; + uint32_t last = address + length; + + if (address > from->address) + address = from->address; + if (last < from_last) + last = from_last; + + length = last - address; + + if (address == from->address && length == from->length) + return from; + } + new = new_load(address, length); + if (from) { + load_paste(new, from); + free (from); + } + return new; +} + +/* + * Create a new load structure with data from the existing one + * and the new data + */ +static struct ao_hex_image * +load_write(struct ao_hex_image *from, uint32_t address, uint32_t length, void *data) +{ + struct ao_hex_image *new; + + new = expand_load(from, address, length); + memcpy(new->data + address - new->address, data, length); + return new; +} + +/* + * Construct a large in-memory block for all + * of the loaded sections of the program + */ +static struct ao_hex_image * +get_load(Elf *e) +{ + Elf_Scn *scn; + size_t shstrndx; + GElf_Shdr shdr; + Elf_Data *data; + size_t nphdr; + size_t p; + GElf_Phdr phdr; + GElf_Addr sh_paddr; + struct ao_hex_image *load = NULL; + char *section_name; + size_t nshdr; + size_t s; + + if (elf_getshdrstrndx(e, &shstrndx) < 0) + return 0; + + if (elf_getphdrnum(e, &nphdr) < 0) + return 0; + + if (elf_getshdrnum(e, &nshdr) < 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); + + if (phdr.p_type != PT_LOAD) + continue; + + /* Get the associated file section */ + +#if 0 + printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", + (uint32_t) phdr.p_offset, + (uint32_t) phdr.p_vaddr, + (uint32_t) phdr.p_paddr, + (uint32_t) phdr.p_filesz, + (uint32_t) phdr.p_memsz); +#endif + + for (s = 0; s < nshdr; s++) { + scn = elf_getscn(e, s); + + if (!scn) { + printf ("getscn failed\n"); + abort(); + } + if (gelf_getshdr(scn, &shdr) != &shdr) { + printf ("gelf_getshdr failed\n"); + abort(); + } + + section_name = elf_strptr(e, shstrndx, shdr.sh_name); + + if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { + + if (shdr.sh_size == 0) + continue; + + sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; + + printf ("\tsize %08x rom %08x exec %08x %s\n", + (uint32_t) shdr.sh_size, + (uint32_t) sh_paddr, + (uint32_t) shdr.sh_addr, + section_name); + + data = elf_getdata(scn, NULL); + + /* Write the section data into the memory block */ + load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf); + } + } + } + return load; +} + +/* + * Open the specified ELF file and + * check for the symbols we need + */ + +struct ao_hex_image * +ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols) +{ + int fd; + Elf *e; + size_t shstrndx; + struct ao_hex_image *image; + + 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, symbols, num_symbols)) { + fprintf (stderr, "Cannot find required symbols\n"); + return NULL; + } + + image = get_load(e); + if (!image) { + fprintf (stderr, "Cannot create memory image from file\n"); + return NULL; + } + + return image; +} diff --git a/ao-tools/lib/ao-elf.h b/ao-tools/lib/ao-elf.h new file mode 100644 index 00000000..f3a2358c --- /dev/null +++ b/ao-tools/lib/ao-elf.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ELF_H_ +#define _AO_ELF_H_ + +#include +#include +#include "ao-hex.h" + +struct ao_elf_sym { + unsigned addr; + unsigned default_addr; + char *name; + bool required; + bool found; +}; + +struct ao_hex_image * +ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols); + +int +ao_elf_find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols); + +#endif /* _AO_ELF_H_ */ diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c new file mode 100644 index 00000000..85acc07f --- /dev/null +++ b/ao-tools/lib/ao-hex.c @@ -0,0 +1,384 @@ +/* + * Copyright © 2008 Keith Packard + * + * 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; 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include "ao-hex.h" + +struct ao_hex_input { + FILE *file; + int line; + char *name; +}; + +enum ao_hex_read_state { + read_marker, + read_length, + read_address, + read_type, + read_data, + read_checksum, + read_newline, + read_white, + read_done, +}; + + +static void +ao_hex_error(struct ao_hex_input *input, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + fprintf(stderr, "Hex error %s:%d: ", input->name, input->line); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void +ao_hex_free(struct ao_hex_record *record) +{ + if (!record) return; + free(record); +} + +static struct ao_hex_record * +ao_hex_alloc(uint8_t length) +{ + struct ao_hex_record *record; + + record = calloc(1, sizeof(struct ao_hex_record) + length); + record->length = length; + return record; +} + +static int +ishex(char c) +{ + return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); +} + +static int +fromhex(char c) +{ + if (isdigit(c)) + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + abort(); + return 0; +} + +static uint8_t +ao_hex_checksum(struct ao_hex_record *record) +{ + uint8_t checksum = 0; + int i; + + checksum += record->length; + checksum += record->address >> 8; + checksum += record->address & 0xff; + checksum += record->type; + for (i = 0; i < record->length; i++) + checksum += record->data[i]; + return -checksum; +} + +static struct ao_hex_record * +ao_hex_read_record(struct ao_hex_input *input) +{ + struct ao_hex_record *record = NULL; + enum ao_hex_read_state state = read_marker; + char c; + int nhexbytes; + uint32_t hex; + uint32_t ndata; + uint8_t checksum; + + while (state != read_done) { + c = getc(input->file); + if (c == EOF && state != read_white) { + ao_hex_error(input, "Unexpected EOF"); + goto bail; + } + if (c == ' ') + continue; + if (c == '\n') + input->line++; + switch (state) { + case read_marker: + if (c != ':') { + ao_hex_error(input, "Missing ':'"); + goto bail; + } + state = read_length; + nhexbytes = 2; + hex = 0; + break; + case read_length: + case read_address: + case read_type: + case read_data: + case read_checksum: + if (!ishex(c)) { + ao_hex_error(input, "Non-hex char '%c'", + c); + goto bail; + } + hex = hex << 4 | fromhex(c); + --nhexbytes; + if (nhexbytes != 0) + break; + + switch (state) { + case read_length: + record = ao_hex_alloc(hex); + if (!record) { + ao_hex_error(input, "Out of memory"); + goto bail; + } + state = read_address; + nhexbytes = 4; + break; + case read_address: + record->address = hex; + state = read_type; + nhexbytes = 2; + break; + case read_type: + record->type = hex; + state = read_data; + nhexbytes = 2; + ndata = 0; + break; + case read_data: + record->data[ndata] = hex; + ndata++; + nhexbytes = 2; + break; + case read_checksum: + record->checksum = hex; + state = read_newline; + break; + default: + break; + } + if (state == read_data) + if (ndata == record->length) { + nhexbytes = 2; + state = read_checksum; + } + hex = 0; + break; + case read_newline: + if (c != '\n' && c != '\r') { + ao_hex_error(input, "Missing newline"); + goto bail; + } + state = read_white; + break; + case read_white: + if (!isspace(c)) { + if (c == '\n') + input->line--; + if (c != EOF) + ungetc(c, input->file); + state = read_done; + } + break; + case read_done: + break; + } + } + checksum = ao_hex_checksum(record); + if (checksum != record->checksum) { + ao_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n", + record->checksum, checksum); + goto bail; + } + return record; + +bail: + ao_hex_free(record); + return NULL; +} + +void +ao_hex_file_free(struct ao_hex_file *hex) +{ + int i; + + if (!hex) + return; + for (i = 0; i < hex->nrecord; i++) + ao_hex_free(hex->records[i]); + free(hex); +} + +struct ao_hex_file * +ao_hex_file_read(FILE *file, char *name) +{ + struct ao_hex_input input; + struct ao_hex_file *hex = NULL, *newhex; + struct ao_hex_record *record; + int srecord = 1; + int done = 0; + + hex = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *), 1); + input.name = name; + input.line = 1; + input.file = file; + while (!done) { + record = ao_hex_read_record(&input); + if (!record) + goto bail; + if (hex->nrecord == srecord) { + srecord *= 2; + newhex = realloc(hex, + sizeof (struct ao_hex_file) + + srecord * sizeof (struct ao_hex_record *)); + if (!newhex) + goto bail; + hex = newhex; + } + hex->records[hex->nrecord++] = record; + if (record->type == AO_HEX_RECORD_EOF) + done = 1; + } + return hex; + +bail: + ao_hex_file_free(hex); + return NULL; +} + +struct ao_hex_image * +ao_hex_image_create(struct ao_hex_file *hex) +{ + struct ao_hex_image *image; + struct ao_hex_record *record; + int i; + uint32_t addr; + uint32_t base, bound; + uint32_t offset; + uint32_t extended_addr; + + int length; + + base = 0xffffffff; + bound = 0x0; + extended_addr = 0; + for (i = 0; i < hex->nrecord; i++) { + uint32_t r_bound; + record = hex->records[i]; + switch (record->type) { + case 0: + addr = extended_addr + record->address; + r_bound = addr + record->length; + if (addr < base) + base = addr; + if (r_bound > bound) + bound = r_bound; + break; + case 1: + break; + case 2: + if (record->length != 2) + return NULL; + extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; + break; + case 4: + if (record->length != 2) + return NULL; + extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; + break; + } + + } + length = bound - base; + image = calloc(sizeof(struct ao_hex_image) + length, 1); + if (!image) + return NULL; + image->address = base; + image->length = length; + memset(image->data, 0xff, length); + extended_addr = 0; + for (i = 0; i < hex->nrecord; i++) { + record = hex->records[i]; + switch (record->type) { + case 0: + addr = extended_addr + record->address; + offset = addr - base; + memcpy(image->data + offset, record->data, record->length); + break; + case 1: + break; + case 2: + extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; + break; + case 4: + extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; + break; + } + } + return image; +} + +void +ao_hex_image_free(struct ao_hex_image *image) +{ + free(image); +} + +int +ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b) +{ + if (a->length != b->length) + return 0; + if (memcmp(a->data, b->data, a->length) != 0) + return 0; + return 1; +} + +struct ao_hex_image * +ao_hex_load(char *filename) +{ + FILE *file; + struct ao_hex_file *hex_file; + struct ao_hex_image *hex_image; + + file = fopen (filename, "r"); + if (!file) + return 0; + + hex_file = ao_hex_file_read(file, filename); + fclose(file); + if (!hex_file) + return 0; + hex_image = ao_hex_image_create(hex_file); + if (!hex_image) + return 0; + ao_hex_file_free(hex_file); + return hex_image; +} diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h new file mode 100644 index 00000000..8528eb45 --- /dev/null +++ b/ao-tools/lib/ao-hex.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_HEX_H_ +#define _AO_HEX_H_ + +#include + +#define AO_HEX_RECORD_NORMAL 0x00 +#define AO_HEX_RECORD_EOF 0x01 +#define AO_HEX_RECORD_EXTENDED_ADDRESS_4 0x02 +#define AO_HEX_RECORD_EXTENDED_ADDRESS_8 0x04 +#define AO_HEX_RECORD_SYMBOL 0xfe + +/* Intel hex file format data + */ +struct ao_hex_record { + uint8_t length; + uint16_t address; + uint8_t type; + uint8_t checksum; + uint8_t data[0]; +}; + +struct ao_hex_file { + int nrecord; + struct ao_hex_record *records[0]; +}; + +struct ao_hex_image { + uint32_t address; + uint32_t length; + uint8_t data[0]; +}; + +struct ao_hex_file * +ao_hex_file_read(FILE *file, char *name); + +void +ao_hex_file_free(struct ao_hex_file *hex); + +struct ao_hex_image * +ao_hex_image_create(struct ao_hex_file *hex); + +void +ao_hex_image_free(struct ao_hex_image *image); + +struct ao_hex_image * +ao_hex_load(char *filename); + +int +ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b); + +#endif /* _AO_HEX_H_ */ diff --git a/ao-tools/lib/ccdbg-command.c b/ao-tools/lib/ccdbg-command.c index a1002879..55c912b2 100644 --- a/ao-tools/lib/ccdbg-command.c +++ b/ao-tools/lib/ccdbg-command.c @@ -157,7 +157,7 @@ ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc) } uint8_t -ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image) +ccdbg_execute_hex_image(struct ccdbg *dbg, struct ao_hex_image *image) { uint16_t pc; uint8_t status; diff --git a/ao-tools/lib/ccdbg-flash.c b/ao-tools/lib/ccdbg-flash.c index 1b46870b..44eb952b 100644 --- a/ao-tools/lib/ccdbg-flash.c +++ b/ao-tools/lib/ccdbg-flash.c @@ -238,7 +238,7 @@ ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock) #endif uint8_t -ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) +ccdbg_flash_hex_image(struct ccdbg *dbg, struct ao_hex_image *image) { uint16_t flash_prog; uint16_t flash_len; diff --git a/ao-tools/lib/ccdbg-hex.c b/ao-tools/lib/ccdbg-hex.c deleted file mode 100644 index 184b4e3b..00000000 --- a/ao-tools/lib/ccdbg-hex.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright © 2008 Keith Packard - * - * 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; 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 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ccdbg.h" -#include -#include - -struct hex_input { - FILE *file; - int line; - char *name; -}; - -enum hex_read_state { - read_marker, - read_length, - read_address, - read_type, - read_data, - read_checksum, - read_newline, - read_white, - read_done, -}; - - -static void -ccdbg_hex_error(struct hex_input *input, char *format, ...) -{ - va_list ap; - - va_start(ap, format); - fprintf(stderr, "Hex error %s:%d: ", input->name, input->line); - vfprintf(stderr, format, ap); - fprintf(stderr, "\n"); - va_end(ap); -} - -static void -ccdbg_hex_free(struct hex_record *record) -{ - if (!record) return; - free(record); -} - -static struct hex_record * -ccdbg_hex_alloc(uint8_t length) -{ - struct hex_record *record; - - record = calloc(1, sizeof(struct hex_record) + length); - record->length = length; - return record; -} - -static int -ishex(char c) -{ - return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); -} - -static int -fromhex(char c) -{ - if (isdigit(c)) - return c - '0'; - if ('a' <= c && c <= 'f') - return c - 'a' + 10; - if ('A' <= c && c <= 'F') - return c - 'A' + 10; - abort(); - return 0; -} - -static uint8_t -ccdbg_hex_checksum(struct hex_record *record) -{ - uint8_t checksum = 0; - int i; - - checksum += record->length; - checksum += record->address >> 8; - checksum += record->address & 0xff; - checksum += record->type; - for (i = 0; i < record->length; i++) - checksum += record->data[i]; - return -checksum; -} - -static struct hex_record * -ccdbg_hex_read_record(struct hex_input *input) -{ - struct hex_record *record = NULL; - enum hex_read_state state = read_marker; - char c; - int nhexbytes; - uint32_t hex; - uint32_t ndata; - uint8_t checksum; - - while (state != read_done) { - c = getc(input->file); - if (c == EOF && state != read_white) { - ccdbg_hex_error(input, "Unexpected EOF"); - goto bail; - } - if (c == ' ') - continue; - if (c == '\n') - input->line++; - switch (state) { - case read_marker: - if (c != ':') { - ccdbg_hex_error(input, "Missing ':'"); - goto bail; - } - state = read_length; - nhexbytes = 2; - hex = 0; - break; - case read_length: - case read_address: - case read_type: - case read_data: - case read_checksum: - if (!ishex(c)) { - ccdbg_hex_error(input, "Non-hex char '%c'", - c); - goto bail; - } - hex = hex << 4 | fromhex(c); - --nhexbytes; - if (nhexbytes != 0) - break; - - switch (state) { - case read_length: - record = ccdbg_hex_alloc(hex); - if (!record) { - ccdbg_hex_error(input, "Out of memory"); - goto bail; - } - state = read_address; - nhexbytes = 4; - break; - case read_address: - record->address = hex; - state = read_type; - nhexbytes = 2; - break; - case read_type: - record->type = hex; - state = read_data; - nhexbytes = 2; - ndata = 0; - break; - case read_data: - record->data[ndata] = hex; - ndata++; - nhexbytes = 2; - break; - case read_checksum: - record->checksum = hex; - state = read_newline; - break; - default: - break; - } - if (state == read_data) - if (ndata == record->length) { - nhexbytes = 2; - state = read_checksum; - } - hex = 0; - break; - case read_newline: - if (c != '\n' && c != '\r') { - ccdbg_hex_error(input, "Missing newline"); - goto bail; - } - state = read_white; - break; - case read_white: - if (!isspace(c)) { - if (c == '\n') - input->line--; - if (c != EOF) - ungetc(c, input->file); - state = read_done; - } - break; - case read_done: - break; - } - } - checksum = ccdbg_hex_checksum(record); - if (checksum != record->checksum) { - ccdbg_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n", - record->checksum, checksum); - goto bail; - } - return record; - -bail: - ccdbg_hex_free(record); - return NULL; -} - -void -ccdbg_hex_file_free(struct hex_file *hex) -{ - int i; - - if (!hex) - return; - for (i = 0; i < hex->nrecord; i++) - ccdbg_hex_free(hex->records[i]); - free(hex); -} - -struct hex_file * -ccdbg_hex_file_read(FILE *file, char *name) -{ - struct hex_input input; - struct hex_file *hex = NULL, *newhex; - struct hex_record *record; - int srecord = 1; - int done = 0; - - hex = calloc(sizeof (struct hex_file) + sizeof (struct hex_record *), 1); - input.name = name; - input.line = 1; - input.file = file; - while (!done) { - record = ccdbg_hex_read_record(&input); - if (!record) - goto bail; - if (hex->nrecord == srecord) { - srecord *= 2; - newhex = realloc(hex, - sizeof (struct hex_file) + - srecord * sizeof (struct hex_record *)); - if (!newhex) - goto bail; - hex = newhex; - } - hex->records[hex->nrecord++] = record; - if (record->type == HEX_RECORD_EOF) - done = 1; - } - return hex; - -bail: - ccdbg_hex_file_free(hex); - return NULL; -} - -struct hex_image * -ccdbg_hex_image_create(struct hex_file *hex) -{ - struct hex_image *image; - struct hex_record *record; - int i; - uint32_t addr; - uint32_t base, bound; - uint32_t offset; - uint32_t extended_addr; - - int length; - - base = 0xffffffff; - bound = 0x0; - extended_addr = 0; - for (i = 0; i < hex->nrecord; i++) { - uint32_t r_bound; - record = hex->records[i]; - switch (record->type) { - case 0: - addr = extended_addr + record->address; - r_bound = addr + record->length; - if (addr < base) - base = addr; - if (r_bound > bound) - bound = r_bound; - break; - case 1: - break; - case 2: - if (record->length != 2) - return NULL; - extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; - break; - case 4: - if (record->length != 2) - return NULL; - extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; - break; - } - - } - length = bound - base; - image = calloc(sizeof(struct hex_image) + length, 1); - if (!image) - return NULL; - image->address = base; - image->length = length; - memset(image->data, 0xff, length); - extended_addr = 0; - for (i = 0; i < hex->nrecord; i++) { - record = hex->records[i]; - switch (record->type) { - case 0: - addr = extended_addr + record->address; - offset = addr - base; - memcpy(image->data + offset, record->data, record->length); - break; - case 1: - break; - case 2: - extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; - break; - case 4: - extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; - break; - } - } - return image; -} - -void -ccdbg_hex_image_free(struct hex_image *image) -{ - free(image); -} - -int -ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b) -{ - if (a->length != b->length) - return 0; - if (memcmp(a->data, b->data, a->length) != 0) - return 0; - return 1; -} - -struct hex_image * -ccdbg_hex_load(char *filename) -{ - FILE *file; - struct hex_file *hex_file; - struct hex_image *hex_image; - - file = fopen (filename, "r"); - if (!file) - return 0; - - hex_file = ccdbg_hex_file_read(file, filename); - fclose(file); - if (!hex_file) - return 0; - hex_image = ccdbg_hex_image_create(hex_file); - if (!hex_image) - return 0; - ccdbg_hex_file_free(hex_file); - return hex_image; -} diff --git a/ao-tools/lib/ccdbg-memory.c b/ao-tools/lib/ccdbg-memory.c index 554ac637..04059e2e 100644 --- a/ao-tools/lib/ccdbg-memory.c +++ b/ao-tools/lib/ccdbg-memory.c @@ -117,18 +117,18 @@ ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte) } uint8_t -ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset) +ccdbg_write_hex_image(struct ccdbg *dbg, struct ao_hex_image *image, uint16_t offset) { ccdbg_write_memory(dbg, image->address + offset, image->data, image->length); return 0; } -struct hex_image * +struct ao_hex_image * ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length) { - struct hex_image *image; + struct ao_hex_image *image; - image = calloc(sizeof(struct hex_image) + length, 1); + image = calloc(sizeof(struct ao_hex_image) + length, 1); image->address = address; image->length = length; memset(image->data, 0xff, length); diff --git a/ao-tools/lib/ccdbg-rom.c b/ao-tools/lib/ccdbg-rom.c index 71bed220..6e8e7378 100644 --- a/ao-tools/lib/ccdbg-rom.c +++ b/ao-tools/lib/ccdbg-rom.c @@ -19,10 +19,10 @@ #include "ccdbg.h" uint8_t -ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) +ccdbg_set_rom(struct ccdbg *dbg, struct ao_hex_image *rom) { if (dbg->rom) - ccdbg_hex_image_free(dbg->rom); + ao_hex_image_free(dbg->rom); dbg->rom = rom; return 0; } @@ -30,7 +30,7 @@ ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) uint8_t ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes) { - struct hex_image *rom = dbg->rom; + struct ao_hex_image *rom = dbg->rom; if (!rom) return 0; if (addr < rom->address || rom->address + rom->length < addr + nbytes) @@ -42,7 +42,7 @@ uint8_t ccdbg_rom_replace_xmem(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) { - struct hex_image *rom = dbg->rom; + struct ao_hex_image *rom = dbg->rom; if (!rom) return 0; diff --git a/ao-tools/lib/ccdbg.h b/ao-tools/lib/ccdbg.h index a27ff5d1..b17f289d 100644 --- a/ao-tools/lib/ccdbg.h +++ b/ao-tools/lib/ccdbg.h @@ -33,6 +33,7 @@ #include "ccdbg-debug.h" #include "cc-bitbang.h" #include "cc-usb.h" +#include "ao-hex.h" /* 8051 instructions */ @@ -103,29 +104,9 @@ struct ccdbg { struct cc_bitbang *bb; struct cc_usb *usb; - struct hex_image *rom; + struct ao_hex_image *rom; }; -/* Intel hex file format data - */ -struct hex_record { - uint8_t length; - uint16_t address; - uint8_t type; - uint8_t checksum; - uint8_t data[0]; -}; - -struct hex_file { - int nrecord; - struct hex_record *records[0]; -}; - -struct hex_image { - uint32_t address; - uint32_t length; - uint8_t data[0]; -}; #define CC_STATE_ACC 0x1 #define CC_STATE_PSW 0x2 @@ -139,10 +120,6 @@ struct ccstate { uint8_t sfr[CC_STATE_NSFR]; }; -#define HEX_RECORD_NORMAL 0x00 -#define HEX_RECORD_EOF 0x01 -#define HEX_RECORD_EXTENDED_ADDRESS 0x02 - /* CC1111 debug port commands */ #define CC_CHIP_ERASE 0x14 @@ -234,30 +211,11 @@ uint8_t ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc); uint8_t -ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image); +ccdbg_execute_hex_image(struct ccdbg *dbg, struct ao_hex_image *image); /* ccdbg-flash.c */ uint8_t -ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image); - -/* ccdbg-hex.c */ -struct hex_file * -ccdbg_hex_file_read(FILE *file, char *name); - -void -ccdbg_hex_file_free(struct hex_file *hex); - -struct hex_image * -ccdbg_hex_image_create(struct hex_file *hex); - -void -ccdbg_hex_image_free(struct hex_image *image); - -struct hex_image * -ccdbg_hex_load(char *filename); - -int -ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b); +ccdbg_flash_hex_image(struct ccdbg *dbg, struct ao_hex_image *image); /* ccdbg-io.c */ struct ccdbg * @@ -304,9 +262,9 @@ uint8_t ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte); uint8_t -ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset); +ccdbg_write_hex_image(struct ccdbg *dbg, struct ao_hex_image *image, uint16_t offset); -struct hex_image * +struct ao_hex_image * ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length); uint8_t @@ -317,7 +275,7 @@ ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); /* ccdbg-rom.c */ uint8_t -ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom); +ccdbg_set_rom(struct ccdbg *dbg, struct ao_hex_image *rom); uint8_t ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes); -- cgit v1.2.3 From ee07f1a0f8e431bebb3b948f6249f5f33413e966 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 09:29:52 -0800 Subject: ao-tools: Add debug printf support --- ao-tools/lib/ao-verbose.c | 36 ++++++++++++++++++++++++++++++++++++ ao-tools/lib/ao-verbose.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 ao-tools/lib/ao-verbose.c create mode 100644 ao-tools/lib/ao-verbose.h (limited to 'ao-tools/lib') diff --git a/ao-tools/lib/ao-verbose.c b/ao-tools/lib/ao-verbose.c new file mode 100644 index 00000000..a1678ed1 --- /dev/null +++ b/ao-tools/lib/ao-verbose.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao-verbose.h" +#include + +uint32_t ao_verbose; + +void +ao_printf(uint32_t verbose, const char *format, ...) +{ + va_list args; + + if (!(ao_verbose & verbose)) + return; + + va_start(args, format); + vprintf(format, args); + va_end(args); +} + + diff --git a/ao-tools/lib/ao-verbose.h b/ao-tools/lib/ao-verbose.h new file mode 100644 index 00000000..45a0559c --- /dev/null +++ b/ao-tools/lib/ao-verbose.h @@ -0,0 +1,31 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_VERBOSE_H_ +#define _AO_VERBOSE_H_ + +#include +#include + +uint32_t ao_verbose; + +#define AO_VERBOSE_EXE 1 + +void +ao_printf(uint32_t verbose, const char *format, ...); + +#endif /* _AO_VERBOSE_H_ */ -- cgit v1.2.3 From 14204e3d147ad99cc249ad8de254809180fe5c38 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 09:31:02 -0800 Subject: ao-tools: Add ao-elftohex and .ihx symbol support ao-elftohex converts an elf file into a hex file so that we can load it with java. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-elftohex/Makefile.am | 18 +++ ao-tools/ao-elftohex/ao-elftohex.1 | 38 +++++ ao-tools/ao-elftohex/ao-elftohex.c | 102 +++++++++++++ ao-tools/ao-stmload/ao-stmload.c | 39 ++++- ao-tools/ao-stmload/ao-stmload.h | 2 +- ao-tools/lib/Makefile.am | 4 +- ao-tools/lib/ao-elf.c | 94 ++++++++---- ao-tools/lib/ao-elf.h | 13 +- ao-tools/lib/ao-hex.c | 286 ++++++++++++++++++++++++++++++++++--- ao-tools/lib/ao-hex.h | 16 ++- configure.ac | 1 + 12 files changed, 540 insertions(+), 75 deletions(-) create mode 100644 ao-tools/ao-elftohex/Makefile.am create mode 100644 ao-tools/ao-elftohex/ao-elftohex.1 create mode 100644 ao-tools/ao-elftohex/ao-elftohex.c (limited to 'ao-tools/lib') diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 4600f1d6..9c382739 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1,3 +1,3 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \ ao-load ao-telem ao-stmload ao-send-telem ao-sky-flash \ - ao-dumpflash ao-edit-telem ao-dump-up + ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex diff --git a/ao-tools/ao-elftohex/Makefile.am b/ao-tools/ao-elftohex/Makefile.am new file mode 100644 index 00000000..33c9923f --- /dev/null +++ b/ao-tools/ao-elftohex/Makefile.am @@ -0,0 +1,18 @@ +if LIBSTLINK + +bin_PROGRAMS=ao-elftohex + +LIBSTLINKDIR=/local/src/stlink + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS) +AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_elftohex_DEPENDENCIES = $(AO_STMLOAD_LIBS) + +ao_elftohex_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf + +ao_elftohex_SOURCES=ao-elftohex.c + +man_MANS = ao-elftohex.1 + +endif diff --git a/ao-tools/ao-elftohex/ao-elftohex.1 b/ao-tools/ao-elftohex/ao-elftohex.1 new file mode 100644 index 00000000..e52e6f5a --- /dev/null +++ b/ao-tools/ao-elftohex/ao-elftohex.1 @@ -0,0 +1,38 @@ +.\" +.\" Copyright © 2013 Keith Packard +.\" +.\" 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; 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 +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +.\" General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +.\" +.\" +.TH AO-LOAD 1 "ao-elftohex" "" +.SH NAME +ao-elftohex \- convert a program to IHX format +.SH SYNOPSIS +.B "ao-elftohex" +[\--output-\fIoutput.ihx\fP] +[\--verbose] +\fIinput.elf\fP +.SH DESCRIPTION +.I ao-elftohex +reads the specified .elf file and writes out a .ihx version. +.SH OPTIONS +.TP +\--output=\fIoutput.ihx\fP +This specifies the output file (default is stdout) +.TP +\--verbose +Dumps some debug information. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-elftohex/ao-elftohex.c b/ao-tools/ao-elftohex/ao-elftohex.c new file mode 100644 index 00000000..db8f86f1 --- /dev/null +++ b/ao-tools/ao-elftohex/ao-elftohex.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include "ao-hex.h" +#include "ao-elf.h" +#include "ao-verbose.h" + +static const struct option options[] = { + { .name = "verbose", .has_arg = 1, .val = 'v' }, + { .name = "output", .has_arg = 1, .val = 'o' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--verbose=] [--output=] \n", program); + exit(1); +} + +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) +{ + char *input = NULL; + char *output = NULL; + struct ao_hex_image *image; + struct ao_sym *file_symbols; + int num_file_symbols; + FILE *file; + int c; + + while ((c = getopt_long(argc, argv, "v:o:", options, NULL)) != -1) { + switch (c) { + case 'o': + output = optarg; + break; + case 'v': + ao_verbose = (int) strtol(optarg, NULL, 0); + break; + default: + usage(argv[0]); + break; + } + } + + input = argv[optind]; + if (input == NULL) + usage(argv[0]); + + if (ends_with (input, ".ihx")) + image = ao_hex_load(input, &file_symbols, &num_file_symbols); + else + image = ao_load_elf(input, &file_symbols, &num_file_symbols); + + if (!image) + usage(argv[0]); + + if (!output) + file = stdout; + else { + file = fopen(output, "w"); + if (!file) { + perror(output); + exit(1); + } + } + + if (!ao_hex_save(file, image, file_symbols, num_file_symbols)) { + fprintf(stderr, "%s: failed to write hex file\n", output ? output : ""); + if (output) + unlink(output); + exit(1); + } + exit(0); +} diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index 6e3906fd..a11d93de 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "stlink-common.h" #include "ao-elf.h" #include "ccdbg.h" @@ -34,7 +35,7 @@ #define AO_USB_DESC_STRING 3 -struct ao_elf_sym ao_symbols[] = { +struct ao_sym ao_symbols[] = { { 0, AO_BOOT_APPLICATION_BASE + 0x100, "ao_romconfig_version", 1 }, #define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) @@ -218,6 +219,30 @@ check_flashed(stlink_t *sl, struct cc_usb *cc) return 1; } +/* + * Find the symbols needed to correctly load the program + */ + +static bool +find_symbols(struct ao_sym *file_symbols, int num_file_symbols, + struct ao_sym *symbols, int num_symbols) +{ + int f, s; + + for (f = 0; f < num_file_symbols; f++) { + for (s = 0; s < num_symbols; s++) { + if (strcmp(symbols[s].name, file_symbols[f].name) == 0) { + symbols[s].addr = file_symbols[f].addr; + symbols[s].found = true; + } + } + } + for (s = 0; s < num_symbols; s++) + if (!symbols[s].found && symbols[s].required) + return false; + return true; +} + static const struct option options[] = { { .name = "stlink", .has_arg = 0, .val = 'S' }, { .name = "tty", .has_arg = 1, .val = 'T' }, @@ -288,6 +313,8 @@ main (int argc, char **argv) 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:Sv", options, NULL)) != -1) { switch (c) { @@ -329,15 +356,15 @@ main (int argc, char **argv) usage(argv[0]); if (ends_with (filename, ".elf")) { - load = ao_load_elf(filename, ao_symbols, ao_num_symbols); + load = ao_load_elf(filename, &file_symbols, &num_file_symbols); } else if (ends_with (filename, ".ihx")) { - int i; - load = ao_hex_load(filename); - for (i = 0; i < ao_num_symbols; i++) - ao_symbols[i].addr = ao_symbols[i].default_addr; + load = ao_hex_load(filename, &file_symbols, &num_file_symbols); } else usage(argv[0]); + if (!find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) + fprintf(stderr, "Cannot find required symbols\n"); + if (use_stlink) { /* Connect to the programming dongle */ diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h index 28c2dda4..744dfa75 100644 --- a/ao-tools/ao-stmload/ao-stmload.h +++ b/ao-tools/ao-stmload/ao-stmload.h @@ -22,7 +22,7 @@ #define AO_BOOT_APPLICATION_BASE 0x08001000 -extern struct ao_elf_sym ao_symbols[]; +extern struct ao_sym ao_symbols[]; extern int ao_num_symbols; extern int ao_num_required_symbols; diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index 868b64f1..ca32e121 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -43,4 +43,6 @@ libao_tools_a_SOURCES = \ ao-hex.c \ ao-hex.h \ ao-elf.c \ - ao-elf.h + ao-elf.h \ + ao-verbose.c \ + ao-verbose.h diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c index 932dc853..99b37210 100644 --- a/ao-tools/lib/ao-elf.c +++ b/ao-tools/lib/ao-elf.c @@ -27,21 +27,26 @@ #include #include "ao-elf.h" #include "ao-hex.h" +#include "ao-verbose.h" /* * Look through the Elf file for symbols that can be adjusted before * the image is written to the device */ -static bool -find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols) +static struct ao_sym * +load_symbols (Elf *e, int *num_symbolsp) { Elf_Scn *scn; Elf_Data *symbol_data = NULL; GElf_Shdr shdr; GElf_Sym sym; - int i, symbol_count, s; + int i, symbol_count; char *symbol_name; size_t shstrndx; + struct ao_sym *symbols = NULL; + struct ao_sym *symbol; + int num_symbols = 0; + int size_symbols = 0; if (elf_getshdrstrndx(e, &shstrndx) < 0) return false; @@ -64,23 +69,46 @@ find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols) } if (!symbol_data) - return false; + return NULL; for (i = 0; i < symbol_count; i++) { gelf_getsym(symbol_data, i, &sym); symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); + if (!symbol_name[0]) + continue; - for (s = 0; s < num_symbols; s++) - if (!strcmp (symbols[s].name, symbol_name)) { - symbols[s].addr = sym.st_value; - symbols[s].found = true; - } + if (num_symbols == size_symbols) { + struct ao_sym *new_symbols; + int new_size; + + if (!size_symbols) + new_size = 16; + else + new_size = size_symbols * 2; + new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym)); + if (!new_symbols) + goto bail; + + symbols = new_symbols; + size_symbols = new_size; + } + symbol = &symbols[num_symbols]; + memset(symbol, 0, sizeof (struct ao_sym)); + symbol->name = strdup(symbol_name); + if (!symbol->name) + goto bail; + symbol->addr = sym.st_value; + ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr); + num_symbols++; } - for (s = 0; s < num_symbols; s++) - if (symbols[s].required && !symbols[s].found) - return false; - return true; + *num_symbolsp = num_symbols; + return symbols; +bail: + for (i = 0; i < num_symbols; i++) + free(symbols[i].name); + free(symbols); + return NULL; } static uint32_t @@ -173,7 +201,9 @@ get_load(Elf *e) GElf_Phdr phdr; GElf_Addr sh_paddr; struct ao_hex_image *load = NULL; +#if 0 char *section_name; +#endif size_t nshdr; size_t s; @@ -201,27 +231,29 @@ get_load(Elf *e) /* Get the associated file section */ #if 0 - printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", - (uint32_t) phdr.p_offset, - (uint32_t) phdr.p_vaddr, - (uint32_t) phdr.p_paddr, - (uint32_t) phdr.p_filesz, - (uint32_t) phdr.p_memsz); + fprintf (stderr, "offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", + (uint32_t) phdr.p_offset, + (uint32_t) phdr.p_vaddr, + (uint32_t) phdr.p_paddr, + (uint32_t) phdr.p_filesz, + (uint32_t) phdr.p_memsz); #endif for (s = 0; s < nshdr; s++) { scn = elf_getscn(e, s); if (!scn) { - printf ("getscn failed\n"); + fprintf (stderr, "getscn failed\n"); abort(); } if (gelf_getshdr(scn, &shdr) != &shdr) { - printf ("gelf_getshdr failed\n"); + fprintf (stderr, "gelf_getshdr failed\n"); abort(); } +#if 0 section_name = elf_strptr(e, shstrndx, shdr.sh_name); +#endif if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { @@ -230,11 +262,13 @@ get_load(Elf *e) sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; - printf ("\tsize %08x rom %08x exec %08x %s\n", - (uint32_t) shdr.sh_size, - (uint32_t) sh_paddr, - (uint32_t) shdr.sh_addr, - section_name); +#if 0 + fprintf (stderr, "\tsize %08x rom %08x exec %08x %s\n", + (uint32_t) shdr.sh_size, + (uint32_t) sh_paddr, + (uint32_t) shdr.sh_addr, + section_name); +#endif data = elf_getdata(scn, NULL); @@ -252,7 +286,7 @@ get_load(Elf *e) */ struct ao_hex_image * -ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols) +ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols) { int fd; Elf *e; @@ -278,10 +312,8 @@ ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols) if (elf_getshdrstrndx(e, &shstrndx) != 0) return NULL; - if (!find_symbols(e, symbols, num_symbols)) { - fprintf (stderr, "Cannot find required symbols\n"); - return NULL; - } + if (symbols) + *symbols = load_symbols(e, num_symbols); image = get_load(e); if (!image) { diff --git a/ao-tools/lib/ao-elf.h b/ao-tools/lib/ao-elf.h index f3a2358c..0f79d142 100644 --- a/ao-tools/lib/ao-elf.h +++ b/ao-tools/lib/ao-elf.h @@ -22,18 +22,7 @@ #include #include "ao-hex.h" -struct ao_elf_sym { - unsigned addr; - unsigned default_addr; - char *name; - bool required; - bool found; -}; - struct ao_hex_image * -ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols); - -int -ao_elf_find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols); +ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols); #endif /* _AO_ELF_H_ */ diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c index 85acc07f..5cfc63c1 100644 --- a/ao-tools/lib/ao-hex.c +++ b/ao-tools/lib/ao-hex.c @@ -20,8 +20,10 @@ #include #include #include +#include #include #include "ao-hex.h" +#include "ao-verbose.h" struct ao_hex_input { FILE *file; @@ -118,7 +120,7 @@ ao_hex_read_record(struct ao_hex_input *input) while (state != read_done) { c = getc(input->file); - if (c == EOF && state != read_white) { + if (c == EOF && state != read_white && state != read_marker) { ao_hex_error(input, "Unexpected EOF"); goto bail; } @@ -128,6 +130,8 @@ ao_hex_read_record(struct ao_hex_input *input) input->line++; switch (state) { case read_marker: + if (c == EOF) + return NULL; if (c != ':') { ao_hex_error(input, "Missing ':'"); goto bail; @@ -246,13 +250,20 @@ ao_hex_file_read(FILE *file, char *name) int done = 0; hex = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *), 1); + if (!hex) + return NULL; input.name = name; input.line = 1; input.file = file; while (!done) { record = ao_hex_read_record(&input); - if (!record) - goto bail; + if (!record) { + if (feof(input.file)) { + done = 1; + break; + } else + goto bail; + } if (hex->nrecord == srecord) { srecord *= 2; newhex = realloc(hex, @@ -263,8 +274,6 @@ ao_hex_file_read(FILE *file, char *name) hex = newhex; } hex->records[hex->nrecord++] = record; - if (record->type == AO_HEX_RECORD_EOF) - done = 1; } return hex; @@ -273,6 +282,92 @@ bail: return NULL; } +static struct ao_sym * +load_symbols(struct ao_hex_file *hex, + int *num_symbolsp) +{ + uint32_t extended_addr; + uint32_t addr; + int i; + struct ao_hex_record *record; + struct ao_sym *symbols = NULL; + struct ao_sym *symbol; + int num_symbols = 0; + int size_symbols = 0; + + extended_addr = 0; + for (i = 0; i < hex->nrecord; i++) { + record = hex->records[i]; + switch (record->type) { + case AO_HEX_RECORD_NORMAL: + addr = extended_addr + record->address; + break; + case AO_HEX_RECORD_EOF: + break; + case AO_HEX_RECORD_EXTENDED_ADDRESS_4: + if (record->length != 2) + goto bail; + extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; + break; + case AO_HEX_RECORD_EXTENDED_ADDRESS_8: + if (record->length != 2) + goto bail; + extended_addr = (record->data[0] << 24) | (record->data[1] << 16); + break; + case AO_HEX_RECORD_SYMBOL: + addr = extended_addr + record->address; + if (num_symbols == size_symbols) { + struct ao_sym *new_symbols; + int new_size; + + if (!size_symbols) + new_size = 16; + else + new_size = size_symbols * 2; + new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym)); + if (!new_symbols) + goto bail; + + symbols = new_symbols; + size_symbols = new_size; + } + symbol = &symbols[num_symbols]; + memset(symbol, 0, sizeof (struct ao_sym)); + symbol->name = calloc(record->length + 1, 1); + if (!symbol->name) + goto bail; + memcpy(symbol->name, record->data, record->length); + symbol->addr = addr; + ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr); + num_symbols++; + break; + } + } + *num_symbolsp = num_symbols; + return symbols; +bail: + for (i = 0; i < num_symbols; i++) + free(symbols[i].name); + free(symbols); + return NULL; +} + +static void +ao_hex_record_set_checksum(struct ao_hex_record *record) +{ + uint8_t cksum = 0; + int i; + + cksum += record->length; + cksum += record->address >> 8; + cksum += record->address; + cksum += record->type; + for (i = 0; i < record->length; i++) + cksum += record->data[i]; + + record->checksum = -cksum; +} + struct ao_hex_image * ao_hex_image_create(struct ao_hex_file *hex) { @@ -286,6 +381,8 @@ ao_hex_image_create(struct ao_hex_file *hex) int length; + /* Find the address bounds of the file + */ base = 0xffffffff; bound = 0x0; extended_addr = 0; @@ -293,7 +390,7 @@ ao_hex_image_create(struct ao_hex_file *hex) uint32_t r_bound; record = hex->records[i]; switch (record->type) { - case 0: + case AO_HEX_RECORD_NORMAL: addr = extended_addr + record->address; r_bound = addr + record->length; if (addr < base) @@ -301,20 +398,21 @@ ao_hex_image_create(struct ao_hex_file *hex) if (r_bound > bound) bound = r_bound; break; - case 1: + case AO_HEX_RECORD_EOF: break; - case 2: + case AO_HEX_RECORD_EXTENDED_ADDRESS_4: if (record->length != 2) return NULL; extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; break; - case 4: + case AO_HEX_RECORD_EXTENDED_ADDRESS_8: if (record->length != 2) return NULL; - extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; + extended_addr = (record->data[0] << 24) | (record->data[1] << 16); + break; + case AO_HEX_RECORD_SYMBOL: break; } - } length = bound - base; image = calloc(sizeof(struct ao_hex_image) + length, 1); @@ -327,18 +425,20 @@ ao_hex_image_create(struct ao_hex_file *hex) for (i = 0; i < hex->nrecord; i++) { record = hex->records[i]; switch (record->type) { - case 0: + case AO_HEX_RECORD_NORMAL: addr = extended_addr + record->address; offset = addr - base; memcpy(image->data + offset, record->data, record->length); break; - case 1: + case AO_HEX_RECORD_EOF: break; - case 2: + case AO_HEX_RECORD_EXTENDED_ADDRESS_4: extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; break; - case 4: - extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; + case AO_HEX_RECORD_EXTENDED_ADDRESS_8: + extended_addr = (record->data[0] << 24) | (record->data[1] << 16); + break; + case AO_HEX_RECORD_SYMBOL: break; } } @@ -362,23 +462,165 @@ ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b) } struct ao_hex_image * -ao_hex_load(char *filename) +ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp) { - FILE *file; + FILE *file; struct ao_hex_file *hex_file; - struct ao_hex_image *hex_image; + struct ao_hex_image *hex_image; file = fopen (filename, "r"); if (!file) - return 0; + return NULL; hex_file = ao_hex_file_read(file, filename); fclose(file); if (!hex_file) - return 0; + return NULL; hex_image = ao_hex_image_create(hex_file); if (!hex_image) - return 0; + return NULL; + + if (symbols) + *symbols = load_symbols(hex_file, num_symbolsp); + ao_hex_file_free(hex_file); return hex_image; } + +#define BYTES_PER_RECORD 32 + +static struct ao_hex_file * +ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_symbols) +{ + /* split data into n-byte-sized chunks */ + uint32_t data_records = (image->length + BYTES_PER_RECORD-1) / BYTES_PER_RECORD; + /* extended address and data for each block, EOF, address and data for each symbol */ + uint32_t total_records = data_records * 2 + 1 + num_symbols * 2; + uint32_t offset; + uint32_t address; + uint32_t length; + char *name; + struct ao_hex_file *hex_file; + int nrecord = 0; + int s; + struct ao_hex_record *record; + + hex_file = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *) * total_records, 1); + if (!hex_file) + return NULL; + + /* Add the data + */ + for (offset = 0; offset < image->length; offset += BYTES_PER_RECORD) { + uint32_t address = image->address + offset; + uint32_t length = image->length - offset; + + if (length > BYTES_PER_RECORD) + length = BYTES_PER_RECORD; + + record = calloc(sizeof (struct ao_hex_record) + 2, 1); + record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8; + record->address = 0; + record->length = 2; + record->data[0] = address >> 24; + record->data[1] = address >> 16; + ao_hex_record_set_checksum(record); + + hex_file->records[nrecord++] = record; + + record = calloc(sizeof (struct ao_hex_record) + length, 1); + record->type = AO_HEX_RECORD_NORMAL; + record->address = address; + record->length = length; + memcpy(record->data, image->data + offset, length); + ao_hex_record_set_checksum(record); + + hex_file->records[nrecord++] = record; + } + + /* Stick an EOF after the data + */ + record = calloc(sizeof (struct ao_hex_record), 1); + record->type = AO_HEX_RECORD_EOF; + record->address = 0; + record->length = 0; + record->data[0] = 0; + record->data[1] = 0; + ao_hex_record_set_checksum(record); + + hex_file->records[nrecord++] = record; + + /* Add the symbols + */ + + for (s = 0; s < num_symbols; s++) { + + name = symbols[s].name; + address = symbols[s].addr; + length = strlen (name); + + record = calloc(sizeof (struct ao_hex_record) + 2, 1); + record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8; + record->address = 0; + record->length = 2; + record->data[0] = address >> 24; + record->data[1] = address >> 16; + ao_hex_record_set_checksum(record); + + hex_file->records[nrecord++] = record; + + record = calloc(sizeof (struct ao_hex_record) + length, 1); + record->type = AO_HEX_RECORD_SYMBOL; + record->address = address; + record->length = length; + memcpy(record->data, name, length); + ao_hex_record_set_checksum(record); + + hex_file->records[nrecord++] = record; + } + + hex_file->nrecord = nrecord; + return hex_file; +} + +static bool +ao_hex_write_record(FILE *file, struct ao_hex_record *record) +{ + int i; + + fputc(':', file); + fprintf(file, "%02x", record->length); + fprintf(file, "%04x", record->address); + fprintf(file, "%02x", record->type); + for (i = 0; i < record->length; i++) + fprintf(file, "%02x", record->data[i]); + fprintf(file, "%02x", record->checksum); + fputc('\n', file); + return true; +} + +bool +ao_hex_save(FILE *file, struct ao_hex_image *image, + struct ao_sym *symbols, int num_symbols) +{ + struct ao_hex_file *hex_file; + int i; + bool ret = false; + + hex_file = ao_hex_file_create(image, symbols, num_symbols); + if (!hex_file) + goto create_failed; + + for (i = 0; i < hex_file->nrecord; i++) { + if (!ao_hex_write_record(file, hex_file->records[i])) + goto write_failed; + } + ret = true; + + if (fflush(file) != 0) + ret = false; +write_failed: + ao_hex_file_free(hex_file); +create_failed: + return ret; +} diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h index 8528eb45..98497460 100644 --- a/ao-tools/lib/ao-hex.h +++ b/ao-tools/lib/ao-hex.h @@ -19,6 +19,8 @@ #define _AO_HEX_H_ #include +#include +#include #define AO_HEX_RECORD_NORMAL 0x00 #define AO_HEX_RECORD_EOF 0x01 @@ -47,6 +49,14 @@ struct ao_hex_image { uint8_t data[0]; }; +struct ao_sym { + unsigned addr; + unsigned default_addr; + char *name; + bool required; + bool found; +}; + struct ao_hex_file * ao_hex_file_read(FILE *file, char *name); @@ -60,9 +70,13 @@ void ao_hex_image_free(struct ao_hex_image *image); struct ao_hex_image * -ao_hex_load(char *filename); +ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols); int ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b); +bool +ao_hex_save(FILE *file, struct ao_hex_image *image, + struct ao_sym *symbols, int num_symbols); + #endif /* _AO_HEX_H_ */ diff --git a/configure.ac b/configure.ac index d1de21e6..bf801744 100644 --- a/configure.ac +++ b/configure.ac @@ -406,6 +406,7 @@ ao-tools/ao-sky-flash/Makefile ao-tools/ao-dumpflash/Makefile ao-tools/ao-edit-telem/Makefile ao-tools/ao-dump-up/Makefile +ao-tools/ao-elftohex/Makefile ao-utils/Makefile src/Version ]) -- cgit v1.2.3 From d93a65a90f19e4816231e03b1f399af6e3742aee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 09:46:13 -0800 Subject: ao-tools: Move ao-selfload into library This needs to be shared between ao-stmload and ao-usbload Signed-off-by: Keith Packard --- ao-tools/ao-stmload/Makefile.am | 2 +- ao-tools/ao-stmload/ao-selfload.c | 127 -------------------------------------- ao-tools/ao-stmload/ao-stmload.c | 10 +-- ao-tools/ao-stmload/ao-stmload.h | 8 --- ao-tools/lib/Makefile.am | 2 + ao-tools/lib/ao-selfload.c | 124 +++++++++++++++++++++++++++++++++++++ ao-tools/lib/ao-verbose.h | 1 + 7 files changed, 134 insertions(+), 140 deletions(-) delete mode 100644 ao-tools/ao-stmload/ao-selfload.c create mode 100644 ao-tools/lib/ao-selfload.c (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am index 68b518f1..9ed286cc 100644 --- a/ao-tools/ao-stmload/Makefile.am +++ b/ao-tools/ao-stmload/Makefile.am @@ -11,7 +11,7 @@ ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS) ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf -ao_stmload_SOURCES=ao-stmload.c ao-stmload.h ao-selfload.c +ao_stmload_SOURCES=ao-stmload.c ao-stmload.h man_MANS = ao-stmload.1 diff --git a/ao-tools/ao-stmload/ao-selfload.c b/ao-tools/ao-stmload/ao-selfload.c deleted file mode 100644 index dee1c3cb..00000000 --- a/ao-tools/ao-stmload/ao-selfload.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include -#include -#include -#include -#include -#include "cc.h" -#include "cc-usb.h" -#include "ccdbg.h" -#include "ao-stmload.h" - -int ao_self_verbose; - -#define TRACE(...) if (ao_self_verbose) printf (__VA_ARGS__) - -void -ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]) -{ - int byte; - cc_usb_sync(cc); - cc_usb_printf(cc, "R %x\n", address); - for (byte = 0; byte < 0x100; byte++) { - block[byte] = cc_usb_getchar(cc); - } - TRACE ("\nread %08x\n", address); - for (byte = 0; byte < 0x100; byte++) { - TRACE (" %02x", block[byte]); - if ((byte & 0xf) == 0xf) - TRACE ("\n"); - } -} - -void -ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]) -{ - int byte; - cc_usb_sync(cc); - cc_usb_printf(cc, "W %x\n", address); - TRACE ("write %08x\n", address); - for (byte = 0; byte < 0x100; byte++) { - TRACE (" %02x", block[byte]); - if ((byte & 0xf) == 0xf) - TRACE ("\n"); - } - for (byte = 0; byte < 0x100; byte++) { - cc_usb_printf(cc, "%c", block[byte]); - } -} - -struct ao_hex_image * -ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) -{ - struct ao_hex_image *image; - int pages; - int page; - uint32_t base = address & ~0xff; - uint32_t bound = (address + length + 0xff) & ~0xff; - - image = calloc(sizeof (struct ao_hex_image) + (bound - base), 1); - image->address = base; - image->length = bound - base; - pages = image->length / 0x100; - for (page = 0; page < pages; page++) - ao_self_block_read(cc, image->address + page * 0x100, image->data + page * 0x100); - return image; -} - -int -ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) -{ - uint8_t block[256]; - uint8_t check[256]; - uint32_t base, bound, length, address; - uint32_t pages; - uint32_t page; - - base = image->address & ~0xff; - bound = (image->address + image->length + 0xff) & ~0xff; - - address = base; - length = bound - base; - - pages = length / 0x100; - printf ("Write %08x %d pages: ", address, length/0x100); fflush(stdout); - for (page = 0; page < pages; page++) { - uint32_t start, stop; - address = base + page * 0x100; - - if (address < image->address || address + 0x100 > image->address + image->length) { - ao_self_block_read(cc, address, block); - } - start = address; - stop = address + 0x100; - if (start < image->address) - start = image->address; - if (stop > image->address + image->length) - stop = image->address + image->length; - memcpy(block + start - address, image->data + start - image->address, stop - start); - ao_self_block_write(cc, address, block); - ao_self_block_read(cc, address, check); - if (memcmp(block, check, 0x100) != 0) { - fprintf(stderr, "Block at 0x%08x doesn't match\n", address); - return 0; - } - putchar('.'); fflush(stdout); - } - printf("done\n"); - cc_usb_printf(cc,"a\n"); - return 1; -} diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index a11d93de..71d1ec57 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -32,6 +32,8 @@ #include "cc-usb.h" #include "cc.h" #include "ao-stmload.h" +#include "ao-selfload.h" +#include "ao-verbose.h" #define AO_USB_DESC_STRING 3 @@ -249,13 +251,13 @@ static const struct option options[] = { { .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 = 0, .val = 'v' }, + { .name = "verbose", .has_arg = 1, .val = 'v' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--stlink] [--verbose] [--device=] [-tty=] [--cal=] [--serial=] file.{elf,ihx}\n", program); + fprintf(stderr, "usage: %s [--stlink] [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] file.{elf,ihx}\n", program); exit(1); } @@ -316,7 +318,7 @@ main (int argc, char **argv) struct ao_sym *file_symbols; int num_file_symbols; - while ((c = getopt_long(argc, argv, "T:D:c:s:Sv", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:c:s:Sv:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -346,7 +348,7 @@ main (int argc, char **argv) } } - ao_self_verbose = verbose; + ao_verbose = verbose; if (verbose > 1) ccdbg_add_debug(CC_DEBUG_BITBANG); diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h index 744dfa75..1ba9a977 100644 --- a/ao-tools/ao-stmload/ao-stmload.h +++ b/ao-tools/ao-stmload/ao-stmload.h @@ -33,12 +33,4 @@ ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]); void ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]); -struct ao_hex_image * -ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length); - -int -ao_self_write(struct cc_usb *cc, struct ao_hex_image *image); - -extern int ao_self_verbose; - #endif /* _AO_STMLOAD_H_ */ diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index ca32e121..5f47c089 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -44,5 +44,7 @@ libao_tools_a_SOURCES = \ ao-hex.h \ ao-elf.c \ ao-elf.h \ + ao-selfload.c \ + ao-selfload.h \ ao-verbose.c \ ao-verbose.h diff --git a/ao-tools/lib/ao-selfload.c b/ao-tools/lib/ao-selfload.c new file mode 100644 index 00000000..bf036f33 --- /dev/null +++ b/ao-tools/lib/ao-selfload.c @@ -0,0 +1,124 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include "ao-hex.h" +#include "ao-selfload.h" +#include "ao-verbose.h" + +#define TRACE(...) ao_printf(AO_VERBOSE_SELF, __VA_ARGS__) + +static void +ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ + int byte; + cc_usb_sync(cc); + cc_usb_printf(cc, "R %x\n", address); + for (byte = 0; byte < 0x100; byte++) { + block[byte] = cc_usb_getchar(cc); + } + TRACE ("\nread %08x\n", address); + for (byte = 0; byte < 0x100; byte++) { + TRACE (" %02x", block[byte]); + if ((byte & 0xf) == 0xf) + TRACE ("\n"); + } +} + +static void +ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ + int byte; + cc_usb_sync(cc); + cc_usb_printf(cc, "W %x\n", address); + TRACE ("write %08x\n", address); + for (byte = 0; byte < 0x100; byte++) { + TRACE (" %02x", block[byte]); + if ((byte & 0xf) == 0xf) + TRACE ("\n"); + } + for (byte = 0; byte < 0x100; byte++) { + cc_usb_printf(cc, "%c", block[byte]); + } +} + +struct ao_hex_image * +ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) +{ + struct ao_hex_image *image; + int pages; + int page; + uint32_t base = address & ~0xff; + uint32_t bound = (address + length + 0xff) & ~0xff; + + image = calloc(sizeof (struct ao_hex_image) + (bound - base), 1); + image->address = base; + image->length = bound - base; + pages = image->length / 0x100; + for (page = 0; page < pages; page++) + ao_self_block_read(cc, image->address + page * 0x100, image->data + page * 0x100); + return image; +} + +bool +ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) +{ + uint8_t block[256]; + uint8_t check[256]; + uint32_t base, bound, length, address; + uint32_t pages; + uint32_t page; + + base = image->address & ~0xff; + bound = (image->address + image->length + 0xff) & ~0xff; + + address = base; + length = bound - base; + + pages = length / 0x100; + printf ("Write %08x %d pages: ", address, length/0x100); fflush(stdout); + for (page = 0; page < pages; page++) { + uint32_t start, stop; + address = base + page * 0x100; + + if (address < image->address || address + 0x100 > image->address + image->length) { + ao_self_block_read(cc, address, block); + } + start = address; + stop = address + 0x100; + if (start < image->address) + start = image->address; + if (stop > image->address + image->length) + stop = image->address + image->length; + memcpy(block + start - address, image->data + start - image->address, stop - start); + ao_self_block_write(cc, address, block); + ao_self_block_read(cc, address, check); + if (memcmp(block, check, 0x100) != 0) { + fprintf(stderr, "Block at 0x%08x doesn't match\n", address); + return 0; + } + putchar('.'); fflush(stdout); + } + printf("done\n"); + cc_usb_printf(cc,"a\n"); + return 1; +} diff --git a/ao-tools/lib/ao-verbose.h b/ao-tools/lib/ao-verbose.h index 45a0559c..26c2fe41 100644 --- a/ao-tools/lib/ao-verbose.h +++ b/ao-tools/lib/ao-verbose.h @@ -24,6 +24,7 @@ uint32_t ao_verbose; #define AO_VERBOSE_EXE 1 +#define AO_VERBOSE_SELF 2 void ao_printf(uint32_t verbose, const char *format, ...); -- cgit v1.2.3 From e6c9ca218d944443c86555e513534d82713af936 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 09:52:01 -0800 Subject: ao-tools: move 16/32-bit readers from ao-stmload to lib --- ao-tools/ao-stmload/ao-stmload.c | 40 ++-------------------------------------- ao-tools/lib/ao-selfload.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 38 deletions(-) (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index 71d1ec57..7f521bbc 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -56,10 +56,8 @@ struct ao_sym ao_symbols[] = { }; #define NUM_SYMBOLS 5 -#define NUM_REQUIRED_SYMBOLS 3 int ao_num_symbols = NUM_SYMBOLS; -int ao_num_required_symbols = NUM_REQUIRED_SYMBOLS; /* * Edit the to-be-written memory block @@ -82,40 +80,6 @@ rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length) memcpy(load->data + address - load->address, data, length); } -/* - * Read a 16-bit value from the USB target - */ - -static uint16_t -get_uint16_cc(struct cc_usb *cc, uint32_t addr) -{ - struct ao_hex_image *hex = ao_self_read(cc, addr, 2); - uint16_t v; - uint8_t *data; - - if (!hex) - return 0; - data = hex->data + addr - hex->address; - v = data[0] | (data[1] << 8); - free(hex); - return v; -} - -static uint32_t -get_uint32_cc(struct cc_usb *cc, uint32_t addr) -{ - struct ao_hex_image *hex = ao_self_read(cc, addr, 4); - uint32_t v; - uint8_t *data; - - if (!hex) - return 0; - data = hex->data + addr - hex->address; - v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - free(hex); - return v; -} - /* * Read a 16-bit value from the target device with arbitrary * alignment @@ -148,7 +112,7 @@ get_uint16(stlink_t *sl, struct cc_usb *cc, uint32_t addr) { uint16_t result; if (cc) - result = get_uint16_cc(cc, addr); + result = ao_self_get_uint16(cc, addr); else result = get_uint16_sl(sl, addr); printf ("read 0x%08x = 0x%04x\n", addr, result); @@ -193,7 +157,7 @@ get_uint32(stlink_t *sl, struct cc_usb *cc, uint32_t addr) uint32_t result; if (cc) - result = get_uint32_cc(cc, addr); + result = ao_self_get_uint32(cc, addr); else result = get_uint32_sl(sl, addr); printf ("read 0x%08x = 0x%08x\n", addr, result); diff --git a/ao-tools/lib/ao-selfload.c b/ao-tools/lib/ao-selfload.c index bf036f33..41e45adc 100644 --- a/ao-tools/lib/ao-selfload.c +++ b/ao-tools/lib/ao-selfload.c @@ -122,3 +122,37 @@ ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) cc_usb_printf(cc,"a\n"); return 1; } + +/* + * Read a 16-bit value from the USB target + */ + +uint16_t +ao_self_get_uint16(struct cc_usb *cc, uint32_t addr) +{ + struct ao_hex_image *hex = ao_self_read(cc, addr, 2); + uint16_t v; + uint8_t *data; + + if (!hex) + return 0; + data = hex->data + addr - hex->address; + v = data[0] | (data[1] << 8); + free(hex); + return v; +} + +uint32_t +ao_self_get_uint32(struct cc_usb *cc, uint32_t addr) +{ + struct ao_hex_image *hex = ao_self_read(cc, addr, 4); + uint32_t v; + uint8_t *data; + + if (!hex) + return 0; + data = hex->data + addr - hex->address; + v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + free(hex); + return v; +} -- cgit v1.2.3 From 5ef287723f8d8bfbfb3582d22bfb5c2a3129414a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 09:52:38 -0800 Subject: ao-tools: Missing ao-selfload.h --- ao-tools/lib/ao-selfload.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 ao-tools/lib/ao-selfload.h (limited to 'ao-tools/lib') diff --git a/ao-tools/lib/ao-selfload.h b/ao-tools/lib/ao-selfload.h new file mode 100644 index 00000000..a001a404 --- /dev/null +++ b/ao-tools/lib/ao-selfload.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SELFLOAD_H_ +#define _AO_SELFLOAD_H_ + +#include +#include "ao-hex.h" +#include "cc-usb.h" + +struct ao_hex_image * +ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length); + +bool +ao_self_write(struct cc_usb *cc, struct ao_hex_image *image); + +uint16_t +ao_self_get_uint16(struct cc_usb *cc, uint32_t addr); + +uint32_t +ao_self_get_uint32(struct cc_usb *cc, uint32_t addr); + +#endif /* _AO_SELFLOAD_H_ */ -- cgit v1.2.3 From f27dff090c8f3a63bd932715643980703160bde6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Nov 2013 10:31:32 -0800 Subject: ao-tools: Split out altos symbol editing from ao-stmload to be shared with ao-usbload Signed-off-by: Keith Packard --- ao-tools/ao-stmload/ao-stmload.c | 129 +-------------------------------- ao-tools/lib/Makefile.am | 2 + ao-tools/lib/ao-editaltos.c | 153 +++++++++++++++++++++++++++++++++++++++ ao-tools/lib/ao-editaltos.h | 50 +++++++++++++ 4 files changed, 208 insertions(+), 126 deletions(-) create mode 100644 ao-tools/lib/ao-editaltos.c create mode 100644 ao-tools/lib/ao-editaltos.h (limited to 'ao-tools/lib') diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index 7f521bbc..f78626ac 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -34,51 +34,8 @@ #include "ao-stmload.h" #include "ao-selfload.h" #include "ao-verbose.h" +#include "ao-editaltos.h" -#define AO_USB_DESC_STRING 3 - -struct ao_sym ao_symbols[] = { - - { 0, AO_BOOT_APPLICATION_BASE + 0x100, "ao_romconfig_version", 1 }, -#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) - - { 0, AO_BOOT_APPLICATION_BASE + 0x102, "ao_romconfig_check", 1 }, -#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr) - - { 0, AO_BOOT_APPLICATION_BASE + 0x104, "ao_serial_number", 1 }, -#define AO_SERIAL_NUMBER (ao_symbols[2].addr) - - { 0, AO_BOOT_APPLICATION_BASE + 0x108, "ao_radio_cal", 0 }, -#define AO_RADIO_CAL (ao_symbols[3].addr) - - { 0, AO_BOOT_APPLICATION_BASE + 0x10c, "ao_usb_descriptors", 0 }, -#define AO_USB_DESCRIPTORS (ao_symbols[4].addr) -}; - -#define NUM_SYMBOLS 5 - -int ao_num_symbols = NUM_SYMBOLS; - -/* - * Edit the to-be-written memory block - */ -static int -rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length) -{ - int i; - - if (address < load->address || load->address + load->length < address + length) - return 0; - - printf("rewrite %04x:", address); - for (i = 0; i < length; i++) - printf (" %02x", load->data[address - load->address + i]); - printf(" ->"); - for (i = 0; i < length; i++) - printf (" %02x", data[i]); - printf("\n"); - memcpy(load->data + address - load->address, data, length); -} /* * Read a 16-bit value from the target device with arbitrary @@ -185,30 +142,6 @@ check_flashed(stlink_t *sl, struct cc_usb *cc) return 1; } -/* - * Find the symbols needed to correctly load the program - */ - -static bool -find_symbols(struct ao_sym *file_symbols, int num_file_symbols, - struct ao_sym *symbols, int num_symbols) -{ - int f, s; - - for (f = 0; f < num_file_symbols; f++) { - for (s = 0; s < num_symbols; s++) { - if (strcmp(symbols[s].name, file_symbols[f].name) == 0) { - symbols[s].addr = file_symbols[f].addr; - symbols[s].found = true; - } - } - } - for (s = 0; s < num_symbols; s++) - if (!symbols[s].found && symbols[s].required) - return false; - return true; -} - static const struct option options[] = { { .name = "stlink", .has_arg = 0, .val = 'S' }, { .name = "tty", .has_arg = 1, .val = 'T' }, @@ -328,7 +261,7 @@ main (int argc, char **argv) } else usage(argv[0]); - if (!find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) + if (ao_editaltos_find_symbols(file_symbols, num_file_symbols, ao_symbols, ao_num_symbols)) fprintf(stderr, "Cannot find required symbols\n"); if (use_stlink) { @@ -465,64 +398,8 @@ 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, cc, 1); - } - - if (AO_USB_DESCRIPTORS) { - uint32_t usb_descriptors = AO_USB_DESCRIPTORS - load->address; - string_num = 0; - - while (load->data[usb_descriptors] != 0 && usb_descriptors < load->length) { - if (load->data[usb_descriptors+1] == AO_USB_DESC_STRING) { - ++string_num; - if (string_num == 4) - break; - } - usb_descriptors += load->data[usb_descriptors]; - } - if (usb_descriptors >= load->length || load->data[usb_descriptors] == 0 ) { - fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS); - done(sl, cc, 1); - } - - serial_ucs2_len = load->data[usb_descriptors] - 2; - serial_ucs2 = malloc(serial_ucs2_len); - if (!serial_ucs2) { - fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); - done(sl, cc, 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->address, serial_ucs2, serial_ucs2_len)) { - fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS); - done(sl, cc, 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 */ diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index 5f47c089..a03a976c 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -42,6 +42,8 @@ libao_tools_a_SOURCES = \ cephes.h \ ao-hex.c \ ao-hex.h \ + ao-editaltos.c \ + ao-editaltos.h \ ao-elf.c \ ao-elf.h \ ao-selfload.c \ diff --git a/ao-tools/lib/ao-editaltos.c b/ao-tools/lib/ao-editaltos.c new file mode 100644 index 00000000..a8b64098 --- /dev/null +++ b/ao-tools/lib/ao-editaltos.c @@ -0,0 +1,153 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include "ao-editaltos.h" + +struct ao_sym ao_symbols[] = { + + { 0, 0, "ao_romconfig_version", 1 }, + { 0, 0, "ao_romconfig_check", 1 }, + { 0, 0, "ao_serial_number", 1 }, + { 0, 0, "ao_radio_cal", 0 }, + { 0, 0, "ao_usb_descriptors", 0 }, +}; + +#define NUM_SYMBOLS 5 + +int ao_num_symbols = NUM_SYMBOLS; + +/* + * Edit the to-be-written memory block + */ +static bool +rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length) +{ + int i; + + if (address < load->address || load->address + load->length < address + length) + return false; + + printf("rewrite %04x:", address); + for (i = 0; i < length; i++) + printf (" %02x", load->data[address - load->address + i]); + printf(" ->"); + for (i = 0; i < length; i++) + printf (" %02x", data[i]); + printf("\n"); + memcpy(load->data + address - load->address, data, length); + return true; +} + +/* + * Find the symbols needed to correctly load the program + */ + +bool +ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols, + struct ao_sym *symbols, int num_symbols) +{ + int f, s; + + for (f = 0; f < num_file_symbols; f++) { + for (s = 0; s < num_symbols; s++) { + if (strcmp(symbols[s].name, file_symbols[f].name) == 0) { + symbols[s].addr = file_symbols[f].addr; + symbols[s].found = true; + } + } + } + for (s = 0; s < num_symbols; s++) + if (!symbols[s].found && symbols[s].required) + return false; + return true; +} + +bool +ao_editaltos(struct ao_hex_image *image, + uint16_t serial, + uint32_t cal) +{ + uint8_t *serial_ucs2; + int serial_ucs2_len; + uint8_t serial_int[2]; + unsigned int s; + int i; + int string_num; + uint8_t cal_int[4]; + + /* Write the config values into the flash image + */ + + serial_int[0] = serial & 0xff; + serial_int[1] = (serial >> 8) & 0xff; + + if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) { + fprintf(stderr, "Cannot rewrite serial integer at %08x\n", + AO_SERIAL_NUMBER); + return false; + } + + if (AO_USB_DESCRIPTORS) { + uint32_t usb_descriptors = AO_USB_DESCRIPTORS - image->address; + string_num = 0; + + while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { + if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + usb_descriptors += image->data[usb_descriptors]; + } + if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) { + fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS); + return false; + } + + serial_ucs2_len = image->data[usb_descriptors] - 2; + serial_ucs2 = malloc(serial_ucs2_len); + if (!serial_ucs2) { + fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); + return false; + } + 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(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) { + fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS); + return false; + } + } + + 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(image, AO_RADIO_CAL, cal_int, sizeof (cal_int))) { + fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL); + return false; + } + } + return true; +} diff --git a/ao-tools/lib/ao-editaltos.h b/ao-tools/lib/ao-editaltos.h new file mode 100644 index 00000000..74530435 --- /dev/null +++ b/ao-tools/lib/ao-editaltos.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EDITALTOS_H_ +#define _AO_EDITALTOS_H_ + +#include +#include +#include "ao-hex.h" + +extern struct ao_sym ao_symbols[]; +extern int ao_num_symbols; + +#define AO_USB_DESC_STRING 3 + +#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) +#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr) +#define AO_SERIAL_NUMBER (ao_symbols[2].addr) +#define AO_RADIO_CAL (ao_symbols[3].addr) +#define AO_USB_DESCRIPTORS (ao_symbols[4].addr) + +struct ao_editaltos_funcs { + uint16_t (*get_uint16)(void *closure, uint32_t addr); + uint32_t (*get_uint32)(void *closure, uint32_t addr); +}; + +bool +ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols, + struct ao_sym *symbols, int num_symbols); + +bool +ao_editaltos(struct ao_hex_image *image, + uint16_t serial, + uint32_t radio_cal); + +#endif /* _AO_EDITALTOS_H_ */ -- cgit v1.2.3