From db0406d75d27f79386b43afd8d2a8bf2d9d79b89 Mon Sep 17 00:00:00 2001 From: Daniel Beer Date: Mon, 12 Jul 2010 16:36:01 +1200 Subject: [PATCH] Added support for S19 file format. --- Makefile | 10 ++-- binfile.c | 5 ++ srec.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ srec.h | 27 ++++++++++ titext.c | 10 ++-- util.h | 6 +++ 6 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 srec.c create mode 100644 srec.h diff --git a/Makefile b/Makefile index 5376895..1473a46 100644 --- a/Makefile +++ b/Makefile @@ -20,11 +20,11 @@ INSTALL = /usr/bin/install PREFIX ?= /usr/local ifdef WITHOUT_READLINE -READLINE_CFLAGS = -READLINE_LIBS = + READLINE_CFLAGS = + READLINE_LIBS = else -READLINE_CFLAGS = -DUSE_READLINE -READLINE_LIBS = -lreadline + READLINE_CFLAGS = -DUSE_READLINE + READLINE_LIBS = -lreadline endif # Mac OS X/MacPorts stuff @@ -56,7 +56,7 @@ install: mspdebug mspdebug.man mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \ util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \ cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o \ - usbutil.o titext.o + usbutil.o titext.o srec.o $(CC) $(LDFLAGS) $(MACPORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) .c.o: diff --git a/binfile.c b/binfile.c index 29aaef6..4f4c459 100644 --- a/binfile.c +++ b/binfile.c @@ -22,6 +22,7 @@ #include "elf32.h" #include "symmap.h" #include "titext.h" +#include "srec.h" struct file_format { int (*check)(FILE *in); @@ -46,6 +47,10 @@ static const struct file_format formats[] = { { .check = titext_check, .extract = titext_extract + }, + { + .check = srec_check, + .extract = srec_extract } }; diff --git a/srec.c b/srec.c new file mode 100644 index 0000000..cb43c2a --- /dev/null +++ b/srec.c @@ -0,0 +1,148 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "srec.h" +#include "util.h" + +int srec_check(FILE *in) +{ + char buf[128]; + int i; + + rewind(in); + if (!fgets(buf, sizeof(buf), in)) + return 0; + + if (buf[0] != 'S') + return 0; + + for (i = 1; buf[i] && !isspace(buf[i]); i++) + if (!ishex(buf[i])) + return 0; + + for (; buf[i]; i++) + if (!isspace(buf[i])) + return 0; + + return 1; +} + +static int hexval(int c) +{ + if (isdigit(c)) + return c - '0'; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return c - 'a' + 10; +} + +int srec_extract(FILE *in, binfile_imgcb_t cb, void *user_data) +{ + char buf[128]; + int lno = 0; + + rewind(in); + while (fgets(buf, sizeof(buf), in)) { + uint8_t bytes[128]; + uint8_t cksum = 0; + int count = 0; + int i; + + lno++; + + if (buf[0] != 'S') { + fprintf(stderr, "srec: garbage on line %d\n", lno); + return -1; + } + + for (i = 2; ishex(buf[i]) && ishex(buf[i + 1]); i += 2) { + if (count >= sizeof(bytes)) { + fprintf(stderr, "srec: too many bytes on " + "line %d\n", lno); + return -1; + } + + bytes[count++] = (hexval(buf[i]) << 4) | + hexval(buf[i + 1]); + } + + while (buf[i]) { + if (!isspace(buf[i])) { + fprintf(stderr, "srec: trailing garbage on " + "line %d\n", lno); + return -1; + } + + i++; + } + + if (count < 2) { + fprintf(stderr, "srec: too few bytes on line %d\n", + lno); + return -1; + } + + if (bytes[0] + 1 != count) { + fprintf(stderr, "srec: byte count mismatch on " + "line %d\n", lno); + return -1; + } + + for (i = 0; i + 1 < count; i++) + cksum += bytes[i]; + cksum = ~cksum; + if (cksum != bytes[count - 1]) { + fprintf(stderr, "srec: checksum error on line %d " + "(calc = 0x%02x, read = 0x%02x)\n", + lno, cksum, bytes[count - 1]); + return -1; + } + + if (buf[1] >= '1' && buf[1] <= '3') { + int addrbytes = buf[1] - '1' + 2; + int addr = 0; + + for (i = 0; i < addrbytes; i++) + addr = (addr << 8) | bytes[i + 1]; + + if (count < addrbytes + 2) { + fprintf(stderr, "srec: too few address bytes " + "on line %d\n", lno); + return -1; + } + + if (addr > 0xffff) { + fprintf(stderr, "srec: address out of range " + "on line %d: 0x%x\n", lno, addr); + return -1; + } + + if (cb(user_data, addr, bytes + addrbytes + 1, + count - 2 - addrbytes) < 0) { + fprintf(stderr, "srec: error on line %d\n", + lno); + return -1; + } + } + } + + return 0; +} diff --git a/srec.h b/srec.h new file mode 100644 index 0000000..86a9587 --- /dev/null +++ b/srec.h @@ -0,0 +1,27 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SREC_H_ +#define SREC_H_ + +#include "binfile.h" + +int srec_check(FILE *in); +int srec_extract(FILE *in, binfile_imgcb_t cb, void *user_data); + +#endif diff --git a/titext.c b/titext.c index 6a096e7..73f7992 100644 --- a/titext.c +++ b/titext.c @@ -19,11 +19,7 @@ #include #include #include "titext.h" - -static inline int ishex(int c) -{ - return isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); -} +#include "util.h" static int is_address_line(const char *text) { @@ -65,7 +61,9 @@ int titext_check(FILE *in) char buf[64]; rewind(in); - fgets(buf, sizeof(buf), in); + if (!fgets(buf, sizeof(buf), in)) + return 0; + return is_address_line(buf); } diff --git a/util.h b/util.h index b009193..1c71142 100644 --- a/util.h +++ b/util.h @@ -20,6 +20,7 @@ #define UTIL_H_ #include +#include #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -49,4 +50,9 @@ void debug_hexdump(const char *label, /* Get text length, not including ANSI codes */ int textlen(const char *text); +static inline int ishex(int c) +{ + return isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + #endif