Commit 95638c32fb24c716668443dcfa17454355ef3708
authorMichel Pollet <buserror@gmail.com>
Tue, 16 Jun 2015 18:06:10 +0000 (19:06 +0100)
committerMichel Pollet <buserror@gmail.com>
Thu, 2 Jul 2015 18:02:54 +0000 (19:02 +0100)
Use ihex_read_chunk to implement ihex_read_file, and add a
ihex_free_chuncks for consistency sake

Signed-off-by: Michel Pollet <buserror@gmail.com>
2 files changed:
simavr/sim/sim_hex.c
simavr/sim/sim_hex.h

index a8bcf631395cece99eeb245fa64018ea27153016..18047c2d554dd0fd46b9a93613e0a01262320944 100644 (file)
@@ -74,85 +74,17 @@ int read_hex_string(const char * src, uint8_t * buffer, int maxlen)
     return dst - buffer;
 }
 
-uint8_t * read_ihex_file(const char * fname, uint32_t * dsize, uint32_t * start)
+void
+free_ihex_chunks(
+               ihex_chunk_p chunks)
 {
-       if (!fname || !dsize)
-               return NULL;
-       FILE * f = fopen(fname, "r");
-       if (!f) {
-               perror(fname);
-               return NULL;
-       }
-       uint8_t * res = NULL;
-       uint32_t size = 0;
-       uint32_t base = ~0;
-       uint32_t segment = 0;
-
-       while (!feof(f)) {
-               char line[128];
-               if (!fgets(line, sizeof(line)-1, f))
-                       continue;
-               if (line[0] != ':') {
-                       fprintf(stderr, "AVR: '%s' invalid ihex format (%.4s)\n",
-                                       fname, line);
-                       break;
-               }
-               uint8_t bline[64];
-
-               int len = read_hex_string(line + 1, bline, sizeof(bline));
-               if (len <= 0)
-                       continue;
-
-               uint8_t chk = 0;
-               {       // calculate checksum
-                       uint8_t * src = bline;
-                       int tlen = len-1;
-                       while (tlen--)
-                               chk += *src++;
-                       chk = 0x100 - chk;
-               }
-               if (chk != bline[len-1]) {
-                       fprintf(stderr, "%s: %s, invalid checksum %02x/%02x\n",
-                                       __func__, fname, chk, bline[len-1]);
-                       break;
-               }
-               switch (bline[3]) {
-                       case 0: // data
-                               break;
-                       case 1: // end of data
-                               segment = 0;
-                               continue;
-                       case 2: // extended record (for big flash)
-                               segment = ((bline[4] << 8) | bline[5]) << 4;
-                               continue;
-                       case 3: // CS:IP value. WTF in AVR ihex format? perhaps PC value?
-                               continue;
-                       default:
-                               fprintf(stderr, "%s: %s, unsupported chunk type %02x\n",
-                                               __func__, fname, bline[3]);
-                               continue;
-               }
-               uint32_t addr = segment | (bline[1] << 8) | bline[2];
-               if (base == ~0) {
-                       base = addr;    // start address
-               }
-               if (addr != base + size) {
-                       fprintf(stderr, "%s: %s, offset out of bounds %04x(%d) expected %04x\n",
-                                       __func__, fname, addr, bline[0], base+size);
-                       break;
-               }
-               res = realloc(res, size + bline[0]);
-               memcpy(res + size, bline + 4, bline[0]);
-               size += bline[0];
-       }
-       *dsize = size;
-       if (start)
-               *start = base;
-       fclose(f);
-       return res;
+       if (!chunks)
+               return;
+       for (int i = 0; chunks[i].size; i++)
+               if (chunks[i].data)
+                       free(chunks[i].data);
 }
 
-
 int
 read_ihex_chunks(
                const char * fname,
@@ -218,12 +150,16 @@ read_ihex_chunks(
                }
                if (chunk >= max_chunks) {
                        max_chunks++;
-                       *chunks = realloc(*chunks, max_chunks * sizeof(ihex_chunk_t));
-                       memset(*chunks + chunk, 0, (max_chunks - chunk) * sizeof(ihex_chunk_t));
+                       /* Here we allocate and zero an extra chunk, to act as terminator */
+                       *chunks = realloc(*chunks, (1 + max_chunks) * sizeof(ihex_chunk_t));
+                       memset(*chunks + chunk, 0,
+                                       (1 + (max_chunks - chunk)) * sizeof(ihex_chunk_t));
                        (*chunks)[chunk].baseaddr = addr;
                }
-               (*chunks)[chunk].data = realloc((*chunks)[chunk].data, (*chunks)[chunk].size + bline[0]);
-               memcpy((*chunks)[chunk].data + (*chunks)[chunk].size, bline + 4, bline[0]);
+               (*chunks)[chunk].data = realloc((*chunks)[chunk].data,
+                                                                       (*chunks)[chunk].size + bline[0]);
+               memcpy((*chunks)[chunk].data + (*chunks)[chunk].size,
+                               bline + 4, bline[0]);
                (*chunks)[chunk].size += bline[0];
        }
        fclose(f);
@@ -231,6 +167,30 @@ read_ihex_chunks(
 }
 
 
+uint8_t *
+read_ihex_file(
+               const char * fname, uint32_t * dsize, uint32_t * start)
+{
+       ihex_chunk_p chunks = NULL;
+       int count = read_ihex_chunks(fname, &chunks);
+       uint8_t * res = NULL;
+
+       if (count > 0) {
+               *dsize = chunks[0].size;
+               *start = chunks[0].baseaddr;
+               res = chunks[0].data;
+               chunks[0].data = NULL;
+       }
+       if (count > 1) {
+               fprintf(stderr, "AVR: '%s' ihex contains more chunks than loaded (%d)\n",
+                               fname, count);
+       }
+       free_ihex_chunks(chunks);
+       return res;
+}
+
+
+
 #ifdef IHEX_TEST
 // gcc -std=gnu99 -Isimavr/sim simavr/sim/sim_hex.c -o sim_hex -DIHEX_TEST -Dtest_main=main
 int test_main(int argc, char * argv[])
index 89ba939df87419df52c469db05477939cc97c761..4b3fe76cb1babf00fd77a7c8dcd0664276a08223 100644 (file)
@@ -52,6 +52,10 @@ int
 read_ihex_chunks(
                const char * fname,
                ihex_chunk_p * chunks );
+/* Frees previously allocated chunks */
+void
+free_ihex_chunks(
+               ihex_chunk_p chunks);
 
 // reads IHEX file 'fname', puts it's decoded size in *'dsize' and returns
 // a newly allocated buffer with the binary data (or NULL, if error)