Added ELF support, made all buffers u_int8_t.

This commit is contained in:
Daniel Beer 2010-01-05 17:21:45 +13:00
parent 34e1d2d7a1
commit 1d3b4f3f81
9 changed files with 423 additions and 135 deletions

View File

@ -25,7 +25,7 @@ clean:
.SUFFIXES: .c .o
mspdebug: main.o fet.o rf2500.o dis.o uif.o
mspdebug: main.o fet.o rf2500.o dis.o uif.o ihex.o elf32.o
$(CC) $(CFLAGS) -o $@ $^ -lusb
.c.o:

36
binfile.h Normal file
View File

@ -0,0 +1,36 @@
/* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009 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 BINFILE_H_
#define BINFILE_H_
#include <stdio.h>
#include <sys/types.h>
/* Callback for binary image data */
typedef int (*imgfunc_t)(u_int16_t addr, const u_int8_t *data, int len);
/* Intel HEX file support */
int ihex_check(FILE *in);
int ihex_extract(FILE *in, imgfunc_t cb);
/* ELF32 file support */
int elf32_check(FILE *in);
int elf32_extract(FILE *in, imgfunc_t cb);
#endif

192
elf32.c Normal file
View File

@ -0,0 +1,192 @@
/* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009 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 <errno.h>
#include <string.h>
#include <elf.h>
#include "binfile.h"
#define EM_MSP430 0x69
static const u_int8_t elf32_id[] = {
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32
};
#define MAX_PHDRS 32
#define MAX_SHDRS 32
static Elf32_Ehdr file_ehdr;
static Elf32_Phdr file_phdrs[MAX_PHDRS];
static Elf32_Shdr file_shdrs[MAX_SHDRS];
static int read_ehdr(FILE *in)
{
int i;
/* Read and check the ELF header */
rewind(in);
if (fread(&file_ehdr, sizeof(file_ehdr), 1, in) < 0) {
perror("elf32: couldn't read ELF header");
return -1;
}
for (i = 0; i < sizeof(elf32_id); i++)
if (file_ehdr.e_ident[i] != elf32_id[i]) {
fprintf(stderr, "elf32: not an ELF32 file\n");
return -1;
}
return 0;
}
static int read_phdr(FILE *in)
{
int i;
if (file_ehdr.e_phnum > MAX_PHDRS) {
fprintf(stderr, "elf32: too many program headers: %d\n",
file_ehdr.e_phnum);
return -1;
}
for (i = 0; i < file_ehdr.e_phnum; i++) {
if (fseek(in, i * file_ehdr.e_phentsize + file_ehdr.e_phoff,
SEEK_SET) < 0) {
fprintf(stderr, "elf32: can't seek to phdr %d\n", i);
return -1;
}
if (fread(&file_phdrs[i], sizeof(file_phdrs[0]), 1, in) < 0) {
fprintf(stderr, "elf32: can't read phdr %d: %s\n",
i, strerror(errno));
return -1;
}
}
return 0;
}
static int read_shdr(FILE *in)
{
int i;
if (file_ehdr.e_shnum > MAX_SHDRS) {
fprintf(stderr, "elf32: too many section headers: %d\n",
file_ehdr.e_shnum);
return -1;
}
for (i = 0; i < file_ehdr.e_shnum; i++) {
if (fseek(in, i * file_ehdr.e_shentsize + file_ehdr.e_shoff,
SEEK_SET) < 0) {
fprintf(stderr, "elf32: can't seek to phdr %d\n", i);
return -1;
}
if (fread(&file_shdrs[i], sizeof(file_shdrs[0]), 1, in) < 0) {
fprintf(stderr, "elf32: can't read phdr %d: %s\n",
i, strerror(errno));
return -1;
}
}
return 0;
}
static u_int32_t file_to_phys(u_int32_t v)
{
int i;
for (i = 0; i < file_ehdr.e_phnum; i++) {
Elf32_Phdr *p = &file_phdrs[i];
if (v >= p->p_offset && v - p->p_offset < p->p_filesz)
return v - p->p_offset + p->p_paddr;
}
return v;
}
static int feed_section(FILE *in, int offset, int size, imgfunc_t cb)
{
u_int8_t buf[1024];
u_int16_t addr = file_to_phys(offset);
if (fseek(in, offset, SEEK_SET) < 0) {
perror("elf32: can't seek to section");
return -1;
}
while (size) {
int ask = size > sizeof(buf) ? sizeof(buf) : size;
int len = fread(buf, 1, ask, in);
if (len < 0) {
perror("elf32: can't read section");
return -1;
}
if (cb(addr, buf, len) < 0)
return -1;
size -= len;
offset += len;
addr += len;
}
return 0;
}
int elf32_extract(FILE *in, imgfunc_t cb)
{
int i;
if (read_ehdr(in) < 0)
return -1;
if (file_ehdr.e_machine != EM_MSP430) {
fprintf(stderr, "elf32: this is not an MSP430 ELF32\n");
return -1;
}
if (read_phdr(in) < 0)
return -1;
if (read_shdr(in) < 0)
return -1;
for (i = 0; i < file_ehdr.e_shnum; i++) {
Elf32_Shdr *s = &file_shdrs[i];
if (s->sh_type == SHT_PROGBITS && s->sh_flags & SHF_ALLOC &&
feed_section(in, s->sh_offset, s->sh_size, cb) < 0)
return -1;
}
return 0;
}
int elf32_check(FILE *in)
{
int i;
rewind(in);
for (i = 0; i < sizeof(elf32_id); i++)
if (fgetc(in) != elf32_id[i])
return 0;
return 1;
}

