ao-tools: Create general elf and hex library routines
authorKeith Packard <keithp@keithp.com>
Wed, 27 Nov 2013 21:59:06 +0000 (13:59 -0800)
committerKeith Packard <keithp@keithp.com>
Wed, 27 Nov 2013 21:59:06 +0000 (13:59 -0800)
Pulls the elf stuff out of ao-stmload, change the hex stuff into ao_
routines.

Signed-off-by: Keith Packard <keithp@keithp.com>
20 files changed:
ao-tools/ao-dbg/ao-dbg-command.c
ao-tools/ao-load/ao-load.c
ao-tools/ao-rawload/ao-rawload.c
ao-tools/ao-stmload/Makefile.am
ao-tools/ao-stmload/ao-elf.c [deleted file]
ao-tools/ao-stmload/ao-elf.h [deleted file]
ao-tools/ao-stmload/ao-selfload.c
ao-tools/ao-stmload/ao-stmload.c
ao-tools/ao-stmload/ao-stmload.h
ao-tools/lib/Makefile.am
ao-tools/lib/ao-elf.c [new file with mode: 0644]
ao-tools/lib/ao-elf.h [new file with mode: 0644]
ao-tools/lib/ao-hex.c [new file with mode: 0644]
ao-tools/lib/ao-hex.h [new file with mode: 0644]
ao-tools/lib/ccdbg-command.c
ao-tools/lib/ccdbg-flash.c
ao-tools/lib/ccdbg-hex.c [deleted file]
ao-tools/lib/ccdbg-memory.c
ao-tools/lib/ccdbg-rom.c
ao-tools/lib/ccdbg.h

index eab7bc689d7502f5832f61957ac06e22e8556fb2..11c521e88d5a47614137a651f4ac6a02a7a252fa 100644 (file)
@@ -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;
 }
 
index e3cef4a5664f61c8d06959482dc48db8a342a08d..c1f551499ceac969b76072f417bb3f66f49e3e31 100644 (file)
@@ -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);
        }
index a4746b195411ac8d73bb237774f12cea3020b808..17ed73cae20e5ac58a7176ba8583459da22b7e07 100644 (file)
@@ -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);
        }
index 4eaf699cac02de404eec0ac1114452683ee7eeb6..68b518f15b070af7d3d2f339cc17422562666804 100644 (file)
@@ -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 (file)
index dad8fb8..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * 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 <err.h>
-#include <gelf.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#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 (file)
index 4303d5c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * 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
index 95667dcac21f4e8459d1729f344121a44140bc24..dee1c3cbd6d3ac151e9279eb0f0e63d5423bca86 100644 (file)
@@ -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];
index dd25f07f8e0cb6f2d355a15a72c1e09931a1c92e..6e3906fd691a1f40f10e29ffdddd4a02254c58db 100644 (file)
@@ -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
index 98884535f6ecaf4926685d4d99e70a807b31d00b..28c2dda47a46100346f45acc6a693292ddde3b7c 100644 (file)
 #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;
 
index fd4dab253a8f4d33ffa3d6c07bd3bc5dd2758a09..868b64f157de882a14f253d9e3966367ab7bf5d4 100644 (file)
@@ -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 (file)
index 0000000..932dc85
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#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 (file)
index 0000000..f3a2358
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <stdbool.h>
+#include <gelf.h>
+#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 (file)
index 0000000..85acc07
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..8528eb4
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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 <stdint.h>
+
+#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_ */
index a1002879f815b178630face7a11ff8e365440350..55c912b295a003162972f73c588abfa35e89733c 100644 (file)
@@ -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;
index 1b46870b86d96de483ea59b72be2443eb1ddb39d..44eb952baaa1236400cb3f8c690cc793989941cb 100644 (file)
@@ -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 (file)
index 184b4e3..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright © 2008 Keith Packard <keithp@keithp.com>
- *
- * 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 <stdarg.h>
-#include <ctype.h>
-
-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;
-}
index 554ac637c6911491e61005ba76ca7932d8d06686..04059e2eeddacf373bf2bf6437321ef72663acbb 100644 (file)
@@ -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);
index 71bed2200478b2f9b56a199f2a8e7a8ee87d523f..6e8e7378ef1a38f3c899e346b7fe851cb6b1e2be 100644 (file)
 #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;
 
index a27ff5d1c9c664368b3f12a0cf3128389339ca4e..b17f289d59894d0f72d532ed0b331373ceae21ff 100644 (file)
@@ -33,6 +33,7 @@
 #include "ccdbg-debug.h"
 #include "cc-bitbang.h"
 #include "cc-usb.h"
+#include "ao-hex.h"
 
 /* 8051 instructions
  */
 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);