diff --git a/avrdude/avr.c b/avrdude/avr.c index 5413a91d..69decd01 100644 --- a/avrdude/avr.c +++ b/avrdude/avr.c @@ -489,7 +489,6 @@ char * avr_memtstr ( AVRMEM memtype ) } - int avr_initmem ( struct avrpart * p ) { int i; @@ -508,8 +507,11 @@ int avr_initmem ( struct avrpart * p ) /* - * Verify up to 'size' bytes of p against v. Return the number of - * bytes verified, or -1 if they don't match. + * Verify the memory buffer of p with that of v. The byte range of v, + * may be a subset of p. The byte range of p should cover the whole + * chip's memory size. + * + * Return the number of bytes verified, or -1 if they don't match. */ int avr_verify(struct avrpart * p, struct avrpart * v, AVRMEM memtype, int size) { diff --git a/avrdude/fileio.c b/avrdude/fileio.c index 44642a53..041740d2 100644 --- a/avrdude/fileio.c +++ b/avrdude/fileio.c @@ -29,7 +29,9 @@ /* $Id$ */ +#include <limits.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <errno.h> #include <ctype.h> @@ -38,6 +40,17 @@ #include "fileio.h" +#define IHEX_MAXDATA 256 + +struct ihexrec { + unsigned char reclen; + unsigned short loadofs; + unsigned char rectyp; + unsigned char data[IHEX_MAXDATA]; + unsigned char cksum; +}; + + extern char * progname; extern char progbuf[]; @@ -135,101 +148,174 @@ int b2ihex ( unsigned char * inbuf, int bufsize, } +int ihex_readrec ( struct ihexrec * ihex, char * rec ) +{ + int i, j; + char buf[8]; + int offset, len; + char * e; + unsigned char cksum; + int rc; + + len = strlen(rec); + offset = 1; + cksum = 0; + + /* reclen */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->reclen = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + /* load offset */ + if (offset + 4 > len) + return -1; + for (i=0; i<4; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->loadofs = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + /* record type */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->rectyp = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + cksum = ihex->reclen + ((ihex->loadofs >> 8 ) & 0x0ff) + + (ihex->loadofs & 0x0ff) + ihex->rectyp; + + /* data */ + for (j=0; j<ihex->reclen; j++) { + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->data[j] = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + cksum += ihex->data[j]; + } + + /* cksum */ + if (offset + 2 > len) + return -1; + for (i=0; i<2; i++) + buf[i] = rec[offset++]; + buf[i] = 0; + ihex->cksum = strtoul(buf, &e, 16); + if (e == buf || *e != 0) + return -1; + + rc = -cksum & 0x000000ff; + + return rc; +} + + + + int ihex2b ( char * infile, FILE * inf, unsigned char * outbuf, int bufsize ) { - unsigned char buffer [ MAX_LINE_LEN ]; + char buffer [ MAX_LINE_LEN ]; unsigned char * buf; - unsigned int nextaddr; - unsigned int b; - int n, nbytes; - int i, j; - unsigned int cksum, rectype; + unsigned int nextaddr, baseaddr; + int nbytes; + int i; int lineno; + int len; + struct ihexrec ihex; + int rc; lineno = 0; buf = outbuf; nbytes = 0; + baseaddr = 0; while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { lineno++; + len = strlen(buffer); + if (buffer[len-1] == '\n') + buffer[--len] = 0; if (buffer[0] != ':') continue; - if (sscanf((char *)&buffer[1], - "%02x%04x%02x", &n, &nextaddr, &rectype) != 3) { + rc = ihex_readrec(&ihex, buffer); + if (rc < 0) { fprintf(stderr, "%s: invalid record at line %d of \"%s\"\n", progname, lineno, infile); - exit(1); + return -1; } - - if ((rectype != 0) && (rectype != 1)) { - fprintf(stderr, - "%s: don't know how to deal with rectype=%d " - "at line %d of %s\n", - progname, rectype, lineno, infile); - exit(1); - } - - if (n && ((nextaddr + n) > bufsize)) { - fprintf(stderr, "%s: address 0x%04x out of range at line %d of %s\n", - progname, nextaddr+n, lineno, infile); + else if (rc != ihex.cksum) { + fprintf(stderr, "%s: ERROR: checksum mismatch at line %d of \"%s\"\n", + progname, lineno, infile); + fprintf(stderr, "%s: checksum=0x%02x, computed checksum=0x%02x\n", + progname, ihex.cksum, rc); return -1; } - /* start computing a checksum */ - cksum = n + ((nextaddr >> 8 ) & 0x0ff) + (nextaddr & 0x0ff) + rectype; + switch (ihex.rectyp) { - for (i=0; i<n; i++) { - if (sscanf((char *)&buffer[i*2+9], "%02x", &b) != 1) { - fprintf(stderr, "%s: can't scan byte number %d at line %d of %s\n", - progname, i, lineno, infile); - /* display the buffer and the position of the scan error */ - fprintf(stderr, "%s", buffer); - for (j=0; j<9+2*i; j++) { - fprintf(stderr, " "); + case 0: /* data record */ + nextaddr = ihex.loadofs + baseaddr; + 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; } - fprintf(stderr, "^\n"); + for (i=0; i<ihex.reclen; i++) { + buf[nextaddr+i] = ihex.data[i]; + } + nbytes += ihex.reclen; + break; + + case 1: /* end of file record */ + return nbytes; + break; + + case 2: /* extended segment address record */ + baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 4; + break; + + case 3: /* start segment address record */ + /* we don't do anything with the start address */ + break; + + case 4: /* extended linear address record */ + baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 16; + break; + + case 5: /* start linear address record */ + /* we don't do anything with the start address */ + break; + + default: + fprintf(stderr, + "%s: don't know how to deal with rectype=%d " + "at line %d of %s\n", + progname, ihex.rectyp, lineno, infile); return -1; - } - - buf[nextaddr + i] = b; - cksum += b; - } - - nbytes += n; - - /*----------------------------------------------------------------- - read the cksum value from the record and compare it with our - computed value - -----------------------------------------------------------------*/ - if (sscanf((char *)&buffer[n*2+9], "%02x", &b) != 1) { - fprintf(stderr, "%s: can't scan byte number %d at line %d of %s\n", - progname, i, lineno, infile); - /* display the buffer and the position of the scan error */ - fprintf(stderr, "%s", buffer); - for (j=0; j<9+2*i; j++) { - fprintf(stderr, " "); - } - fprintf(stderr, "^\n"); - return -1; - } - - cksum = -cksum & 0xff; - if (cksum != b) { - fprintf(stderr, - "%s: WARNING: cksum error for line %d of \"%s\": computed=%02x " - "found=%02x\n", - progname, lineno, infile, cksum, b); - /* return -1; */ - } - - if (rectype == 1) { - /* end of record */ - return nbytes; + break; } } /* while */ + fprintf(stderr, + "%s: WARNING: no end of file record found for Intel Hex " + "file \"%s\"\n", + progname, infile); + return nbytes; }