28
fet.c
View File

@ -105,7 +105,7 @@ static void init_codes(void)
* needs to be stored in little-endian format at the end of the payload.
*/
static u_int16_t calc_checksum(const char *data, int len)
static u_int16_t calc_checksum(const u_int8_t *data, int len)
{
int i;
u_int16_t cksum = 0xffff;
@ -140,13 +140,13 @@ static u_int16_t calc_checksum(const char *data, int len)
*
* No checksums are included.
*/
static int send_rf2500_data(const char *data, int len)
static int send_rf2500_data(const u_int8_t *data, int len)
{
int offset = 0;
assert (fet_transport != NULL);
while (len) {
char pbuf[63];
u_int8_t pbuf[63];
int plen = len > 59 ? 59 : len;
pbuf[0] = 0x83;
@ -165,7 +165,7 @@ static int send_rf2500_data(const char *data, int len)
return 0;
}
static char fet_buf[65538];
static u_int8_t fet_buf[65538];
static int fet_len;
#define MAX_PARAMS 16
@ -178,7 +178,7 @@ static struct {
int argc;
u_int32_t argv[MAX_PARAMS];
char *data;
u_int8_t *data;
int datalen;
} fet_reply;
@ -372,12 +372,12 @@ static int recv_packet(void)
static int send_command(int command_code,
const u_int32_t *params, int nparams,
const char *extra, int exlen)
const u_int8_t *extra, int exlen)
{
char datapkt[256];
u_int8_t datapkt[256];
int len = 0;
char buf[512];
u_int8_t buf[512];
u_int16_t cksum;
int i = 0;
int j;
@ -449,7 +449,7 @@ static int send_command(int command_code,
return fet_transport->send(buf, i);
}
static int xfer(int command_code, const char *data, int datalen,
static int xfer(int command_code, const u_int8_t *data, int datalen,
int nparams, ...)
{
u_int32_t params[MAX_PARAMS];
@ -534,7 +534,7 @@ static const struct {
}
};
extern void hexdump(int addr, const char *data, int len);
extern void hexdump(int addr, const u_int8_t *data, int len);
static int do_identify(void)
{
@ -633,7 +633,7 @@ int fet_open(const struct fet_transport *tr, int proto_flags, int vcc_mv)
* This is RF2500-specific.
*/
if (fet_is_rf2500) {
static const char data[] = {
static const u_int8_t data[] = {
0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10,
0xff, 0x10, 0x40, 0x00, 0x00, 0x02, 0xff, 0x05,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
@ -703,7 +703,7 @@ int fet_get_context(u_int16_t *regs)
int fet_set_context(u_int16_t *regs)
{
char buf[FET_NUM_REGS * 4];
u_int8_t buf[FET_NUM_REGS * 4];;
int i;
int ret;
@ -729,7 +729,7 @@ int fet_set_context(u_int16_t *regs)
return 0;
}
int fet_read_mem(u_int16_t addr, char *buffer, int count)
int fet_read_mem(u_int16_t addr, u_int8_t *buffer, int count)
{
while (count) {
int plen = count > 128 ? 128 : count;
@ -755,7 +755,7 @@ int fet_read_mem(u_int16_t addr, char *buffer, int count)
return 0;
}
int fet_write_mem(u_int16_t addr, char *buffer, int count)
int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count)
{
while (count) {
int plen = count > 128 ? 128 : count;

8
fet.h
View File

@ -39,8 +39,8 @@ int rf2500_open(void);
* high-level functions.
*/
struct fet_transport {
int (*send)(const char *data, int len);
int (*recv)(char *data, int max_len);
int (*send)(const u_int8_t *data, int len);
int (*recv)(u_int8_t *data, int max_len);
void (*close)(void);
};
@ -90,8 +90,8 @@ int fet_erase(int type, u_int16_t addr, int len);
/* Read and write memory. fet_write_mem can be used to reflash the
* device, but only after an erase.
*/
int fet_read_mem(u_int16_t addr, char *buffer, int count);
int fet_write_mem(u_int16_t addr, char *buffer, int count);
int fet_read_mem(u_int16_t addr, u_int8_t *buffer, int count);
int fet_write_mem(u_int16_t addr, const u_int8_t *buffer, int count);
/* Fetch the device status. If the device is currently running, then
* the FET_POLL_RUNNING flag will be set. FET_POLL_BREAKPOINT is set

93
ihex.c Normal file
View File

@ -0,0 +1,93 @@
/* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009 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 <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "binfile.h"
int ihex_check(FILE *in)
{
rewind(in);
return fgetc(in) == ':';
}
static int feed_line(FILE *in, u_int8_t *data, int nbytes, imgfunc_t cb)
{
u_int8_t cksum = 0;
int i;
if (nbytes < 5 || data[3])
return 0;
/* Verify checksum */
for (i = 0; i + 1 < nbytes; i++)
cksum += data[i];
cksum = ~(cksum - 1) & 0xff;
if (data[nbytes - 1] != cksum) {
fprintf(stderr, "ihex: invalid checksum: %02x "
"(calculated %02x)\n", data[nbytes - 1], cksum);
return -1;
}
return cb(((u_int16_t)data[1]) << 8 | ((u_int16_t)data[2]),
data + 4, nbytes - 5);
}
int ihex_extract(FILE *in, imgfunc_t cb)
{
char buf[128];
int lno = 0;
rewind(in);
while (fgets(buf, sizeof(buf), in)) {
int len = strlen(buf);
int i;
u_int8_t data[64];
int nbytes;
lno++;
if (buf[0] != ':') {
fprintf(stderr, "ihex: line %d: invalid start "
"marker\n", lno);
continue;
}
/* Trim trailing whitespace */
while (len && isspace(buf[len - 1]))
len--;
buf[len] = 0;
/* Decode hex digits */
nbytes = (len - 1) / 2;
for (i = 0; i < nbytes; i++) {
char d[] = {buf[i * 2 + 1], buf[i * 2 + 2], 0};
data[i] = strtoul(d, NULL, 16);
}
/* Handle the line */
if (feed_line(in, data, nbytes, cb) < 0) {
fprintf(stderr, "ihex: error on line %d\n", lno);
return -1;
}
}
return 0;
}

154
main.c
View File

@ -26,8 +26,9 @@
#include "dis.h"
#include "fet.h"
#include "binfile.h"
void hexdump(int addr, const char *data, int len)
void hexdump(int addr, const u_int8_t *data, int len)
{
int offset = 0;
@ -145,7 +146,7 @@ static int cmd_md(char **arg)
}
while (length) {
char buf[128];
u_int8_t buf[128];
int blen = length > sizeof(buf) ? sizeof(buf) : length;
if (fet_read_mem(offset, buf, blen) < 0)
@ -202,7 +203,7 @@ static int cmd_dis(char **arg)
char *len_text = get_arg(arg);
unsigned int offset = 0;
unsigned int length = 0;
char buf[128];
u_int8_t buf[128];
if (!off_text) {
fprintf(stderr, "md: offset must be specified\n");
@ -235,7 +236,7 @@ static int cmd_reset(char **arg)
static int cmd_regs(char **arg)
{
u_int16_t regs[FET_NUM_REGS];
char code[16];
u_int8_t code[16];
if (fet_get_context(regs) < 0)
return -1;
@ -325,107 +326,76 @@ static int cmd_step(char **arg)
return cmd_regs(NULL);
}
static int hexval(const char *text, int len)
{
int value = 0;
/************************************************************************
* Flash image programming state machine.
*/
while (len && *text) {
value <<= 4;
if (*text >= 'A' && *text <= 'F')
value += *text - 'A' + 10;
else if (*text >= 'a' && *text <= 'f')
value += *text - 'a' + 10;
else if (isdigit(*text))
value += *text - '0';
text++;
len--;
}
return value;
}
static char prog_buf[128];
static u_int8_t prog_buf[128];
static u_int16_t prog_addr;
static int prog_len;
static int prog_have_erased;
static void prog_init(void)
{
prog_len = 0;
prog_have_erased = 0;
}
static int prog_flush(void)
{
while (prog_len) {
int wlen = prog_len;
if (!prog_len)
return 0;
/* Writing across this address seems to cause a hang */
if (prog_addr < 0x999a && wlen + prog_addr > 0x999a)
wlen = 0x999a - prog_addr;
printf("Writing %3d bytes to %04x...\n", wlen, prog_addr);
if (!prog_have_erased) {
printf("Erasing...\n");
if (fet_erase(FET_ERASE_ALL, 0x1000, 0x100) < 0)
return -1;
prog_have_erased = 1;
}
printf("Writing %3d bytes to %04x...\n", wlen, prog_addr);
if (fet_write_mem(prog_addr, prog_buf, wlen) < 0)
return -1;
memmove(prog_buf, prog_buf + wlen, prog_len - wlen);
prog_len -= wlen;
prog_addr += wlen;
}
return 0;
}
static int prog_hex(int lno, const char *hex)
static int prog_feed(u_int16_t addr, const u_int8_t *data, int len)
{
int len = strlen(hex);
int count, address, type, cksum = 0;
int i;
if (*hex != ':')
return 0;
hex++;
len--;
while (len && isspace(hex[len - 1]))
len--;
if (len < 10)
return 0;
count = hexval(hex, 2);
address = hexval(hex + 2, 4);
type = hexval(hex + 6, 2);
if (type)
return 0;
for (i = 0; i + 2 < len; i += 2)
cksum = (cksum + hexval(hex + i, 2))
& 0xff;
cksum = ~(cksum - 1) & 0xff;
if (count * 2 + 10 != len) {
fprintf(stderr, "warning: length mismatch at line %d\n", lno);
count = (len - 10) / 2;
}
if (cksum != hexval(hex + len - 2, 2))
fprintf(stderr, "warning: invalid checksum at line %d\n", lno);
for (i = 0; i < count; i++) {
int offset;
offset = address + i - prog_addr;
if (offset < 0 || offset >= sizeof(prog_buf))
if (prog_flush() < 0)
/* Flush if this section is discontiguous */
if (prog_len && prog_addr + prog_len != addr && prog_flush() < 0)
return -1;
if (!prog_len)
prog_addr = address + i;
prog_addr = addr;
offset = address + i - prog_addr;
prog_buf[offset] = hexval(hex + 8 + i * 2, 2);
if (offset + 1 > prog_len)
prog_len = offset + 1;
/* Add the buffer in piece by piece, flushing when it gets
* full.
*/
while (len) {
int count = sizeof(prog_buf) - prog_len;
if (count > len)
count = len;
if (!count) {
if (prog_flush() < 0)
return -1;
} else {
memcpy(prog_buf + prog_len, data, count);
prog_len += count;
data += count;
len -= count;
}
}
return 0;
@ -434,35 +404,31 @@ static int prog_hex(int lno, const char *hex)
static int cmd_prog(char **arg)
{
FILE *in = fopen(*arg, "r");
char text[256];
int lno = 1;
int result = 0;
if (!in) {
fprintf(stderr, "prog: %s: %s\n", *arg, strerror(errno));
return -1;
}
printf("Erasing...\n");
if (fet_erase(FET_ERASE_ALL, 0x1000, 0x100) < 0) {
if (fet_reset(FET_RESET_ALL | FET_RESET_HALT) < 0) {
fclose(in);
return -1;
}
if (fet_reset(FET_RESET_ALL | FET_RESET_HALT) < 0)
return -1;
prog_init();
if (elf32_check(in))
result = elf32_extract(in, prog_feed);
else if (ihex_check(in))
result = ihex_extract(in, prog_feed);
else
fprintf(stderr, "%s: unknown file type\n", *arg);
if (!result)
result = prog_flush();
prog_len = 0;
while (fgets(text, sizeof(text), in))
if (prog_hex(lno++, text) < 0) {
fclose(in);
return -1;
}
fclose(in);
if (prog_flush() < 0)
return -1;
return fet_reset(FET_RESET_ALL | FET_RESET_HALT);
return result;
}
static const struct command all_commands[] = {

View File

@ -22,7 +22,7 @@
#include "fet.h"
void hexdump(int addr, const char *data, int len);
extern void hexdump(int addr, const u_int8_t *data, int len);
/*********************************************************************
* USB transport
@ -87,10 +87,10 @@ static int usbtr_open_device(struct usb_device *dev)
return -1;
}
static int usbtr_send(const char *data, int len)
static int usbtr_send(const u_int8_t *data, int len)
{
while (len) {
char pbuf[256];
u_int8_t pbuf[256];
int plen = len > 255 ? 255 : len;
int txlen = plen + 1;
@ -112,7 +112,7 @@ static int usbtr_send(const char *data, int len)
hexdump(0, pbuf, txlen);
#endif
if (usb_bulk_write(usbtr_handle, USB_FET_OUT_EP,
pbuf, txlen, 10000) < 0) {
(const char *)pbuf, txlen, 10000) < 0) {
perror("usbtr_send");
return -1;
}
@ -124,7 +124,7 @@ static int usbtr_send(const char *data, int len)
return 0;
}
static char usbtr_buf[64];
static u_int8_t usbtr_buf[64];
static int usbtr_len;
static int usbtr_offset;
@ -136,13 +136,14 @@ static void usbtr_flush(void)
buf, sizeof(buf), 100) >= 0);
}
static int usbtr_recv(char *databuf, int max_len)
static int usbtr_recv(u_int8_t *databuf, int max_len)
{
int rlen;
if (usbtr_offset >= usbtr_len) {
if (usb_bulk_read(usbtr_handle, USB_FET_IN_EP,
usbtr_buf, sizeof(usbtr_buf), 10000) < 0) {
(char *)usbtr_buf, sizeof(usbtr_buf),
10000) < 0) {
perror("usbtr_recv");
return -1;
}

6
uif.c
View File

@ -28,11 +28,11 @@
#include "fet.h"
void hexdump(int addr, const char *data, int len);
extern void hexdump(int addr, const u_int8_t *data, int len);
static int serial_fd = -1;
static int serial_send(const char *data, int len)
static int serial_send(const u_int8_t *data, int len)
{
int result;
@ -60,7 +60,7 @@ static int serial_send(const char *data, int len)
return 0;
}
static int serial_recv(char *data, int max_len)
static int serial_recv(u_int8_t *data, int max_len)
{
int len;