ao-tools/lib: Add loading support for 32-bit ihx files
authorKeith Packard <keithp@keithp.com>
Sun, 24 Mar 2013 22:30:24 +0000 (15:30 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 8 May 2013 03:16:52 +0000 (20:16 -0700)
These place the upper 16 bits of the address in a special record. That
requires handling records in file order, so don't sort them in address
order anymore, instead find the bounds of the loaded data by scanning
them all.

Signed-off-by: Keith Packard <keithp@keithp.com>
ao-tools/lib/ccdbg-hex.c
ao-tools/lib/ccdbg.h

index dfea915601a74e6258d8c6427b885eaf300870c5..184b4e3b8e1b51fb344a3492aae40b43d7ea3007 100644 (file)
@@ -233,15 +233,6 @@ ccdbg_hex_file_free(struct hex_file *hex)
        free(hex);
 }
 
-static int
-ccdbg_hex_record_compar(const void *av, const void *bv)
-{
-       const struct hex_record *a = *(struct hex_record **) av;
-       const struct hex_record *b = *(struct hex_record **) bv;
-
-       return (int) a->address - (int) b->address;
-}
-
 struct hex_file *
 ccdbg_hex_file_read(FILE *file, char *name)
 {
@@ -272,11 +263,6 @@ ccdbg_hex_file_read(FILE *file, char *name)
                if (record->type == HEX_RECORD_EOF)
                        done = 1;
        }
-       /*
-        * Sort them into increasing addresses, except for EOF
-        */
-       qsort(hex->records, hex->nrecord - 1, sizeof (struct hex_record *),
-             ccdbg_hex_record_compar);
        return hex;
 
 bail:
@@ -288,16 +274,45 @@ struct hex_image *
 ccdbg_hex_image_create(struct hex_file *hex)
 {
        struct hex_image *image;
-       struct hex_record *first, *last, *record;
+       struct hex_record *record;
        int i;
+       uint32_t addr;
        uint32_t base, bound;
        uint32_t offset;
+       uint32_t extended_addr;
+
        int length;
 
-       first = hex->records[0];
-       last = hex->records[hex->nrecord - 2];  /* skip EOF */
-       base = (uint32_t) first->address;
-       bound = (uint32_t) last->address + (uint32_t) last->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)
@@ -305,10 +320,24 @@ ccdbg_hex_image_create(struct hex_file *hex)
        image->address = base;
        image->length = length;
        memset(image->data, 0xff, length);
-       for (i = 0; i < hex->nrecord - 1; i++) {
+       extended_addr = 0;
+       for (i = 0; i < hex->nrecord; i++) {
                record = hex->records[i];
-               offset = record->address - base;
-               memcpy(image->data + offset, record->data, record->length);
+               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;
 }
@@ -328,3 +357,25 @@ ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b)
                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 ca5961432d8926b649c916e7182e962221d88921..a27ff5d1c9c664368b3f12a0cf3128389339ca4e 100644 (file)
@@ -122,8 +122,8 @@ struct hex_file {
 };
 
 struct hex_image {
-       uint16_t        address;
-       uint16_t        length;
+       uint32_t        address;
+       uint32_t        length;
        uint8_t         data[0];
 };
 
@@ -253,6 +253,9 @@ 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);