diff --git a/.gitignore b/.gitignore index ba8f3fc..e4fbe81 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build twiboot mpmboot funkboot +eprom_prog diff --git a/Makefile b/Makefile index 736c749..f9831c2 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -TARGETS=twiboot mpmboot funkboot +TARGETS=twiboot mpmboot funkboot eprom_prog TARGET_DIR=~/bin BUILD_DIR = build -CFLAGS= -pipe -O2 -Wall -Wno-unused-result +CFLAGS= -pipe -O2 -Wall -Wextra -Wno-unused-result CFLAGS+= -MMD -MP -MF $(BUILD_DIR)/$(*D)/$(*F).d LDFLAGS= diff --git a/chipinfo_avr.c b/chipinfo_avr.c index 7efa121..81a668c 100644 --- a/chipinfo_avr.c +++ b/chipinfo_avr.c @@ -46,7 +46,7 @@ static struct chipinfo chips[] = * ************************************************************************* */ const char * chipinfo_get_avr_name(const uint8_t *sig) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(chips); i++) { diff --git a/eprom_prog.c b/eprom_prog.c new file mode 100644 index 0000000..ff56a29 --- /dev/null +++ b/eprom_prog.c @@ -0,0 +1,936 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "multiboot.h" +#include "optarg.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MEMTYPE_EPROM 1 + +#define SERIAL_BAUDRATE B115200 +#define SERIAL_TIMEOUT 1000 +#define SERIAL_TIMEOUT_SYNC 5 + +#define MSGTYPE_SYNC 0x00 /* trigger { MSGTYPE_ERROR_RSP, 1, ERROR_UNKNOWN_COMMAND } */ +#define MSGTYPE_VERSION_REQ 0x01 /* no payload */ +#define MSGTYPE_PAGESIZE_REQ 0x02 /* no payload */ +#define MSGTYPE_CONFIG_REQ 0x03 /* eprom_type(1), pagesize(1), reset_polarity(1) */ +#define MSGTYPE_PROGMODE_REQ 0x04 /* progmode(1) */ +#define MSGTYPE_SETADDRESS_REQ 0x05 /* address(3) msb first */ +#define MSGTYPE_WRITE_REQ 0x06 /* data(0-pagesize) */ +#define MSGTYPE_READ_REQ 0x07 /* length(1) */ + +#define MSGTYPE_ERROR_RSP 0x80 /* error_code(1) */ +#define MSGTYPE_VERSION_RSP 0x81 /* version(?) */ +#define MSGTYPE_PAGESIZE_RSP 0x82 /* pagesize(1) */ +#define MSGTYPE_CONFIG_RSP 0x83 /* no payload */ +#define MSGTYPE_PROGMODE_RSP 0x84 /* no payload */ +#define MSGTYPE_SETADDRESS_RSP 0x85 /* no payload */ +#define MSGTYPE_WRITE_RSP 0x86 /* no payload */ +#define MSGTYPE_READ_RSP 0x87 /* data(0-pagesize) */ + +#define SUCCESS 0x00 +#define ERROR_UNKNOWN_COMMAND 0x01 /* unknown message type */ +#define ERROR_NOT_SUPPORTED 0x02 /* command not supported */ +#define ERROR_INVALID_MODE 0x03 /* invalid progmode */ +#define ERROR_INVALID_PARAMETER 0x04 /* invalid parameter in request */ +#define ERROR_INVALID_ADDRESS 0x05 /* write outside of configured region */ + +#define RESET_POLARITY_LOW 0x00 /* low active reset */ +#define RESET_POLARITY_HIGH 0x01 /* high active reset */ + +#define EPROM_TYPE_2K 0x02 /* 2716 */ +#define EPROM_TYPE_4K 0x04 /* 2732 */ +#define EPROM_TYPE_8K 0x08 /* 2764 */ +#define EPROM_TYPE_16K 0x10 /* 27128 */ +#define EPROM_TYPE_32K 0x20 /* 27256 */ +#define EPROM_TYPE_64K 0x40 /* 27512 */ +#define EPROM_TYPE_128K 0x80 /* 27010 */ + +#define PROGMODE_DISABLED 0x00 /* target running, no write access to RAM */ +#define PROGMODE_ENABLED 0x01 /* target reset, write access to RAM */ + + +struct multiboot_ops eprog_ops; + +struct eprog_privdata +{ + char * device; + struct termios oldtio; + int fd; + + uint8_t version[32]; + uint8_t pagesize_max; + + uint8_t eprom_type; + uint8_t pagesize; + int reset_polarity; + + uint8_t progmode; +}; + +struct eprog_type +{ + const char name[8]; + uint8_t eprom_type; + uint8_t pagesize; +}; + +static struct eprog_type eprom_types[] = +{ + { "2716", EPROM_TYPE_2K, 0xFF }, + { "2732", EPROM_TYPE_4K, 0xFF }, + { "2764", EPROM_TYPE_8K, 0xFF }, + { "2864", EPROM_TYPE_8K, 0x40 }, + { "27128", EPROM_TYPE_16K, 0xFF }, + { "27256", EPROM_TYPE_32K, 0xFF }, + { "27512", EPROM_TYPE_64K, 0xFF }, + { "27010", EPROM_TYPE_128K, 0xFF }, +}; + +static struct option eprog_optargs[] = +{ + { "device", 1, 0, 'd' }, /* [ -d ] */ + { "reset", 1, 0, 'x' }, /* [ -x ] */ + { "type", 1, 0, 't' }, /* [ -t ] */ +}; + +/* ************************************************************************* + * eprog_optarg_cb + * ************************************************************************* */ +static int eprog_optarg_cb(int val, const char *arg, void *privdata) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)privdata; + + switch (val) + { + case 'd': /* device */ + if (p_prog->device != NULL) + { + fprintf(stderr, "invalid device: '%s'\n", arg); + return -1; + } + + p_prog->device = strdup(optarg); + if (p_prog->device == NULL) + { + perror("strdup()"); + return -1; + } + break; + + case 'x': + if (strcasecmp(arg, "high") == 0) + { + p_prog->reset_polarity = RESET_POLARITY_HIGH; + } + else if (strcasecmp(arg, "low") == 0) + { + p_prog->reset_polarity = RESET_POLARITY_LOW; + } + else + { + fprintf(stderr, "invalid reset polarity: '%s'\n", arg); + return -1; + } + break; + + case 't': + { + unsigned int i; + + if (p_prog->eprom_type != 0) + { + fprintf(stderr, "invalid EPROM type: '%s'\n", arg); + return -1; + } + + for (i = 0; i < ARRAY_SIZE(eprom_types); i++) + { + if (strcmp(arg, eprom_types[i].name) == 0) + { + p_prog->eprom_type = eprom_types[i].eprom_type; + p_prog->pagesize = eprom_types[i].pagesize; + } + } + + if (p_prog->eprom_type == 0) + { + fprintf(stderr, "invalid EPROM type: '%s'\n", arg); + return -1; + } + } + break; + + case 'h': + case '?': /* error */ + fprintf(stderr, "Usage: eprom_sim [options]\n" + " -d - selects eprom_sim device\n" + " -x - select 'high' or 'low' active reset\n" + " -t - selects EPROM type (2716 - 27010)\n" + " -r eprom: - reads EPROM to file (.bin | .hex | -)\n" + " -w eprom: - write EPROM from file (.bin | .hex)\n" + " -p <0|1|2> - progress bar mode\n" + "\n" + "Example: eprom_sim -d /dev/ttyUSB0 -t 2764 -r high -w eprom:data.hex\n" + "\n"); + + return -1; + + default: + return 1; + } + + return 0; +} /* eprog_optarg_cb */ + + +/* ************************************************************************* + * eprog_alloc + * ************************************************************************* */ +static struct multiboot * eprog_alloc(void) +{ + struct multiboot * mboot = malloc(sizeof(struct multiboot)); + if (mboot == NULL) + { + return NULL; + } + + memset(mboot, 0x00, sizeof(struct multiboot)); + mboot->ops= &eprog_ops; + + struct eprog_privdata *p_prog = malloc(sizeof(struct eprog_privdata)); + if (p_prog == NULL) + { + free(mboot); + return NULL; + } + + memset(p_prog, 0x00, sizeof(struct eprog_privdata)); + p_prog->device = NULL; + + optarg_register(eprog_optargs, ARRAY_SIZE(eprog_optargs), + eprog_optarg_cb, (void *)p_prog); + + mboot->privdata = p_prog; + return mboot; +} /* eprog_alloc */ + + +/* ************************************************************************* + * eprog_free + * ************************************************************************* */ +static void eprog_free(struct multiboot *mboot) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + + if (p_prog->device != NULL) + { + free(p_prog->device); + } + + free(p_prog); + free(mboot); +} /* eprog_free */ + + +/* ************************************************************************* + * eprog_get_memtype + * ************************************************************************* */ +static int eprog_get_memtype(struct multiboot *mboot, + const char *memname) +{ + /* unused parameter */ + (void)mboot; + + if (strcmp(memname, "eprom") == 0) + { + return MEMTYPE_EPROM; + } + + return -1; +} /* eprog_get_memtype */ + + +/* ************************************************************************* + * eprog_get_memsize + * ************************************************************************* */ +static int eprog_get_memsize(struct multiboot *mboot, + int memtype) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + + if (memtype != MEMTYPE_EPROM) + { + return 0; + } + + return p_prog->eprom_type * 1024; +} /* eprog_get_memsize */ + + +/* ************************************************************************* + * eprog_close_device + * ************************************************************************* */ +static void eprog_close_device(struct eprog_privdata *p_prog) +{ + /* delay close() / tcsetattr() */ + usleep(100000); + + tcsetattr(p_prog->fd, TCSANOW, &p_prog->oldtio); + close(p_prog->fd); +} /* eprog_close_device */ + + +/* ************************************************************************* + * eprog_open_device + * ************************************************************************* */ +static int eprog_open_device(struct eprog_privdata *p_prog) +{ + p_prog->fd = open(p_prog->device, O_RDWR | O_NOCTTY | O_CLOEXEC); + if (p_prog->fd < 0) + { + perror("open()"); + return -1; + } + + if (tcgetattr(p_prog->fd, &p_prog->oldtio) < 0) + { + perror("tcgetattr(oldtio)"); + close(p_prog->fd); + return -1; + } + + struct termios newtio; + memset(&newtio, 0, sizeof(newtio)); + + newtio.c_iflag |= IGNBRK; + newtio.c_cflag |= SERIAL_BAUDRATE | CS8 | CLOCAL | CREAD; + + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + + int err = tcsetattr(p_prog->fd, TCSANOW, &newtio); + if (err < 0) + { + perror("tcsetattr(newtio)"); + close(p_prog->fd); + return -1; + } + + return 0; +} /* eprog_open_device */ + + +/* ************************************************************************* + * eprog_serial_read + * ************************************************************************* */ +static int eprog_serial_read(int fd, void * data, int size, unsigned int timeout_ms) +{ + int pos = 0; + + while (1) + { + fd_set fdset; + struct timeval timeout; + struct timeval * p_timeout = NULL; + + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + + if (timeout_ms != 0) + { + p_timeout = &timeout; + + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + } + + int ret = select(fd +1, &fdset, NULL, NULL, p_timeout); + if (ret == -1) + { + perror("select"); + return -1; + } + else if (ret == 0) + { + break; + } + else if (FD_ISSET(fd, &fdset)) + { + int len = read(fd, data + pos, size - pos); + if (len < 0) + { + return -1; + } + else + { + pos += len; + if (pos == size) + { + break; + } + } + } + } + + return pos; +} /* eprog_serial_read */ + + +/* ************************************************************************* + * eprog_recv + * ************************************************************************* */ +static int eprog_recv(int fd, uint8_t msgtype, uint8_t * data, uint8_t length) +{ + uint8_t header[2]; + uint8_t dummy[64]; + + int ret = eprog_serial_read(fd, header, sizeof(header), SERIAL_TIMEOUT); + if (ret < (int)sizeof(header)) + { + fprintf(stderr, "short read from device (header)\n"); + return -1; + } + + uint8_t pos = 0; + uint8_t msgsize = header[1]; + + while (msgsize > 0) + { + if ((data != NULL) && (pos < length)) + { + uint8_t readsize = MIN(msgsize, length - pos); + + ret = eprog_serial_read(fd, &data[pos], readsize, SERIAL_TIMEOUT); + if (ret <= 0) + { + fprintf(stderr, "short read from device (payload)\n"); + return -1; + } + + pos += ret; + } + else + { + uint8_t readsize = MIN(msgsize, sizeof(dummy)); + + ret = eprog_serial_read(fd, &dummy, readsize, SERIAL_TIMEOUT); + if (ret <= 0) + { + fprintf(stderr, "short read from device (dummy)\n"); + return -1; + } + } + + msgsize -= ret; + } + + if (header[0] != msgtype) + { + if ((header[0] == MSGTYPE_ERROR_RSP) && (header[1] == 1)) + { + uint8_t error_code = (data != NULL) ? data[0] : dummy[0]; + + fprintf(stderr, "expected msgtype 0x%x received ERROR_RSP error_code 0x%x\n", + msgtype, error_code); + } + else + { + fprintf(stderr, "wrong msgtype received (0x%x != 0x%x)\n", + header[0], msgtype); + } + + return -1; + } + + return pos; +} /* eprog_recv */ + + +/* ************************************************************************* + * eprog_sync + * ************************************************************************* */ +static int eprog_sync(struct eprog_privdata *p_prog) +{ + int sync_count = 255; + + while (sync_count > 0) + { + /* send only MSGTYPE, no request length! */ + uint8_t request[] = { MSGTYPE_SYNC }; + uint8_t response[3]; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_serial_read(p_prog->fd, response, sizeof(response), SERIAL_TIMEOUT_SYNC); + if ((ret == sizeof(response)) && + (response[0] == MSGTYPE_ERROR_RSP) && + (response[1] == 1) && + (response[2] == ERROR_UNKNOWN_COMMAND) + ) + { + return 0; + } + + sync_count--; + } + + return -1; +} /* eprog_sync */ + + +/* ************************************************************************* + * eprog_get_version + * ************************************************************************* */ +static int eprog_get_version(struct eprog_privdata *p_prog, + uint8_t *version, uint8_t length) +{ + uint8_t request[] = { MSGTYPE_VERSION_REQ, 0 }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_VERSION_RSP, version, length); + if (ret <= 0) + { + return -1; + } + + if (ret < length) + { + version[ret] = '\0'; + } + else + { + version[length -1] = '\0'; + } + + return 0; +} /* eprog_get_version */ + + +/* ************************************************************************* + * eprog_get_pagesize + * ************************************************************************* */ +static int eprog_get_pagesize(struct eprog_privdata *p_prog, + uint8_t *pagesize) +{ + uint8_t request[] = { MSGTYPE_PAGESIZE_REQ, 0 }; + uint8_t response[1]; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_PAGESIZE_RSP, response, sizeof(response)); + if (ret != sizeof(response)) + { + return -1; + } + + *pagesize = response[0]; + + return 0; +} /* eprog_get_pagesize */ + + +/* ************************************************************************* + * eprog_set_config + * ************************************************************************* */ +static int eprog_set_config(struct eprog_privdata *p_prog, + uint8_t eprom_type, + uint8_t pagesize, + uint8_t reset_polarity) +{ + uint8_t request[] = { MSGTYPE_CONFIG_REQ, 3, eprom_type, pagesize, reset_polarity }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_CONFIG_RSP, NULL, 0); + if (ret < 0) + { + return ret; + } + + return 0; +} /* eprog_set_config */ + + +/* ************************************************************************* + * eprog_set_progmode + * ************************************************************************* */ +static int eprog_set_progmode(struct eprog_privdata *p_prog, + uint8_t progmode) +{ + uint8_t request[] = { MSGTYPE_PROGMODE_REQ, 1, progmode }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_PROGMODE_RSP, NULL, 0); + if (ret < 0) + { + return ret; + } + + return 0; +} /* eprog_set_progmode */ + + +/* ************************************************************************* + * eprog_set_address + * ************************************************************************* */ +static int eprog_set_address(struct eprog_privdata *p_prog, + uint32_t address) +{ + uint8_t request[] = { MSGTYPE_SETADDRESS_REQ, 3, + (address >> 16) & 0xFF, + (address >> 8) & 0xFF, + (address >> 0) & 0xFF }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_SETADDRESS_RSP, NULL, 0); + if (ret < 0) + { + return ret; + } + + return 0; +} /* eprog_set_address */ + + +/* ************************************************************************* + * eprog_read_data + * ************************************************************************* */ +static int eprog_read_data(struct eprog_privdata *p_prog, + uint8_t * data, + uint8_t length) +{ + uint8_t request[] = { MSGTYPE_READ_REQ, 1, length }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_READ_RSP, data, length); + if (ret < 0) + { + return ret; + } + + return 0; +} /* eprog_read_data */ + + +/* ************************************************************************* + * eprog_write_data + * ************************************************************************* */ +static int eprog_write_data(struct eprog_privdata *p_prog, + const uint8_t * data, + uint8_t length) +{ + uint8_t request[] = { MSGTYPE_WRITE_REQ, length }; + + int ret = write(p_prog->fd, request, sizeof(request)); + if (ret <= 0) + { + return ret; + } + + ret = write(p_prog->fd, data, length); + if (ret <= 0) + { + return ret; + } + + ret = eprog_recv(p_prog->fd, MSGTYPE_WRITE_RSP, NULL, 0); + if (ret < 0) + { + return ret; + } + + return 0; +} /* eprog_write_data */ + + +/* ************************************************************************* + * eprog_close + * ************************************************************************* */ +static int eprog_close(struct multiboot *mboot) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + + if (p_prog->progmode == PROGMODE_ENABLED) + { + eprog_set_progmode(p_prog, PROGMODE_DISABLED); + } + + eprog_close_device(p_prog); + + return 0; +} /* eprog_close */ + + +/* ************************************************************************* + * eprog_open + * ************************************************************************* */ +static int eprog_open(struct multiboot *mboot) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + + if (p_prog->device == NULL) + { + fprintf(stderr, "abort: no device given\n"); + return -1; + } + + if (p_prog->eprom_type == 0) + { + fprintf(stderr, "abort: no EPROM type given\n"); + return -1; + } + + if (eprog_open_device(p_prog) < 0) + { + return -1; + } + + if (eprog_sync(p_prog) < 0) + { + fprintf(stderr, "failed to sync\n"); + eprog_close_device(p_prog); + return -1; + } + + if (eprog_get_version(p_prog, p_prog->version, sizeof(p_prog->version)) < 0) + { + fprintf(stderr, "failed to get version\n"); + eprog_close_device(p_prog); + return -1; + } + + if ((eprog_get_pagesize(p_prog, &p_prog->pagesize_max) < 0) || + (p_prog->pagesize_max == 0) + ) + { + fprintf(stderr, "failed to get pagesize\n"); + eprog_close_device(p_prog); + return -1; + } + + p_prog->pagesize = MIN(p_prog->pagesize, p_prog->pagesize_max); + if (eprog_set_config(p_prog, p_prog->eprom_type, p_prog->pagesize, p_prog->reset_polarity) < 0) + { + fprintf(stderr, "failed to set configuration\n"); + eprog_close_device(p_prog); + return -1; + } + + if (eprog_set_progmode(p_prog, PROGMODE_ENABLED) < 0) + { + fprintf(stderr, "failed to enter progmode\n"); + eprog_close_device(p_prog); + return -1; + } + + p_prog->progmode = PROGMODE_ENABLED; + + printf("device : %-16s\n", + p_prog->device); + + printf("version : %-32s\n", + p_prog->version); + + printf("reset polarity : %-4s\n", + p_prog->reset_polarity ? "high" : "low"); + + printf("EPROM size : 0x%05x (%d)\n", + p_prog->eprom_type * 1024, + p_prog->eprom_type * 1024); + + return 0; +} /* eprog_open */ + + +/* ************************************************************************* + * eprog_read + * ************************************************************************* */ +static int eprog_read(struct multiboot *mboot, + struct databuf *dbuf, int memtype) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + char *progress_msg = "reading EPROM"; + + /* unused parameter */ + (void)memtype; + + uint32_t pos = 0; + uint32_t size = p_prog->eprom_type * 1024; + + if (eprog_set_address(p_prog, pos) < 0) + { + fprintf(stderr, "failed to set address\n"); + return -1; + } + + while (pos < size) + { + mboot->progress_cb(progress_msg, pos, size); + + uint8_t len = MIN(p_prog->pagesize_max, size - pos); + if (eprog_read_data(p_prog, dbuf->data + pos, len)) + { + mboot->progress_cb(progress_msg, -1, -1); + return -1; + } + + pos += len; + } + + dbuf->length = pos; + + mboot->progress_cb(progress_msg, pos, size); + return 0; +} /* eprog_read */ + + +/* ************************************************************************* + * eprog_write + * ************************************************************************* */ +static int eprog_write(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + char *progress_msg = "writing EPROM"; + + /* unused parameter */ + (void)memtype; + + uint32_t pos = 0; + + if (eprog_set_address(p_prog, pos) < 0) + { + fprintf(stderr, "failed to set address\n"); + return -1; + } + + while (pos < dbuf->length) + { + mboot->progress_cb(progress_msg, pos, dbuf->length); + + uint8_t len = MIN(p_prog->pagesize, dbuf->length - pos); + if (eprog_write_data(p_prog, dbuf->data + pos, len)) + { + mboot->progress_cb(progress_msg, -1, -1); + return -1; + } + + pos += len; + } + + mboot->progress_cb(progress_msg, pos, dbuf->length); + + return 0; +} /* eprog_write */ + + +/* ************************************************************************* + * eprog_verify + * ************************************************************************* */ +static int eprog_verify(struct multiboot *mboot, + struct databuf *dbuf, int memtype) +{ + struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata; + char *progress_msg = "verifing EPROM"; + + /* unused parameter */ + (void)memtype; + + uint32_t pos = 0; + uint8_t comp[256]; + + if (eprog_set_address(p_prog, pos) < 0) + { + fprintf(stderr, "failed to set address\n"); + return -1; + } + + while (pos < dbuf->length) + { + mboot->progress_cb(progress_msg, pos, dbuf->length); + + uint8_t len = MIN(p_prog->pagesize, dbuf->length - pos); + if (eprog_read_data(p_prog, comp, len)) + { + mboot->progress_cb(progress_msg, -1, -1); + return -1; + } + + if (memcmp(comp, dbuf->data + pos, len) != 0x00) + { + mboot->progress_cb(progress_msg, -1, -1); + fprintf(stderr, "verify failed at pos 0x%04x!!\n", pos); + return -1; + } + + pos += len; + } + + dbuf->length = pos; + + mboot->progress_cb(progress_msg, pos, dbuf->length); + return 0; +} /* eprog_verify */ + + +struct multiboot_ops eprog_ops = +{ + .exec_name = "eprom_prog", + .alloc = eprog_alloc, + .free = eprog_free, + .get_memtype = eprog_get_memtype, + .get_memsize = eprog_get_memsize, + + .open = eprog_open, + .close = eprog_close, + .read = eprog_read, + .write = eprog_write, + .verify = eprog_verify, +}; diff --git a/filedata.c b/filedata.c index cab0717..a8db4ac 100644 --- a/filedata.c +++ b/filedata.c @@ -64,7 +64,8 @@ void dbuf_free(struct databuf *dbuf) * ************************************************************************* */ static void dbuf_dump(struct databuf *dbuf) { - int pos = 0, oldskip = 0; + uint32_t pos = 0; + int oldskip = 0; while (pos < dbuf->length) { @@ -372,6 +373,9 @@ static int hexfile_putrecord(FILE *stream, struct ihex_record *record) * ************************************************************************* */ static int hexfile_getsize(const char *filename, uint32_t *size) { + /* unused parameter */ + (void)filename; + *size = 0x10000; return 0; } /* hexfile_getsize */ @@ -432,9 +436,9 @@ static int hexfile_write(const char *filename, struct databuf *dbuf) return -1; } - int i; - int addr_min = dbuf->length; - int addr_max = 0; + uint32_t i; + uint32_t addr_min = dbuf->length; + uint32_t addr_max = 0; for (i = 0; i < dbuf->length; i++) { if (dbuf->data[i] == 0xFF) diff --git a/funk.c b/funk.c index 1c97741..5bed168 100644 --- a/funk.c +++ b/funk.c @@ -260,6 +260,9 @@ static void funk_free(struct multiboot *mboot) static int funk_get_memtype(struct multiboot *mboot, const char *memname) { + /* unused parameter */ + (void)mboot; + if (strcmp(memname, "flash") == 0) { return MEMTYPE_FLASH; @@ -1066,14 +1069,14 @@ static int funk_read(struct multiboot *mboot, struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "reading flash" : "reading eeprom"; - int pos = 0; - int size = (memtype == MEMTYPE_FLASH) ? funk->flashsize : funk->eepromsize; + uint16_t pos = 0; + uint16_t size = (memtype == MEMTYPE_FLASH) ? funk->flashsize : funk->eepromsize; while (pos < size) { mboot->progress_cb(progress_msg, pos, size); - int len = MIN(READ_BLOCK_SIZE, size - pos); + uint16_t len = MIN(READ_BLOCK_SIZE, size - pos); if (funk_read_memory(funk, dbuf->data + pos, len, memtype, pos)) { mboot->progress_cb(progress_msg, -1, -1); @@ -1100,12 +1103,12 @@ static int funk_write(struct multiboot *mboot, struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; - int pos = 0; + uint16_t pos = 0; while (pos < dbuf->length) { mboot->progress_cb(progress_msg, pos, dbuf->length); - int len = (memtype == MEMTYPE_FLASH) ? funk->flashpage : WRITE_BLOCK_SIZE; + uint16_t len = (memtype == MEMTYPE_FLASH) ? funk->flashpage : WRITE_BLOCK_SIZE; len = MIN(len, dbuf->length - pos); @@ -1133,14 +1136,14 @@ static int funk_verify(struct multiboot *mboot, struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; - int pos = 0; + uint16_t pos = 0; uint8_t comp[READ_BLOCK_SIZE]; while (pos < dbuf->length) { mboot->progress_cb(progress_msg, pos, dbuf->length); - int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); + uint16_t len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); if (funk_read_memory(funk, comp, len, memtype, pos)) { mboot->progress_cb(progress_msg, -1, -1); @@ -1166,6 +1169,7 @@ static int funk_verify(struct multiboot *mboot, struct multiboot_ops funk_ops = { + .exec_name = "funkboot", .alloc = funk_alloc, .free = funk_free, .get_memtype = funk_get_memtype, diff --git a/mpm.c b/mpm.c index 6da88dc..6408134 100644 --- a/mpm.c +++ b/mpm.c @@ -46,11 +46,11 @@ struct mpm_privdata int fd; int connected; - int address; + uint8_t address; - int flashsize; - int flashpage; - int eepromsize; + uint16_t flashsize; + uint8_t flashpage; + uint16_t eepromsize; struct termios oldtio; }; @@ -178,6 +178,9 @@ static void mpm_free(struct multiboot *mboot) static int mpm_get_memtype(struct multiboot *mboot, const char *memname) { + /* unused parameter */ + (void)mboot; + if (strcmp(memname, "flash") == 0) { return MEMTYPE_FLASH; @@ -221,7 +224,7 @@ static int mpm_get_memsize(struct multiboot *mboot, int memtype) * mpm_send * ************************************************************************* */ static int mpm_send(struct mpm_privdata *mpm, uint8_t command, - uint8_t *data, int length) + uint8_t *data, uint16_t length) { struct termios tio; @@ -283,9 +286,9 @@ static int mpm_send(struct mpm_privdata *mpm, uint8_t command, /* ************************************************************************* - * myread + * mpm_serial_read * ************************************************************************* */ -static int myread(int fd, void *data, int size) +static int mpm_serial_read(int fd, void *data, int size) { int pos = 0; @@ -327,7 +330,7 @@ static int myread(int fd, void *data, int size) } return pos; -} /* myread */ +} /* mpm_serial_read */ /* ************************************************************************* @@ -342,7 +345,7 @@ static int mpm_recv(struct mpm_privdata *mpm, int len; uint8_t header[4]; - len = myread(mpm->fd, header, sizeof(header)); + len = mpm_serial_read(mpm->fd, header, sizeof(header)); if (len != sizeof(header)) { fprintf(stderr, "short read() from device (not addressed?)\n"); @@ -367,10 +370,9 @@ static int mpm_recv(struct mpm_privdata *mpm, /* free space in output buffer? */ if ((bufferpos < buffersize) && (buffer != NULL)) { - uint16_t size = MIN(buffersize - bufferpos, length); - len = myread(mpm->fd, buffer + bufferpos, size); + len = mpm_serial_read(mpm->fd, buffer + bufferpos, size); if (len <= 0) { fprintf(stderr, "short read() from device (%d != %d)\n", len, size); @@ -379,7 +381,6 @@ static int mpm_recv(struct mpm_privdata *mpm, bufferpos += len; length -= len; - } else { @@ -388,7 +389,7 @@ static int mpm_recv(struct mpm_privdata *mpm, /* no space in output buffer, but device still sends data -> do dummy read */ uint16_t size = MIN(sizeof(dummy), length); - len = myread(mpm->fd, dummy, size); + len = mpm_serial_read(mpm->fd, dummy, size); if (len <= 0) { fprintf(stderr, "short read() from device (%d != %d)\n", len, size); @@ -728,14 +729,14 @@ static int mpm_read(struct multiboot *mboot, struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "reading flash" : "reading eeprom"; - int pos = 0; - int size = (memtype == MEMTYPE_FLASH) ? mpm->flashsize : mpm->eepromsize; + uint16_t pos = 0; + uint16_t size = (memtype == MEMTYPE_FLASH) ? mpm->flashsize : mpm->eepromsize; while (pos < size) { mboot->progress_cb(progress_msg, pos, size); - int len = MIN(READ_BLOCK_SIZE, size - pos); + uint16_t len = MIN(READ_BLOCK_SIZE, size - pos); if (mpm_read_memory(mpm, dbuf->data + pos, len, memtype, pos)) { mboot->progress_cb(progress_msg, -1, -1); @@ -761,12 +762,12 @@ static int mpm_write(struct multiboot *mboot, struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; - int pos = 0; + uint16_t pos = 0; while (pos < dbuf->length) { mboot->progress_cb(progress_msg, pos, dbuf->length); - int len = (memtype == MEMTYPE_FLASH) ? mpm->flashpage : WRITE_BLOCK_SIZE; + uint16_t len = (memtype == MEMTYPE_FLASH) ? mpm->flashpage : WRITE_BLOCK_SIZE; len = MIN(len, dbuf->length - pos); if (mpm_write_memory(mpm, dbuf->data + pos, len, memtype, pos)) @@ -792,14 +793,14 @@ static int mpm_verify(struct multiboot *mboot, struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; - int pos = 0; + uint16_t pos = 0; uint8_t comp[READ_BLOCK_SIZE]; while (pos < dbuf->length) { mboot->progress_cb(progress_msg, pos, dbuf->length); - int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); + uint16_t len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); if (mpm_read_memory(mpm, comp, len, memtype, pos)) { mboot->progress_cb(progress_msg, -1, -1); @@ -825,6 +826,7 @@ static int mpm_verify(struct multiboot *mboot, struct multiboot_ops mpm_ops = { + .exec_name = "mpmboot", .alloc = mpm_alloc, .free = mpm_free, .get_memtype = mpm_get_memtype, diff --git a/multiboot.c b/multiboot.c index 49b9f9c..f78d383 100644 --- a/multiboot.c +++ b/multiboot.c @@ -33,16 +33,12 @@ #define ACTION_READ 0x01 #define ACTION_WRITE 0x02 -struct prog_mode { - char *progname; - struct multiboot_ops *ops; -}; - -static struct prog_mode prog_modes[] = +static struct multiboot_ops * prog_ops[] = { - { "twiboot", &twi_ops }, - { "mpmboot", &mpm_ops }, - { "funkboot", &funk_ops }, + &twi_ops, + &mpm_ops, + &funk_ops, + &eprog_ops, }; struct mboot_action @@ -71,6 +67,11 @@ static struct option main_optargs[] = * ************************************************************************* */ static void progress_mode0_cb(const char *msg, int pos, int size) { + /* unused parameter */ + (void)msg; + (void)pos; + (void)size; + /* no progress output */ } /* progress_mode0_cb */ @@ -82,15 +83,16 @@ static void progress_mode1_cb(const char *msg, int pos, int size) { if (pos != -1 && size != -1) { - char stars[50]; + char stars[51]; int i; - int count = (pos * sizeof(stars) / size); + int count = (pos * 50 / size); - for (i = 0; i < sizeof(stars); i++) + for (i = 0; i < 50; i++) { stars[i] = (i < count) ? '*' : ' '; } + stars[50] = '\0'; printf("%-15s: [%s] (%d)\r", msg, stars, pos); } @@ -211,14 +213,18 @@ static int main_optarg_cb(int val, const char *arg, void *privdata) switch (val) { case 'r': /* read */ - if (add_action(mboot, ACTION_READ, arg) < 0) + if ((mboot->ops->read == NULL) || + (add_action(mboot, ACTION_READ, arg) < 0) + ) { return -1; } break; case 'w': /* write */ - if (add_action(mboot, ACTION_WRITE, arg) < 0) + if ((mboot->ops->write == NULL) || + (add_action(mboot, ACTION_WRITE, arg) < 0) + ) { return -1; } @@ -263,17 +269,19 @@ int main(int argc, char *argv[]) char *progname = strrchr(argv[0], '/'); progname = (progname != NULL) ? (progname +1) : argv[0]; - int i; - for (i = 0; i < ARRAY_SIZE(prog_modes); i++) + unsigned int i; + for (i = 0; i < ARRAY_SIZE(prog_ops); i++) { - struct prog_mode *mode = &prog_modes[i]; + struct multiboot_ops * ops = prog_ops[i]; - if (strcmp(progname, mode->progname) == 0) + if (strcmp(progname, ops->exec_name) == 0) { - mboot = mode->ops->alloc(); + mboot = ops->alloc(); if (mboot == NULL) { - fprintf(stderr, "failed to allocate '%s'\n", progname); + fprintf(stderr, "failed to allocate '%s'\n", + progname); + return -1; } } @@ -381,7 +389,9 @@ int main(int argc, char *argv[]) break; } - if (mboot->verify) + if (mboot->verify && + (mboot->ops->verify != NULL) + ) { result = mboot->ops->verify(mboot, dbuf, action->memtype); if (result != 0) diff --git a/multiboot.h b/multiboot.h index 264e528..64477db 100644 --- a/multiboot.h +++ b/multiboot.h @@ -15,6 +15,8 @@ struct multiboot struct multiboot_ops { + const char * exec_name; + struct multiboot * (* alloc)(void); void (* free)(struct multiboot *mboot); @@ -32,5 +34,6 @@ struct multiboot_ops extern struct multiboot_ops twi_ops; extern struct multiboot_ops mpm_ops; extern struct multiboot_ops funk_ops; +extern struct multiboot_ops eprog_ops; #endif /* _MULTIBOOT_H_ */ diff --git a/twi.c b/twi.c index bd0ae45..48f0755 100644 --- a/twi.c +++ b/twi.c @@ -360,14 +360,14 @@ static int twi_read(struct multiboot *mboot, struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "reading flash" : "reading eeprom"; - int pos = 0; - int size = (memtype == MEMTYPE_FLASH) ? twi->flashsize : twi->eepromsize; + uint16_t pos = 0; + uint16_t size = (memtype == MEMTYPE_FLASH) ? twi->flashsize : twi->eepromsize; while (pos < size) { mboot->progress_cb(progress_msg, pos, size); - int len = MIN(READ_BLOCK_SIZE, size - pos); + uint8_t len = MIN(READ_BLOCK_SIZE, size - pos); if (twi_read_memory(twi, dbuf->data + pos, len, memtype, pos)) { @@ -395,12 +395,12 @@ static int twi_write(struct multiboot *mboot, struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; - int pos = 0; + uint16_t pos = 0; while (pos < dbuf->length) { mboot->progress_cb(progress_msg, pos, dbuf->length); - int len = (memtype == MEMTYPE_FLASH) ? twi->pagesize : WRITE_BLOCK_SIZE; + uint8_t len = (memtype == MEMTYPE_FLASH) ? twi->pagesize : WRITE_BLOCK_SIZE; len = MIN(len, dbuf->length - pos); @@ -426,7 +426,7 @@ static int twi_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; - int pos = 0; + uint16_t pos = 0; uint8_t comp[READ_BLOCK_SIZE]; while (pos < dbuf->length) @@ -571,6 +571,9 @@ static void twi_free(struct multiboot *mboot) static int twi_get_memtype(struct multiboot *mboot, const char *memname) { + /* unused parameter */ + (void)mboot; + if (strcmp(memname, "flash") == 0) { return MEMTYPE_FLASH; @@ -613,6 +616,7 @@ static int twi_get_memsize(struct multiboot *mboot, struct multiboot_ops twi_ops = { + .exec_name = "twiboot", .alloc = twi_alloc, .free = twi_free, .get_memtype = twi_get_memtype,