From 8770c07d357ebb8581becfaf880a7beb21f6f952 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Mon, 10 Oct 2011 13:42:08 +0000 Subject: [PATCH] bug #34518: loading intel hex files > 64k using record-type 4 (Extended Linear Address Record) Replace the change from r928 (handling of 0x8000000 offset in AVR32 files) by a completely different logic that no longer breaks hex files for other devices starting with an offset; also apply a similar change to S-record files, as well as when writing files. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1017 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 11 +++++++ fileio.c | 85 +++++++++++++++++++++++++++++++++++-------------------- fileio.h | 3 +- 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3eccb524..87853bfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-10-10 Joerg Wunsch + + bug #34518: loading intel hex files > 64k using record-type 4 + (Extended Linear Address Record) + fileio.c: Replace the change from r928 (handling of 0x8000000 + offset in AVR32 files) by a completely different logic that no + longer breaks hex files for other devices starting with an + offset; also apply a similar change to S-record files, as well + as when writing files. + fileio.c: (Ditto.) + 2011-09-15 Joerg Wunsch * avrftdi.c: Remove stray printf()s by fprintf(stderr) diff --git a/fileio.c b/fileio.c index ad523253..fa07a8f3 100644 --- a/fileio.c +++ b/fileio.c @@ -52,14 +52,14 @@ static int b2ihex(unsigned char * inbuf, int bufsize, char * outfile, FILE * outf); static int ihex2b(char * infile, FILE * inf, - AVRMEM * mem, int bufsize); + AVRMEM * mem, int bufsize, unsigned int fileoffset); static int b2srec(unsigned char * inbuf, int bufsize, int recsize, int startaddr, char * outfile, FILE * outf); static int srec2b(char * infile, FILE * inf, - AVRMEM * mem, int bufsize); + AVRMEM * mem, int bufsize, unsigned int fileoffset); static int ihex_readrec(struct ihexrec * ihex, char * rec); @@ -262,21 +262,20 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) * * */ static int ihex2b(char * infile, FILE * inf, - AVRMEM * mem, int bufsize) + AVRMEM * mem, int bufsize, unsigned int fileoffset) { char buffer [ MAX_LINE_LEN ]; - unsigned int nextaddr, baseaddr, maxaddr, offsetaddr; + unsigned int nextaddr, baseaddr, maxaddr; int i; int lineno; int len; struct ihexrec ihex; int rc; - lineno = 0; - baseaddr = 0; - maxaddr = 0; - offsetaddr = 0; - nextaddr = 0; + lineno = 0; + baseaddr = 0; + maxaddr = 0; + nextaddr = 0; while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { lineno++; @@ -301,23 +300,29 @@ static int ihex2b(char * infile, FILE * inf, switch (ihex.rectyp) { case 0: /* data record */ - nextaddr = ihex.loadofs + baseaddr; - if ((nextaddr + ihex.reclen) > (bufsize+offsetaddr)) { + if (fileoffset != 0 && baseaddr < fileoffset) { + fprintf(stderr, + "%s: ERROR: address 0x%04x out of range (below fileoffset 0x%x) at line %d of %s\n", + progname, baseaddr, fileoffset, lineno, infile); + return -1; + } + nextaddr = ihex.loadofs + baseaddr - fileoffset; + if (nextaddr + ihex.reclen > bufsize) { fprintf(stderr, "%s: ERROR: address 0x%04x out of range at line %d of %s\n", progname, nextaddr+ihex.reclen, lineno, infile); return -1; } for (i=0; ibuf[nextaddr+i-offsetaddr] = ihex.data[i]; - mem->tags[nextaddr+i-offsetaddr] = TAG_ALLOCATED; + mem->buf[nextaddr+i] = ihex.data[i]; + mem->tags[nextaddr+i] = TAG_ALLOCATED; } if (nextaddr+ihex.reclen > maxaddr) maxaddr = nextaddr+ihex.reclen; break; case 1: /* end of file record */ - return maxaddr-offsetaddr; + return maxaddr; break; case 2: /* extended segment address record */ @@ -330,7 +335,6 @@ static int ihex2b(char * infile, FILE * inf, case 4: /* extended linear address record */ baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 16; - if(nextaddr == 0) offsetaddr = baseaddr; // if provided before any data, then remember it break; case 5: /* start linear address record */ @@ -353,7 +357,7 @@ static int ihex2b(char * infile, FILE * inf, "file \"%s\"\n", progname, infile); - return maxaddr-offsetaddr; + return maxaddr; } static int b2srec(unsigned char * inbuf, int bufsize, @@ -539,10 +543,10 @@ static int srec_readrec(struct ihexrec * srec, char * rec) static int srec2b(char * infile, FILE * inf, - AVRMEM * mem, int bufsize) + AVRMEM * mem, int bufsize, unsigned int fileoffset) { char buffer [ MAX_LINE_LEN ]; - unsigned int nextaddr, baseaddr, maxaddr; + unsigned int nextaddr, maxaddr; int i; int lineno; int len; @@ -554,7 +558,6 @@ static int srec2b(char * infile, FILE * inf, char * msg = 0; lineno = 0; - baseaddr = 0; maxaddr = 0; reccount = 0; @@ -588,17 +591,17 @@ static int srec2b(char * infile, FILE * inf, case 0x31: /* S1 - 16 bit address data record */ datarec=1; - msg="%s: ERROR: address 0x%04x out of range at line %d of %s\n"; + msg="%s: ERROR: address 0x%04x out of range %sat line %d of %s\n"; break; case 0x32: /* S2 - 24 bit address data record */ datarec=1; - msg="%s: ERROR: address 0x%06x out of range at line %d of %s\n"; + msg="%s: ERROR: address 0x%06x out of range %sat line %d of %s\n"; break; case 0x33: /* S3 - 32 bit address data record */ datarec=1; - msg="%s: ERROR: address 0x%08x out of range at line %d of %s\n"; + msg="%s: ERROR: address 0x%08x out of range %sat line %d of %s\n"; break; case 0x34: /* S4 - symbol record (LSI extension) */ @@ -634,9 +637,17 @@ static int srec2b(char * infile, FILE * inf, } if (datarec == 1) { - nextaddr = srec.loadofs + baseaddr; + nextaddr = srec.loadofs; + if (nextaddr < fileoffset) { + fprintf(stderr, msg, progname, nextaddr, + "(below fileoffset) ", + lineno, infile); + return -1; + } + nextaddr -= fileoffset; if (nextaddr + srec.reclen > bufsize) { - fprintf(stderr, msg, progname, nextaddr+srec.reclen, lineno, infile); + fprintf(stderr, msg, progname, nextaddr+srec.reclen, "", + lineno, infile); return -1; } for (i=0; iop) { case FIO_WRITE: - rc = b2ihex(mem->buf, size, 32, 0, filename, f); + rc = b2ihex(mem->buf, size, 32, fio->fileoffset, filename, f); if (rc < 0) { return -1; } break; case FIO_READ: - rc = ihex2b(filename, f, mem, size); + rc = ihex2b(filename, f, mem, size, fio->fileoffset); if (rc < 0) return -1; break; @@ -816,14 +827,14 @@ static int fileio_srec(struct fioparms * fio, switch (fio->op) { case FIO_WRITE: - rc = b2srec(mem->buf, size, 32, 0, filename, f); + rc = b2srec(mem->buf, size, 32, fio->fileoffset, filename, f); if (rc < 0) { return -1; } break; case FIO_READ: - rc = srec2b(filename, f, mem, size); + rc = srec2b(filename, f, mem, size, fio->fileoffset); if (rc < 0) return -1; break; @@ -912,7 +923,8 @@ static int fileio_num(struct fioparms * fio, } -int fileio_setparms(int op, struct fioparms * fp) +int fileio_setparms(int op, struct fioparms * fp, + struct avrpart * p, AVRMEM * m) { fp->op = op; @@ -938,6 +950,19 @@ int fileio_setparms(int op, struct fioparms * fp) break; } + /* + * AVR32 devices maintain their load offset within the file itself, + * but AVRDUDE maintains all memory images 0-based. + */ + if ((p->flags & AVRPART_AVR32) != 0) + { + fp->fileoffset = m->offset; + } + else + { + fp->fileoffset = 0; + } + return 0; } @@ -1032,7 +1057,7 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - rc = fileio_setparms(op, &fio); + rc = fileio_setparms(op, &fio, p, mem); if (rc < 0) return -1; diff --git a/fileio.h b/fileio.h index 2fe3f209..711dca5a 100644 --- a/fileio.h +++ b/fileio.h @@ -40,6 +40,7 @@ struct fioparms { char * iodesc; char * dir; char * rw; + unsigned int fileoffset; }; enum { @@ -53,8 +54,6 @@ extern "C" { char * fmtstr(FILEFMT format); -int fileio_setparms(int op, struct fioparms * fp); - int fileio(int op, char * filename, FILEFMT format, struct avrpart * p, char * memtype, int size);