Added ELF support, made all buffers u_int8_t.
This commit is contained in:
parent
34e1d2d7a1
commit
1d3b4f3f81
2
Makefile
2
Makefile
|
@ -25,7 +25,7 @@ clean:
|
||||||
|
|
||||||
.SUFFIXES: .c .o
|
.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
|
$(CC) $(CFLAGS) -o $@ $^ -lusb
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
|
|
|
@ -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
|
|
@ -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
28
fet.c
|
@ -105,7 +105,7 @@ static void init_codes(void)
|
||||||
* needs to be stored in little-endian format at the end of the payload.
|
* 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;
|
int i;
|
||||||
u_int16_t cksum = 0xffff;
|
u_int16_t cksum = 0xffff;
|
||||||
|
@ -140,13 +140,13 @@ static u_int16_t calc_checksum(const char *data, int len)
|
||||||
*
|
*
|
||||||
* No checksums are included.
|
* 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;
|
int offset = 0;
|
||||||
|
|
||||||
assert (fet_transport != NULL);
|
assert (fet_transport != NULL);
|
||||||
while (len) {
|
while (len) {
|
||||||
char pbuf[63];
|
u_int8_t pbuf[63];
|
||||||
int plen = len > 59 ? 59 : len;
|
int plen = len > 59 ? 59 : len;
|
||||||
|
|
||||||
pbuf[0] = 0x83;
|
pbuf[0] = 0x83;
|
||||||
|
@ -165,7 +165,7 @@ static int send_rf2500_data(const char *data, int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char fet_buf[65538];
|
static u_int8_t fet_buf[65538];
|
||||||
static int fet_len;
|
static int fet_len;
|
||||||
|
|
||||||
#define MAX_PARAMS 16
|
#define MAX_PARAMS 16
|
||||||
|
@ -178,7 +178,7 @@ static struct {
|
||||||
int argc;
|
int argc;
|
||||||
u_int32_t argv[MAX_PARAMS];
|
u_int32_t argv[MAX_PARAMS];
|
||||||
|
|
||||||
char *data;
|
u_int8_t *data;
|
||||||
int datalen;
|
int datalen;
|
||||||
} fet_reply;
|
} fet_reply;
|
||||||
|
|
||||||
|
@ -372,12 +372,12 @@ static int recv_packet(void)
|
||||||
|
|
||||||
static int send_command(int command_code,
|
static int send_command(int command_code,
|
||||||
const u_int32_t *params, int nparams,
|
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;
|
int len = 0;
|
||||||
|
|
||||||
char buf[512];
|
u_int8_t buf[512];
|
||||||
u_int16_t cksum;
|
u_int16_t cksum;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j;
|
int j;
|
||||||
|
@ -449,7 +449,7 @@ static int send_command(int command_code,
|
||||||
return fet_transport->send(buf, i);
|
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, ...)
|
int nparams, ...)
|
||||||
{
|
{
|
||||||
u_int32_t params[MAX_PARAMS];
|
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)
|
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.
|
* This is RF2500-specific.
|
||||||
*/
|
*/
|
||||||
if (fet_is_rf2500) {
|
if (fet_is_rf2500) {
|
||||||
static const char data[] = {
|
static const u_int8_t data[] = {
|
||||||
0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10,
|
0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10,
|
||||||
0xff, 0x10, 0x40, 0x00, 0x00, 0x02, 0xff, 0x05,
|
0xff, 0x10, 0x40, 0x00, 0x00, 0x02, 0xff, 0x05,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
|
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)
|
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 i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -729,7 +729,7 @@ int fet_set_context(u_int16_t *regs)
|
||||||
return 0;
|
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) {
|
while (count) {
|
||||||
int plen = count > 128 ? 128 : 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;
|
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) {
|
while (count) {
|
||||||
int plen = count > 128 ? 128 : count;
|
int plen = count > 128 ? 128 : count;
|
||||||
|
|
8
fet.h
8
fet.h
|
@ -39,8 +39,8 @@ int rf2500_open(void);
|
||||||
* high-level functions.
|
* high-level functions.
|
||||||
*/
|
*/
|
||||||
struct fet_transport {
|
struct fet_transport {
|
||||||
int (*send)(const char *data, int len);
|
int (*send)(const u_int8_t *data, int len);
|
||||||
int (*recv)(char *data, int max_len);
|
int (*recv)(u_int8_t *data, int max_len);
|
||||||
void (*close)(void);
|
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
|
/* Read and write memory. fet_write_mem can be used to reflash the
|
||||||
* device, but only after an erase.
|
* device, but only after an erase.
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
/* Fetch the device status. If the device is currently running, then
|
/* Fetch the device status. If the device is currently running, then
|
||||||
* the FET_POLL_RUNNING flag will be set. FET_POLL_BREAKPOINT is set
|
* the FET_POLL_RUNNING flag will be set. FET_POLL_BREAKPOINT is set
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
178
main.c
178
main.c
|
@ -26,8 +26,9 @@
|
||||||
|
|
||||||
#include "dis.h"
|
#include "dis.h"
|
||||||
#include "fet.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;
|
int offset = 0;
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ static int cmd_md(char **arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (length) {
|
while (length) {
|
||||||
char buf[128];
|
u_int8_t buf[128];
|
||||||
int blen = length > sizeof(buf) ? sizeof(buf) : length;
|
int blen = length > sizeof(buf) ? sizeof(buf) : length;
|
||||||
|
|
||||||
if (fet_read_mem(offset, buf, blen) < 0)
|
if (fet_read_mem(offset, buf, blen) < 0)
|
||||||
|
@ -202,7 +203,7 @@ static int cmd_dis(char **arg)
|
||||||
char *len_text = get_arg(arg);
|
char *len_text = get_arg(arg);
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
unsigned int length = 0;
|
unsigned int length = 0;
|
||||||
char buf[128];
|
u_int8_t buf[128];
|
||||||
|
|
||||||
if (!off_text) {
|
if (!off_text) {
|
||||||
fprintf(stderr, "md: offset must be specified\n");
|
fprintf(stderr, "md: offset must be specified\n");
|
||||||
|
@ -235,7 +236,7 @@ static int cmd_reset(char **arg)
|
||||||
static int cmd_regs(char **arg)
|
static int cmd_regs(char **arg)
|
||||||
{
|
{
|
||||||
u_int16_t regs[FET_NUM_REGS];
|
u_int16_t regs[FET_NUM_REGS];
|
||||||
char code[16];
|
u_int8_t code[16];
|
||||||
|
|
||||||
if (fet_get_context(regs) < 0)
|
if (fet_get_context(regs) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -325,107 +326,76 @@ static int cmd_step(char **arg)
|
||||||
return cmd_regs(NULL);
|
return cmd_regs(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hexval(const char *text, int len)
|
/************************************************************************
|
||||||
{
|
* Flash image programming state machine.
|
||||||
int value = 0;
|
*/
|
||||||
|
|
||||||
while (len && *text) {
|
static u_int8_t prog_buf[128];
|
||||||
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_int16_t prog_addr;
|
static u_int16_t prog_addr;
|
||||||
static int prog_len;
|
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)
|
static int prog_flush(void)
|
||||||
{
|
{
|
||||||
int wlen = prog_len;
|
while (prog_len) {
|
||||||
|
int wlen = prog_len;
|
||||||
|
|
||||||
if (!prog_len)
|
/* Writing across this address seems to cause a hang */
|
||||||
return 0;
|
if (prog_addr < 0x999a && wlen + prog_addr > 0x999a)
|
||||||
|
wlen = 0x999a - prog_addr;
|
||||||
|
|
||||||
/* Writing across this address seems to cause a hang */
|
if (!prog_have_erased) {
|
||||||
if (prog_addr < 0x999a && wlen + prog_addr > 0x999a)
|
printf("Erasing...\n");
|
||||||
wlen = 0x999a - prog_addr;
|
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);
|
printf("Writing %3d bytes to %04x...\n", wlen, prog_addr);
|
||||||
|
if (fet_write_mem(prog_addr, prog_buf, wlen) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (fet_write_mem(prog_addr, prog_buf, wlen) < 0)
|
memmove(prog_buf, prog_buf + wlen, prog_len - wlen);
|
||||||
return -1;
|
prog_len -= wlen;
|
||||||
|
prog_addr += wlen;
|
||||||
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)
|
|
||||||
{
|
|
||||||
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))
|
return 0;
|
||||||
fprintf(stderr, "warning: invalid checksum at line %d\n", lno);
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
static int prog_feed(u_int16_t addr, const u_int8_t *data, int len)
|
||||||
int offset;
|
{
|
||||||
|
/* Flush if this section is discontiguous */
|
||||||
|
if (prog_len && prog_addr + prog_len != addr && prog_flush() < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
offset = address + i - prog_addr;
|
if (!prog_len)
|
||||||
if (offset < 0 || offset >= sizeof(prog_buf))
|
prog_addr = addr;
|
||||||
|
|
||||||
|
/* 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)
|
if (prog_flush() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
} else {
|
||||||
if (!prog_len)
|
memcpy(prog_buf + prog_len, data, count);
|
||||||
prog_addr = address + i;
|
prog_len += count;
|
||||||
|
data += count;
|
||||||
offset = address + i - prog_addr;
|
len -= count;
|
||||||
prog_buf[offset] = hexval(hex + 8 + i * 2, 2);
|
}
|
||||||
if (offset + 1 > prog_len)
|
|
||||||
prog_len = offset + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -434,35 +404,31 @@ static int prog_hex(int lno, const char *hex)
|
||||||
static int cmd_prog(char **arg)
|
static int cmd_prog(char **arg)
|
||||||
{
|
{
|
||||||
FILE *in = fopen(*arg, "r");
|
FILE *in = fopen(*arg, "r");
|
||||||
char text[256];
|
int result = 0;
|
||||||
int lno = 1;
|
|
||||||
|
|
||||||
if (!in) {
|
if (!in) {
|
||||||
fprintf(stderr, "prog: %s: %s\n", *arg, strerror(errno));
|
fprintf(stderr, "prog: %s: %s\n", *arg, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Erasing...\n");
|
if (fet_reset(FET_RESET_ALL | FET_RESET_HALT) < 0) {
|
||||||
if (fet_erase(FET_ERASE_ALL, 0x1000, 0x100) < 0) {
|
|
||||||
fclose(in);
|
fclose(in);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fet_reset(FET_RESET_ALL | FET_RESET_HALT) < 0)
|
prog_init();
|
||||||
return -1;
|
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);
|
fclose(in);
|
||||||
|
return result;
|
||||||
if (prog_flush() < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return fet_reset(FET_RESET_ALL | FET_RESET_HALT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct command all_commands[] = {
|
static const struct command all_commands[] = {
|
||||||
|
|
15
rf2500.c
15
rf2500.c
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "fet.h"
|
#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
|
* USB transport
|
||||||
|
@ -87,10 +87,10 @@ static int usbtr_open_device(struct usb_device *dev)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usbtr_send(const char *data, int len)
|
static int usbtr_send(const u_int8_t *data, int len)
|
||||||
{
|
{
|
||||||
while (len) {
|
while (len) {
|
||||||
char pbuf[256];
|
u_int8_t pbuf[256];
|
||||||
int plen = len > 255 ? 255 : len;
|
int plen = len > 255 ? 255 : len;
|
||||||
int txlen = plen + 1;
|
int txlen = plen + 1;
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ static int usbtr_send(const char *data, int len)
|
||||||
hexdump(0, pbuf, txlen);
|
hexdump(0, pbuf, txlen);
|
||||||
#endif
|
#endif
|
||||||
if (usb_bulk_write(usbtr_handle, USB_FET_OUT_EP,
|
if (usb_bulk_write(usbtr_handle, USB_FET_OUT_EP,
|
||||||
pbuf, txlen, 10000) < 0) {
|
(const char *)pbuf, txlen, 10000) < 0) {
|
||||||
perror("usbtr_send");
|
perror("usbtr_send");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ static int usbtr_send(const char *data, int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char usbtr_buf[64];
|
static u_int8_t usbtr_buf[64];
|
||||||
static int usbtr_len;
|
static int usbtr_len;
|
||||||
static int usbtr_offset;
|
static int usbtr_offset;
|
||||||
|
|
||||||
|
@ -136,13 +136,14 @@ static void usbtr_flush(void)
|
||||||
buf, sizeof(buf), 100) >= 0);
|
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;
|
int rlen;
|
||||||
|
|
||||||
if (usbtr_offset >= usbtr_len) {
|
if (usbtr_offset >= usbtr_len) {
|
||||||
if (usb_bulk_read(usbtr_handle, USB_FET_IN_EP,
|
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");
|
perror("usbtr_recv");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
6
uif.c
6
uif.c
|
@ -28,11 +28,11 @@
|
||||||
|
|
||||||
#include "fet.h"
|
#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_fd = -1;
|
||||||
|
|
||||||
static int serial_send(const char *data, int len)
|
static int serial_send(const u_int8_t *data, int len)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ static int serial_send(const char *data, int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_recv(char *data, int max_len)
|
static int serial_recv(u_int8_t *data, int max_len)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue