diff --git a/chipinfo_avr.c b/chipinfo_avr.c index 8d84ace..7efa121 100644 --- a/chipinfo_avr.c +++ b/chipinfo_avr.c @@ -27,26 +27,35 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) -struct chipinfo { +struct chipinfo +{ uint8_t sig[3]; const char name[16]; }; -static struct chipinfo chips[] = { +static struct chipinfo chips[] = +{ { { 0x1E, 0x93, 0x07 }, "AVR Mega 8" }, { { 0x1E, 0x93, 0x0A }, "AVR Mega 88" }, { { 0x1E, 0x94, 0x06 }, "AVR Mega 168" }, { { 0x1E, 0x95, 0x02 }, "AVR Mega 32" }, }; +/* ************************************************************************* + * chipinfo_get_avr_name + * ************************************************************************* */ const char * chipinfo_get_avr_name(const uint8_t *sig) { int i; - for (i = 0; i < ARRAY_SIZE(chips); i++) { + + for (i = 0; i < ARRAY_SIZE(chips); i++) + { struct chipinfo *chip = &chips[i]; if (chip->sig[0] == sig[0] && chip->sig[1] == sig[1] && chip->sig[2] == sig[2]) + { return chip->name; + } } return "unknown"; -} +} /* chipinfo_get_avr_name */ diff --git a/filedata.c b/filedata.c index 9d9de03..cab0717 100644 --- a/filedata.c +++ b/filedata.c @@ -31,10 +31,14 @@ #define FILETYPE_BINARY 1 #define FILETYPE_INTELHEX 2 +/* ************************************************************************* + * dbuf_alloc + * ************************************************************************* */ struct databuf * dbuf_alloc(uint32_t size) { struct databuf *dbuf = malloc(sizeof(struct databuf) + size); - if (dbuf == NULL) { + if (dbuf == NULL) + { perror("dbuf_alloc"); return NULL; } @@ -43,71 +47,108 @@ struct databuf * dbuf_alloc(uint32_t size) dbuf->size = size; dbuf->length = 0; return dbuf; -} +} /* dbuf_alloc */ + +/* ************************************************************************* + * dbuf_free + * ************************************************************************* */ void dbuf_free(struct databuf *dbuf) { free(dbuf); -} +} /* dbuf_free */ + +/* ************************************************************************* + * dbuf_dump + * ************************************************************************* */ static void dbuf_dump(struct databuf *dbuf) { int pos = 0, oldskip = 0; - while (pos < dbuf->length) { + while (pos < dbuf->length) + { char buf[128]; int j, i = 0; int skip = 1; - for (j = 0; j < 16; j++) { + for (j = 0; j < 16; j++) + { if (pos + j < dbuf->length) + { i += sprintf(buf + i, "%02X", dbuf->data[pos + j]); - else + } else { i += sprintf(buf + i, " "); + } if (j % 2) - buf[i++] = ' '; - } - - for (j = 0; j < 16; j++) { - if (pos + j < dbuf->length) { - unsigned char val = dbuf->data[pos + j]; - if (val >= 0x20 && val < 0x7F) - buf[i++] = val; - else - buf[i++] = '.'; - - if (val != 0xFF) - skip = 0; - } else { + { buf[i++] = ' '; } } - if (pos == 0 || (pos + 16) >= dbuf->length || skip == 0) { + for (j = 0; j < 16; j++) + { + if (pos + j < dbuf->length) + { + unsigned char val = dbuf->data[pos + j]; + + if (val >= 0x20 && val < 0x7F) + { + buf[i++] = val; + } else { + buf[i++] = '.'; + } + + if (val != 0xFF) + { + skip = 0; + } + } + else + { + buf[i++] = ' '; + } + } + + if ((pos == 0) || + ((pos + 16) >= dbuf->length) || + (skip == 0) + ) + { buf[i++] = '\0'; printf("%04X: %s\r\n", pos, buf); oldskip = 0; - } else if (skip == 1 && oldskip == 0) { + } + else if ((skip == 1) && + (oldskip == 0) + ) + { printf("****\n"); oldskip = 1; } pos += 16; } -} +} /* dbuf_dump */ + +/* ************************************************************************* + * binfile_getsize + * ************************************************************************* */ static int binfile_getsize(const char *filename, uint32_t *size) { int fd = open(filename, O_RDONLY); - if (fd < 0) { + if (fd < 0) + { perror("binfile_getsize(): open()"); return -1; } struct stat filestat; - if (fstat(fd, &filestat) < 0) { + if (fstat(fd, &filestat) < 0) + { perror("binfile_getsize(): fstat()"); close(fd); return -1; @@ -117,18 +158,24 @@ static int binfile_getsize(const char *filename, uint32_t *size) close(fd); return 0; -} +} /* binfile_getsize */ + +/* ************************************************************************* + * binfile_read + * ************************************************************************* */ static int binfile_read(const char *filename, struct databuf *dbuf) { int fd = open(filename, O_RDONLY); - if (fd < 0) { + if (fd < 0) + { perror("binfile_read(): open()"); return -1; } ssize_t readsize = read(fd, dbuf->data, dbuf->size); - if (readsize <= 0) { + if (readsize <= 0) + { perror("binfile_read(): read()"); close(fd); return -1; @@ -138,18 +185,24 @@ static int binfile_read(const char *filename, struct databuf *dbuf) close(fd); return 0; -} +} /* binfile_read */ + +/* ************************************************************************* + * binfile_write + * ************************************************************************* */ static int binfile_write(const char *filename, struct databuf *dbuf) { int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (fd < 0) { + if (fd < 0) + { perror("binfile_write(): open()"); return -1; } ssize_t writesize = write(fd, dbuf->data, dbuf->length); - if (writesize != dbuf->length) { + if (writesize != dbuf->length) + { perror("binfile_write(): write()"); close(fd); return -1; @@ -157,9 +210,11 @@ static int binfile_write(const char *filename, struct databuf *dbuf) close(fd); return 0; -} +} /* binfile_write */ -struct ihex_record { + +struct ihex_record +{ uint8_t byte_count; uint16_t address; uint8_t type; @@ -168,46 +223,61 @@ struct ihex_record { uint8_t chksum; }; + +/* ************************************************************************* + * hex2byte + * ************************************************************************* */ static uint8_t hex2byte(const char *ptr) { int i; uint8_t result = 0; - for (i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) + { result <<= 4; - result |= (ptr[i] >= '0' && ptr[i] <= '9') ? (ptr[i] - '0') : - (((ptr[i] & 0xDF) >= 'A' && (ptr[i] & 0xDF) <= 'F') ? (ptr[i] - 'A' + 0x0A) : - 0x00); + result |= (ptr[i] >= '0' && ptr[i] <= '9') ? (ptr[i] - '0') + : (((ptr[i] & 0xDF) >= 'A' && (ptr[i] & 0xDF) <= 'F') ? (ptr[i] - 'A' + 0x0A) + : 0x00); } return result; -} +} /* hex2byte */ + +/* ************************************************************************* + * hexfile_getrecord + * ************************************************************************* */ static int hexfile_getrecord(FILE *stream, struct ihex_record *record) { char *hexline = NULL; size_t size; ssize_t length = getline(&hexline, &size, stream); - if (length == -1) { - if (!feof(stream)) { + if (length == -1) + { + if (!feof(stream)) + { perror("hexfile_getrecord(): getline()"); } + return -1; } - if (length < 12) { - fprintf(stderr, "record too short (%d)\n", length); + if (length < 12) + { + fprintf(stderr, "record too short (%ld)\n", length); free(hexline); return -1; } int pos = 0; - if (hexline[pos] != ':') { + if (hexline[pos] != ':') + { fprintf(stderr, "invalid startcode\n"); free(hexline); return -1; } + pos++; uint8_t chksum = 0x00; @@ -216,9 +286,11 @@ static int hexfile_getrecord(FILE *stream, struct ihex_record *record) chksum += record->byte_count; pos += 2; - if (record->byte_count > 0) { + if (record->byte_count > 0) + { record->data = malloc(record->byte_count); - if (record->data == NULL) { + if (record->data == NULL) + { perror("hexfile_getrecord(): malloc()"); free(hexline); return -1; @@ -236,7 +308,8 @@ static int hexfile_getrecord(FILE *stream, struct ihex_record *record) pos += 2; int i; - for (i = 0; i < record->byte_count; i++) { + for (i = 0; i < record->byte_count; i++) + { record->data[i] = hex2byte(&hexline[pos]); chksum += record->data[i]; pos += 2; @@ -246,18 +319,26 @@ static int hexfile_getrecord(FILE *stream, struct ihex_record *record) chksum += record->chksum; pos += 2; - if (chksum != 0x00) { + if (chksum != 0x00) + { fprintf(stderr, "invalid checksum (0x%02X)\n", chksum); if (record->byte_count > 0) + { free(record->data); + } + free(hexline); return -1; } free(hexline); return 0; -} +} /* hexfile_getrecord */ + +/* ************************************************************************* + * hexfile_putrecord + * ************************************************************************* */ static int hexfile_putrecord(FILE *stream, struct ihex_record *record) { uint8_t chksum = record->byte_count; @@ -269,39 +350,62 @@ static int hexfile_putrecord(FILE *stream, struct ihex_record *record) char buf[64]; buf[0] = '\0'; - for (i = 0; i < record->byte_count; i++) { + for (i = 0; i < record->byte_count; i++) + { len += snprintf(buf + len, sizeof(buf) - len, "%02X", record->data[i]); chksum += record->data[i]; } - fprintf(stream, ":%02X%04X%02X%s%02X\n", record->byte_count, record->address, record->type, buf, (uint8_t)(0x100 - chksum)); - return -1; -} + fprintf(stream, ":%02X%04X%02X%s%02X\n", + record->byte_count, + record->address, + record->type, + buf, + (uint8_t)(0x100 - chksum)); + return -1; +} /* hexfile_putrecord */ + + +/* ************************************************************************* + * hexfile_getsize + * ************************************************************************* */ static int hexfile_getsize(const char *filename, uint32_t *size) { *size = 0x10000; return 0; -} +} /* hexfile_getsize */ + +/* ************************************************************************* + * hexfile_read + * ************************************************************************* */ static int hexfile_read(const char *filename, struct databuf *dbuf) { FILE *stream = fopen(filename, "r"); - if (stream == NULL) { + if (stream == NULL) + { perror("hexfile_read(): fopen()"); return -1; } - while (1) { + while (1) + { struct ihex_record record; memset(&record, 0x00, sizeof(struct ihex_record)); int result = hexfile_getrecord(stream, &record); if (result == -1) + { break; + } - if (record.type == 0x00) { - if (record.address > dbuf->size || record.address + record.byte_count > dbuf->size) { + if (record.type == 0x00) + { + if ((record.address > dbuf->size) || + (record.address + record.byte_count > dbuf->size) + ) + { fprintf(stderr, "hexfile_read(): data out of bounds\n"); break; } @@ -313,12 +417,17 @@ static int hexfile_read(const char *filename, struct databuf *dbuf) fclose(stream); return 0; -} +} /* hexfile_read */ + +/* ************************************************************************* + * hexfile_write + * ************************************************************************* */ static int hexfile_write(const char *filename, struct databuf *dbuf) { FILE *stream = fopen(filename, "w"); - if (stream == NULL) { + if (stream == NULL) + { perror("hexfile_write(): fopen()"); return -1; } @@ -326,21 +435,30 @@ static int hexfile_write(const char *filename, struct databuf *dbuf) int i; int addr_min = dbuf->length; int addr_max = 0; - for (i = 0; i < dbuf->length; i++) { + for (i = 0; i < dbuf->length; i++) + { if (dbuf->data[i] == 0xFF) + { continue; + } if (addr_min > i) + { addr_min = i; + } if (addr_max < i) + { addr_max = i; + } } + addr_min = addr_min & ~0x0F; addr_max = (addr_max + 0x0F) & ~0x0F; struct ihex_record record; - for (i = addr_min; i < addr_max; i += 0x10) { + for (i = addr_min; i < addr_max; i += 0x10) + { record.byte_count = 0x10; record.address = i; record.type = 0x00; @@ -357,67 +475,93 @@ static int hexfile_write(const char *filename, struct databuf *dbuf) fclose(stream); return 0; -} +} /* hexfile_write */ + +/* ************************************************************************* + * get_filetype + * ************************************************************************* */ static int get_filetype(const char *filename) { const char *ext = filename + (strlen(filename) -4); if (ext < filename) + { return FILETYPE_UNKNOWN; + } if (strncmp(ext, ".bin", 4) == 0) + { return FILETYPE_BINARY; + } if (strncmp(ext, ".hex", 4) == 0) + { return FILETYPE_INTELHEX; + } return FILETYPE_UNKNOWN; -} +} /* get_filetype */ + +/* ************************************************************************* + * file_getsize + * ************************************************************************* */ int file_getsize(const char *filename, uint32_t *size) { - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_getsize(filename, size); + switch (get_filetype(filename)) + { + case FILETYPE_BINARY: + return binfile_getsize(filename, size); - case FILETYPE_INTELHEX: - return hexfile_getsize(filename, size); + case FILETYPE_INTELHEX: + return hexfile_getsize(filename, size); - default: - return -1; + default: + return -1; } -} +} /* file_getsize */ + +/* ************************************************************************* + * file_read + * ************************************************************************* */ int file_read(const char *filename, struct databuf *dbuf) { - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_read(filename, dbuf); + switch (get_filetype(filename)) + { + case FILETYPE_BINARY: + return binfile_read(filename, dbuf); - case FILETYPE_INTELHEX: - return hexfile_read(filename, dbuf); + case FILETYPE_INTELHEX: + return hexfile_read(filename, dbuf); - default: - return -1; + default: + return -1; } -} +} /* file_read */ + +/* ************************************************************************* + * file_write + * ************************************************************************* */ int file_write(const char *filename, struct databuf *dbuf) { - if (strncmp(filename, "-", 1) == 0) { + if (strncmp(filename, "-", 1) == 0) + { dbuf_dump(dbuf); return 0; } - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_write(filename, dbuf); + switch (get_filetype(filename)) + { + case FILETYPE_BINARY: + return binfile_write(filename, dbuf); - case FILETYPE_INTELHEX: - return hexfile_write(filename, dbuf); + case FILETYPE_INTELHEX: + return hexfile_write(filename, dbuf); - default: - return -1; + default: + return -1; } -} +} /* file_write */ diff --git a/funk.c b/funk.c index c769730..1c97741 100644 --- a/funk.c +++ b/funk.c @@ -124,7 +124,8 @@ struct rfm12_pkt struct multiboot_ops funk_ops; -struct funk_privdata { +struct funk_privdata +{ char *device; int fd; int connected; @@ -141,30 +142,35 @@ struct funk_privdata { }; -static struct option funk_optargs[] = { - {"address", 1, 0, 'a'}, /* -a */ - {"device", 1, 0, 'd'}, /* [ -d ] */ +static struct option funk_optargs[] = +{ + { "address", 1, 0, 'a'}, /* -a */ + { "device", 1, 0, 'd'}, /* [ -d ] */ }; +/* ************************************************************************* + * funk_optarg_cb + * ************************************************************************* */ static int funk_optarg_cb(int val, const char *arg, void *privdata) { struct funk_privdata *funk = (struct funk_privdata *)privdata; - switch (val) { - case 'a': /* address */ - { - char *endptr; - funk->address = strtol(arg, &endptr, 16); - if (*endptr != '\0' || funk->address < 0x00 || funk->address > 0xFF) { - fprintf(stderr, "invalid address: '%s'\n", arg); - return -1; - } - } - break; + switch (val) + { + case 'a': /* address */ + { + char *endptr; - case 'd': /* device */ - { + funk->address = strtol(arg, &endptr, 16); + if (*endptr != '\0' || funk->address < 0x00 || funk->address > 0xFF) { + fprintf(stderr, "invalid address: '%s'\n", arg); + return -1; + } + } + break; + + case 'd': /* device */ if (funk->device != NULL) { fprintf(stderr, "invalid device: '%s'\n", optarg); return -1; @@ -175,11 +181,10 @@ static int funk_optarg_cb(int val, const char *arg, void *privdata) perror("strdup()"); return -1; } - } - break; + break; - case 'h': - case '?': /* error */ + case 'h': + case '?': /* error */ fprintf(stderr, "Usage: funkboot [options]\n" " -a
- selects rfm12 address (0x00 - 0xFF)\n" " -d - selects funkbridge device\n" @@ -192,25 +197,31 @@ static int funk_optarg_cb(int val, const char *arg, void *privdata) "\n"); return -1; - default: - return 1; + default: + return 1; } return 0; } /* funk_optarg_cb */ +/* ************************************************************************* + * funk_alloc + * ************************************************************************* */ static struct multiboot * funk_alloc(void) { struct multiboot * mboot = malloc(sizeof(struct multiboot)); if (mboot == NULL) + { return NULL; + } memset(mboot, 0x00, sizeof(struct multiboot)); mboot->ops = &funk_ops; struct funk_privdata *funk = malloc(sizeof(struct funk_privdata)); - if (funk == NULL) { + if (funk == NULL) + { free(mboot); return NULL; } @@ -226,55 +237,78 @@ static struct multiboot * funk_alloc(void) } /* funk_alloc */ +/* ************************************************************************* + * funk_free + * ************************************************************************* */ static void funk_free(struct multiboot *mboot) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; if (funk->device != NULL) + { free(funk->device); + } free(funk); free(mboot); } /* funk_free */ -static int funk_get_memtype(struct multiboot *mboot, const char *memname) +/* ************************************************************************* + * optarg_copy + * ************************************************************************* */ +static int funk_get_memtype(struct multiboot *mboot, + const char *memname) { if (strcmp(memname, "flash") == 0) + { return MEMTYPE_FLASH; - + } else if (strcmp(memname, "eeprom") == 0) + { return MEMTYPE_EEPROM; + } return -1; } /* funk_get_memtype */ -static int funk_get_memsize(struct multiboot *mboot, int memtype) +/* ************************************************************************* + * optarg_copy + * ************************************************************************* */ +static int funk_get_memsize(struct multiboot *mboot, + int memtype) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; if (!funk->connected) + { return 0; + } - switch (memtype) { - case MEMTYPE_FLASH: - return funk->flashsize; + switch (memtype) + { + case MEMTYPE_FLASH: + return funk->flashsize; - case MEMTYPE_EEPROM: - return funk->eepromsize; + case MEMTYPE_EEPROM: + return funk->eepromsize; - default: - return 0; + default: + return 0; } } /* funk_get_memsize */ +/* ************************************************************************* + * funk_serial_read + * ************************************************************************* */ static int funk_serial_read(int fd, void *data, int size) { int pos = 0; - while (1) { + while (1) + { fd_set fdset; struct timeval timeout = { .tv_sec = 1, .tv_usec = 0 }; @@ -282,21 +316,29 @@ static int funk_serial_read(int fd, void *data, int size) FD_SET(fd, &fdset); int ret = select(fd +1, &fdset, NULL, NULL, &timeout); - if (ret == -1) { + if (ret == -1) + { perror("select"); return -1; - } else if (ret == 0) { + } + else if (ret == 0) + { break; - - } else if (FD_ISSET(fd, &fdset)) { + } + else if (FD_ISSET(fd, &fdset)) + { int len = read(fd, data + pos, size - pos); - if (len < 0) { + if (len < 0) + { return -1; - } else { + } + else + { pos += len; - if (pos == size) { + if (pos == size) + { break; } } @@ -308,31 +350,48 @@ static int funk_serial_read(int fd, void *data, int size) #if (FUNK_BRIDGE_DEBUG == 1) || (FUNK_PACKET_DEBUG == 1) +/* ************************************************************************* + * funk_print_data + * ************************************************************************* */ static char * funk_print_data(uint8_t *data, uint16_t length) { int pos = 0, i = 0, j; char *buf = malloc(length * 4 + 64); - while (pos < length) { + while (pos < length) + { i += sprintf(buf + i, "%04X: ", pos); - for (j = 0; j < 16; j++) { + for (j = 0; j < 16; j++) + { if (pos + j < length) + { i += sprintf(buf + i, "%02X", data[pos + j]); + } else + { i += sprintf(buf + i, " "); + if (j % 2) + { + buf[i++] = ' '; + } + } - if (j % 2) - buf[i++] = ' '; - } - - for (j = 0; j < 16; j++) { - if (pos + j < length) { + for (j = 0; j < 16; j++) + { + if (pos + j < length) + { unsigned char val = data[pos + j]; if (val >= 0x20 && val < 0x80) + { buf[i++] = val; + } else + { buf[i++] = '.'; - } else { + } + } + else + { buf[i++] = ' '; } } @@ -348,16 +407,27 @@ static char * funk_print_data(uint8_t *data, uint16_t length) #endif -static int funk_bridge_send(struct funk_privdata *funk, uint8_t *header, uint8_t headerlength, uint8_t *data, uint8_t datalength) +/* ************************************************************************* + * funk_bridge_send + * ************************************************************************* */ +static int funk_bridge_send(struct funk_privdata *funk, + uint8_t *header, + uint8_t headerlength, + uint8_t *data, + uint8_t datalength) { - if (headerlength > 0) { - if (write(funk->fd, header, headerlength) != headerlength) { + if (headerlength > 0) + { + if (write(funk->fd, header, headerlength) != headerlength) + { return -1; } } - if (datalength > 0) { - if (write(funk->fd, data, datalength) != datalength) { + if (datalength > 0) + { + if (write(funk->fd, data, datalength) != datalength) + { return -1; } } @@ -372,7 +442,14 @@ static int funk_bridge_send(struct funk_privdata *funk, uint8_t *header, uint8_t } /* funk_bridge_send */ -static int funk_bridge_recv(struct funk_privdata *funk, uint8_t command, uint8_t *cause, uint8_t *buffer, int buffersize) +/* ************************************************************************* + * funk_bridge_recv + * ************************************************************************* */ +static int funk_bridge_recv(struct funk_privdata *funk, + uint8_t command, + uint8_t *cause, + uint8_t *buffer, + int buffersize) { uint8_t response[3]; int len; @@ -384,45 +461,63 @@ static int funk_bridge_recv(struct funk_privdata *funk, uint8_t command, uint8_t return -1; } - if (response[0] != command) { - fprintf(stderr, "invalid command response (0x%02x != 0x%02x)\n", response[0], command); + if (response[0] != command) + { + fprintf(stderr, "invalid command response (0x%02x != 0x%02x)\n", + response[0], command); + return -1; } *cause = response[1]; uint16_t length = response[2]; uint16_t bufferpos = 0; - while (length > 0) { + + while (length > 0) + { /* free space in output buffer? */ - if ((bufferpos < buffersize) && (buffer != NULL)) { - + if ((bufferpos < buffersize) && (buffer != NULL)) + { uint16_t size = MIN(buffersize - bufferpos, length); + len = funk_serial_read(funk->fd, buffer + bufferpos, size); - if (len <= 0) { - fprintf(stderr, "short read() from device (%d != %d)\n", len, size); + if (len <= 0) + { + fprintf(stderr, "short read() from device (%d != %d)\n", + len, size); + return -1; } + bufferpos += len; length -= len; - - } else { + } + else + { uint8_t dummy[256]; /* no space in output buffer, but device still sends data -> do dummy read */ uint16_t size = MIN(sizeof(dummy), length); + len = funk_serial_read(funk->fd, dummy, size); - if (len <= 0) { - fprintf(stderr, "short read() from device (%d != %d)\n", len, size); + if (len <= 0) + { + fprintf(stderr, "short read() from device (%d != %d)\n", + len, size); + return -1; } + length -= len; } } #if (FUNK_BRIDGE_DEBUG == 1) char *dump = funk_print_data(buffer, bufferpos); - printf("funk_bridge_recv() cmd=0x%02x cause=0x%02x length=0x%02x\n%s\n", command, *cause, length, dump); + printf("funk_bridge_recv() cmd=0x%02x cause=0x%02x length=0x%02x\n%s\n", + command, *cause, length, dump); + free(dump); #endif @@ -430,22 +525,33 @@ static int funk_bridge_recv(struct funk_privdata *funk, uint8_t command, uint8_t } /* funk_bridge_recv */ -static int funk_send_packet(struct funk_privdata *funk, struct rfm12_pkt *pkt, int length) +/* ************************************************************************* + * funk_send_packet + * ************************************************************************* */ +static int funk_send_packet(struct funk_privdata *funk, + struct rfm12_pkt *pkt, + int length) { uint8_t request[] = { BRIDGE_CMD_TRANSMIT, length }; int ret = funk_bridge_send(funk, request, sizeof(request), (uint8_t *)pkt, length); if (ret < 0) + { return ret; + } uint8_t cause = BRIDGE_CAUSE_SUCCESS; ret = funk_bridge_recv(funk, request[0], &cause, NULL, 0); if (ret != 0) + { return -1; + } #if (FUNK_PACKET_DEBUG == 1) char *dump = funk_print_data((uint8_t *)pkt, length); - printf("funk_send_packet() cause=0x%02x length=0x%02x\n%s\n", cause, length, dump); + printf("funk_send_packet() cause=0x%02x length=0x%02x\n%s\n", + cause, length, dump); + free(dump); #endif @@ -453,18 +559,27 @@ static int funk_send_packet(struct funk_privdata *funk, struct rfm12_pkt *pkt, i } /* funk_send_packet */ -static int funk_recv_packet(struct funk_privdata *funk, struct rfm12_pkt *pkt, int *length) +/* ************************************************************************* + * funk_recv_packet + * ************************************************************************* */ +static int funk_recv_packet(struct funk_privdata *funk, + struct rfm12_pkt *pkt, + int *length) { uint8_t request[] = { BRIDGE_CMD_RECEIVE, 0 }; int ret = funk_bridge_send(funk, request, sizeof(request), NULL, 0); if (ret < 0) + { return ret; + } uint8_t cause = BRIDGE_CAUSE_SUCCESS; ret = funk_bridge_recv(funk, request[0], &cause, (uint8_t *)pkt, *length); if (ret < 0) + { return -1; + } *length = ret; @@ -478,18 +593,27 @@ static int funk_recv_packet(struct funk_privdata *funk, struct rfm12_pkt *pkt, i } /* funk_recv_packet */ -static int funk_bridge_version(struct funk_privdata *funk, uint8_t *version, int size) +/* ************************************************************************* + * funk_bridge_version + * ************************************************************************* */ +static int funk_bridge_version(struct funk_privdata *funk, + uint8_t *version, + int size) { uint8_t request[] = { BRIDGE_CMD_VERSION, 0 }; int ret = funk_bridge_send(funk, request, sizeof(request), NULL, 0); if (ret < 0) + { return ret; + } uint8_t cause = BRIDGE_CAUSE_SUCCESS; ret = funk_bridge_recv(funk, request[0], &cause, version, size); if (ret < 0) + { return ret; + } version[ret] = '\0'; @@ -497,6 +621,9 @@ static int funk_bridge_version(struct funk_privdata *funk, uint8_t *version, int } /* funk_bridge_version */ +/* ************************************************************************* + * funk_close_device + * ************************************************************************* */ static void funk_close_device(struct funk_privdata *funk) { /* delay close() / tcsetattr() */ @@ -507,15 +634,20 @@ static void funk_close_device(struct funk_privdata *funk) } /* funk_close_device */ +/* ************************************************************************* + * funk_open_device + * ************************************************************************* */ static int funk_open_device(struct funk_privdata *funk) { funk->fd = open(funk->device, O_RDWR | O_NOCTTY | O_CLOEXEC); - if (funk->fd < 0) { + if (funk->fd < 0) + { perror("open()"); return -1; } - if (tcgetattr(funk->fd, &funk->oldtio) < 0) { + if (tcgetattr(funk->fd, &funk->oldtio) < 0) + { perror("tcgetattr(oldtio)"); close(funk->fd); return -1; @@ -531,7 +663,8 @@ static int funk_open_device(struct funk_privdata *funk) newtio.c_cc[VTIME] = 0; int err = tcsetattr(funk->fd, TCSANOW, &newtio); - if (err < 0) { + if (err < 0) + { perror("tcsetattr(newtio)"); close(funk->fd); return -1; @@ -542,7 +675,11 @@ static int funk_open_device(struct funk_privdata *funk) } /* funk_open_device */ -static int funk_switch_application(struct funk_privdata *funk, uint8_t application) +/* ************************************************************************* + * funk_switch_application + * ************************************************************************* */ +static int funk_switch_application(struct funk_privdata *funk, + uint8_t application) { struct rfm12_pkt packet; @@ -556,14 +693,16 @@ static int funk_switch_application(struct funk_privdata *funk, uint8_t applicati packet.msg.p.switchapp.app = application; int ret = funk_send_packet(funk, &packet, 4 + packet.data_length); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_switch_application(): funk_send_packet()\n"); return ret; } int response_size = sizeof(packet); ret = funk_recv_packet(funk, &packet, &response_size); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_switch_application(): funk_recv_packet()\n"); return ret; } @@ -579,7 +718,12 @@ static int funk_switch_application(struct funk_privdata *funk, uint8_t applicati } /* funk_switch_application */ -static int funk_read_version(struct funk_privdata *funk, uint8_t *version, uint16_t length) +/* ************************************************************************* + * funk_read_version + * ************************************************************************* */ +static int funk_read_version(struct funk_privdata *funk, + uint8_t *version, + uint16_t length) { struct rfm12_pkt packet; @@ -592,14 +736,16 @@ static int funk_read_version(struct funk_privdata *funk, uint8_t *version, uint1 packet.msg.cause = CAUSE_SUCCESS; int ret = funk_send_packet(funk, &packet, 4 + packet.data_length); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_read_version(): funk_send_packet()\n"); return ret; } int response_size = sizeof(packet); ret = funk_recv_packet(funk, &packet, &response_size); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_read_version(): funk_recv_packet()\n"); return ret; } @@ -613,7 +759,9 @@ static int funk_read_version(struct funk_privdata *funk, uint8_t *version, uint1 int i; for (i = 0; i < packet.data_length -3; i++) + { version[i] = packet.msg.p.version.data[i] & 0x7F; + } version[i] = '\0'; @@ -621,7 +769,12 @@ static int funk_read_version(struct funk_privdata *funk, uint8_t *version, uint1 } /* funk_read_version */ -static int funk_read_chipinfo(struct funk_privdata *funk, uint8_t *chipinfo, uint16_t length) +/* ************************************************************************* + * funk_read_chipinfo + * ************************************************************************* */ +static int funk_read_chipinfo(struct funk_privdata *funk, + uint8_t *chipinfo, + uint16_t length) { struct rfm12_pkt packet; @@ -634,7 +787,8 @@ static int funk_read_chipinfo(struct funk_privdata *funk, uint8_t *chipinfo, uin packet.msg.cause = CAUSE_SUCCESS; int ret = funk_send_packet(funk, &packet, 4 + packet.data_length); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_read_chipinfo(): funk_send_packet()\n"); return ret; } @@ -659,7 +813,14 @@ static int funk_read_chipinfo(struct funk_privdata *funk, uint8_t *chipinfo, uin } /* funk_read_chipinfo */ -static int funk_read_memory(struct funk_privdata *funk, uint8_t *buffer, uint16_t size, uint8_t memtype, uint16_t address) +/* ************************************************************************* + * funk_read_memory + * ************************************************************************* */ +static int funk_read_memory(struct funk_privdata *funk, + uint8_t *buffer, + uint16_t size, + uint8_t memtype, + uint16_t address) { struct rfm12_pkt packet; @@ -700,7 +861,14 @@ static int funk_read_memory(struct funk_privdata *funk, uint8_t *buffer, uint16_ } /* funk_read_memory */ -static int __funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint16_t size, uint8_t memtype, uint16_t address) +/* ************************************************************************* + * __funk_write_memory + * ************************************************************************* */ +static int __funk_write_memory(struct funk_privdata *funk, + uint8_t *buffer, + uint16_t size, + uint8_t memtype, + uint16_t address) { struct rfm12_pkt packet; @@ -718,14 +886,16 @@ static int __funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint memcpy(packet.msg.p.write_req.data, buffer, size); int ret = funk_send_packet(funk, &packet, 4 + packet.data_length); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_write_memory(): funk_send_packet()\n"); return ret; } int response_size = sizeof(packet); ret = funk_recv_packet(funk, &packet, &response_size); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "funk_write_memory(): funk_recv_packet()\n"); return ret; } @@ -741,7 +911,14 @@ static int __funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint } /* __funk_write_memory */ -static int funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint16_t size, uint8_t memtype, uint16_t address) +/* ************************************************************************* + * funk_write_memory + * ************************************************************************* */ +static int funk_write_memory(struct funk_privdata *funk, + uint8_t *buffer, + uint16_t size, + uint8_t memtype, + uint16_t address) { if (memtype == MEMTYPE_EEPROM) { @@ -769,7 +946,9 @@ static int funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint16 { ret = __funk_write_memory(funk, &pagebuf[pos], WRITE_BLOCK_SIZE, memtype, address + pos); if (ret < 0) + { break; + } } free(pagebuf); @@ -777,39 +956,52 @@ static int funk_write_memory(struct funk_privdata *funk, uint8_t *buffer, uint16 } /* funk_write_memory */ +/* ************************************************************************* + * funk_close + * ************************************************************************* */ static int funk_close(struct multiboot *mboot) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; if (funk->connected) + { funk_switch_application(funk, BOOTTYPE_APPLICATION); + } funk_close_device(funk); return 0; } /* funk_close */ +/* ************************************************************************* + * funk_open + * ************************************************************************* */ static int funk_open(struct multiboot *mboot) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; - if (funk->address == 0) { + if (funk->address == 0) + { fprintf(stderr, "abort: no address given\n"); return -1; } - if (funk->device == NULL) { + if (funk->device == NULL) + { fprintf(stderr, "abort: no device given\n"); return -1; } if (funk_open_device(funk) < 0) + { return -1; + } printf("funkbridge dev : %-16s\n", funk->device); char bridge_version[20]; - if (funk_bridge_version(funk, (uint8_t *)bridge_version, sizeof(bridge_version))) { + if (funk_bridge_version(funk, (uint8_t *)bridge_version, sizeof(bridge_version))) + { fprintf(stderr, "failed to get funkbridge version\n"); funk_close(mboot); return -1; @@ -817,7 +1009,8 @@ static int funk_open(struct multiboot *mboot) printf("funkbridge ver : %-16s\n", bridge_version); - if (funk_switch_application(funk, BOOTTYPE_BOOTLOADER)) { + if (funk_switch_application(funk, BOOTTYPE_BOOTLOADER)) + { fprintf(stderr, "failed to switch to bootloader (invalid address?)\n"); funk_close(mboot); return -1; @@ -829,14 +1022,16 @@ static int funk_open(struct multiboot *mboot) usleep(100000); char version[20]; - if (funk_read_version(funk, (uint8_t *)version, sizeof(version))) { + if (funk_read_version(funk, (uint8_t *)version, sizeof(version))) + { fprintf(stderr, "failed to get bootloader version\n"); funk_close(mboot); return -1; } uint8_t chipinfo[8]; - if (funk_read_chipinfo(funk, chipinfo, sizeof(chipinfo))) { + if (funk_read_chipinfo(funk, chipinfo, sizeof(chipinfo))) + { fprintf(stderr, "failed to get bootloader chipinfo\n"); funk_close(mboot); return -1; @@ -848,26 +1043,39 @@ static int funk_open(struct multiboot *mboot) funk->flashsize = (chipinfo[4] << 8) + chipinfo[5]; funk->eepromsize = (chipinfo[6] << 8) + chipinfo[7]; - printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); - printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", funk->flashsize, funk->flashsize, funk->flashpage); - printf("eeprom size : 0x%04x / %5d\n", funk->eepromsize, funk->eepromsize); + printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", + version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); + + printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", + funk->flashsize, funk->flashsize, funk->flashpage); + + printf("eeprom size : 0x%04x / %5d\n", + funk->eepromsize, funk->eepromsize); return 0; } /* funk_open */ -static int funk_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) +/* ************************************************************************* + * funk_read + * ************************************************************************* */ +static int funk_read(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) { 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; - while (pos < size) { + + while (pos < size) + { mboot->progress_cb(progress_msg, pos, size); int len = MIN(READ_BLOCK_SIZE, size - pos); - if (funk_read_memory(funk, dbuf->data + pos, len, memtype, pos)) { + if (funk_read_memory(funk, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -882,19 +1090,27 @@ static int funk_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) } /* funk_read */ -static int funk_write(struct multiboot *mboot, struct databuf *dbuf, int memtype) +/* ************************************************************************* + * funk_write + * ************************************************************************* */ +static int funk_write(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; int pos = 0; - while (pos < dbuf->length) { + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int len = (memtype == MEMTYPE_FLASH) ? funk->flashpage : WRITE_BLOCK_SIZE; len = MIN(len, dbuf->length - pos); - if (funk_write_memory(funk, dbuf->data + pos, len, memtype, pos)) { + + if (funk_write_memory(funk, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -907,23 +1123,32 @@ static int funk_write(struct multiboot *mboot, struct databuf *dbuf, int memtype } /* funk_write */ -static int funk_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype) +/* ************************************************************************* + * funk_verify + * ************************************************************************* */ +static int funk_verify(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) { struct funk_privdata *funk = (struct funk_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; int pos = 0; uint8_t comp[READ_BLOCK_SIZE]; - while (pos < dbuf->length) { + + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); - if (funk_read_memory(funk, comp, len, memtype, pos)) { + if (funk_read_memory(funk, comp, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } - if (memcmp(comp, dbuf->data + pos, len) != 0x00) { + if (memcmp(comp, dbuf->data + pos, len) != 0x00) + { mboot->progress_cb(progress_msg, -1, -1); fprintf(stderr, "verify failed at page 0x%04x!!\n", pos); return -1; @@ -939,7 +1164,8 @@ static int funk_verify(struct multiboot *mboot, struct databuf *dbuf, int memtyp } /* funk_verify */ -struct multiboot_ops funk_ops = { +struct multiboot_ops funk_ops = +{ .alloc = funk_alloc, .free = funk_free, .get_memtype = funk_get_memtype, diff --git a/mpm.c b/mpm.c index 2b91e44..6da88dc 100644 --- a/mpm.c +++ b/mpm.c @@ -40,7 +40,8 @@ struct multiboot_ops mpm_ops; -struct mpm_privdata { +struct mpm_privdata +{ char *device; int fd; int connected; @@ -54,44 +55,52 @@ struct mpm_privdata { struct termios oldtio; }; -static struct option mpm_optargs[] = { - {"address", 1, 0, 'a'}, /* -a */ - {"device", 1, 0, 'd'}, /* [ -d ] */ +static struct option mpm_optargs[] = +{ + { "address", 1, 0, 'a'}, /* -a */ + { "device", 1, 0, 'd'}, /* [ -d ] */ }; + +/* ************************************************************************* + * mpm_optarg_cb + * ************************************************************************* */ static int mpm_optarg_cb(int val, const char *arg, void *privdata) { struct mpm_privdata *mpm = (struct mpm_privdata *)privdata; - switch (val) { - case 'a': /* address */ - { - char *endptr; - mpm->address = strtol(arg, &endptr, 16); - if (*endptr != '\0' || mpm->address < 0x01 || mpm->address > 0x7F) { - fprintf(stderr, "invalid address: '%s'\n", arg); - return -1; - } - } - break; + switch (val) + { + case 'a': /* address */ + { + char *endptr; + mpm->address = strtol(arg, &endptr, 16); - case 'd': /* device */ - { - if (mpm->device != NULL) { + if (*endptr != '\0' || mpm->address < 0x01 || mpm->address > 0x7F) + { + fprintf(stderr, "invalid address: '%s'\n", arg); + return -1; + } + } + break; + + case 'd': /* device */ + if (mpm->device != NULL) + { fprintf(stderr, "invalid device: '%s'\n", optarg); return -1; } mpm->device = strdup(optarg); - if (mpm->device == NULL) { + if (mpm->device == NULL) + { perror("strdup()"); return -1; } - } - break; + break; - case 'h': - case '?': /* error */ + case 'h': + case '?': /* error */ fprintf(stderr, "Usage: mpmboot [options]\n" " -a
- selects mpm address (0x01 - 0xFF)\n" " -d - selects mpm device\n" @@ -102,26 +111,34 @@ static int mpm_optarg_cb(int val, const char *arg, void *privdata) "\n" "Example: mpmboot -d /dev/ttyUSB0 -a 0x22 -w flash:blmc.hex -w flash:blmc_eeprom.hex\n" "\n"); + return -1; - default: - return 1; + default: + return 1; } return 0; -} +} /* mpm_optarg_cb */ + +/* ************************************************************************* + * mpm_alloc + * ************************************************************************* */ static struct multiboot * mpm_alloc(void) { struct multiboot * mboot = malloc(sizeof(struct multiboot)); if (mboot == NULL) + { return NULL; + } memset(mboot, 0x00, sizeof(struct multiboot)); mboot->ops = &mpm_ops; struct mpm_privdata *mpm = malloc(sizeof(struct mpm_privdata)); - if (mpm == NULL) { + if (mpm == NULL) + { free(mboot); return NULL; } @@ -130,65 +147,94 @@ static struct multiboot * mpm_alloc(void) mpm->device = NULL; mpm->address = 0; - optarg_register(mpm_optargs, ARRAY_SIZE(mpm_optargs), mpm_optarg_cb, (void *)mpm); + optarg_register(mpm_optargs, ARRAY_SIZE(mpm_optargs), + mpm_optarg_cb, (void *)mpm); mboot->privdata = mpm; return mboot; -} +} /* mpm_alloc */ + +/* ************************************************************************* + * mpm_free + * ************************************************************************* */ static void mpm_free(struct multiboot *mboot) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; if (mpm->device != NULL) + { free(mpm->device); + } free(mpm); free(mboot); -} +} /* mpm_free */ -static int mpm_get_memtype(struct multiboot *mboot, const char *memname) + +/* ************************************************************************* + * mpm_get_memtype + * ************************************************************************* */ +static int mpm_get_memtype(struct multiboot *mboot, + const char *memname) { if (strcmp(memname, "flash") == 0) + { return MEMTYPE_FLASH; - + } else if (strcmp(memname, "eeprom") == 0) + { return MEMTYPE_EEPROM; + } return -1; -} +} /* mpm_get_memtype */ + +/* ************************************************************************* + * mpm_get_memsize + * ************************************************************************* */ static int mpm_get_memsize(struct multiboot *mboot, int memtype) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; if (!mpm->connected) - return 0; - - switch (memtype) { - case MEMTYPE_FLASH: - return mpm->flashsize; - - case MEMTYPE_EEPROM: - return mpm->eepromsize; - - default: + { return 0; } -} -static int mpm_send(struct mpm_privdata *mpm, uint8_t command, uint8_t *data, int length) + switch (memtype) + { + case MEMTYPE_FLASH: + return mpm->flashsize; + + case MEMTYPE_EEPROM: + return mpm->eepromsize; + + default: + return 0; + } +} /* mpm_get_memsize */ + + +/* ************************************************************************* + * mpm_send + * ************************************************************************* */ +static int mpm_send(struct mpm_privdata *mpm, uint8_t command, + uint8_t *data, int length) { struct termios tio; - if (tcgetattr(mpm->fd, &tio) < 0) { + if (tcgetattr(mpm->fd, &tio) < 0) + { perror("tcgetattr(tio)"); return -1; } tio.c_cflag |= PARODD; - if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) { + if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) + { perror("tcsetattr(tio)"); return -1; } @@ -196,7 +242,8 @@ static int mpm_send(struct mpm_privdata *mpm, uint8_t command, uint8_t *data, in // usleep(5000); uint8_t address = mpm->address; - if (write(mpm->fd, &address, sizeof(address)) != sizeof(address)) { + if (write(mpm->fd, &address, sizeof(address)) != sizeof(address)) + { perror("write(address)"); return -1; } @@ -205,7 +252,8 @@ static int mpm_send(struct mpm_privdata *mpm, uint8_t command, uint8_t *data, in tio.c_cflag &= ~(PARODD); - if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) { + if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) + { perror("tcsetattr(tio)"); return -1; } @@ -215,26 +263,34 @@ static int mpm_send(struct mpm_privdata *mpm, uint8_t command, uint8_t *data, in header[1] = (length >> 8) & 0xFF; header[2] = length & 0xFF; - if (write(mpm->fd, header, sizeof(header)) != sizeof(header)) { + if (write(mpm->fd, header, sizeof(header)) != sizeof(header)) + { perror("write(header)"); return -1; } - if (data != NULL && length != 0) { - if (write(mpm->fd, data, length) != length) { + if (data != NULL && length != 0) + { + if (write(mpm->fd, data, length) != length) + { perror("write(data)"); return -1; } } return 0; -} +} /* mpm_send */ + +/* ************************************************************************* + * myread + * ************************************************************************* */ static int myread(int fd, void *data, int size) { int pos = 0; - while (1) { + while (1) + { fd_set fdset; struct timeval timeout = { .tv_sec = 1, .tv_usec = 0 }; @@ -242,21 +298,28 @@ static int myread(int fd, void *data, int size) FD_SET(fd, &fdset); int ret = select(fd +1, &fdset, NULL, NULL, &timeout); - if (ret == -1) { + if (ret == -1) + { perror("select"); return -1; - } else if (ret == 0) { + } + else if (ret == 0) + { break; - - } else if (FD_ISSET(fd, &fdset)) { + } + else if (FD_ISSET(fd, &fdset)) + { int len = read(fd, data + pos, size - pos); - if (len < 0) { + if (len < 0) + { return -1; - - } else { + } + else + { pos += len; - if (pos == size) { + if (pos == size) + { break; } } @@ -264,20 +327,30 @@ static int myread(int fd, void *data, int size) } return pos; -} +} /* myread */ -static int mpm_recv(struct mpm_privdata *mpm, uint8_t command, uint8_t *cause, uint8_t *buffer, uint16_t buffersize) + +/* ************************************************************************* + * mpm_recv + * ************************************************************************* */ +static int mpm_recv(struct mpm_privdata *mpm, + uint8_t command, + uint8_t *cause, + uint8_t *buffer, + uint16_t buffersize) { int len; uint8_t header[4]; len = myread(mpm->fd, header, sizeof(header)); - if (len != sizeof(header)) { + if (len != sizeof(header)) + { fprintf(stderr, "short read() from device (not addressed?)\n"); return -1; } - if (header[0] != command) { + if (header[0] != command) + { fprintf(stderr, "invalid command response (0x%02x != 0x%02x)\n", header[0], command); return -1; } @@ -288,37 +361,51 @@ static int mpm_recv(struct mpm_privdata *mpm, uint8_t command, uint8_t *cause, u // printf("mpm_recv() cmd=0x%02x cause=0x%02x length=0x%04x\n", command, *cause, length); uint16_t bufferpos = 0; - while (length > 0) { + while (length > 0) + { /* free space in output buffer? */ - if ((bufferpos < buffersize) && (buffer != NULL)) { + if ((bufferpos < buffersize) && (buffer != NULL)) + { uint16_t size = MIN(buffersize - bufferpos, length); + len = myread(mpm->fd, buffer + bufferpos, size); - if (len <= 0) { + if (len <= 0) + { fprintf(stderr, "short read() from device (%d != %d)\n", len, size); return -1; } + bufferpos += len; length -= len; - } else { + } + else + { uint8_t dummy[256]; /* 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); - if (len <= 0) { + if (len <= 0) + { fprintf(stderr, "short read() from device (%d != %d)\n", len, size); return -1; } + length -= len; } } return bufferpos; -} +} /* mpm_recv */ + +/* ************************************************************************* + * mpm_close_device + * ************************************************************************* */ static void mpm_close_device(struct mpm_privdata *mpm) { /* delay close() / tcsetattr() */ @@ -326,17 +413,23 @@ static void mpm_close_device(struct mpm_privdata *mpm) tcsetattr(mpm->fd, TCSANOW, &mpm->oldtio); close(mpm->fd); -} +} /* mpm_close_device */ + +/* ************************************************************************* + * mpm_open_device + * ************************************************************************* */ static int mpm_open_device(struct mpm_privdata *mpm) { mpm->fd = open(mpm->device, O_RDWR | O_NOCTTY | O_CLOEXEC); - if (mpm->fd < 0) { + if (mpm->fd < 0) + { perror("open()"); return -1; } - if (tcgetattr(mpm->fd, &mpm->oldtio) < 0) { + if (tcgetattr(mpm->fd, &mpm->oldtio) < 0) + { perror("tcgetattr(oldtio)"); close(mpm->fd); return -1; @@ -352,7 +445,8 @@ static int mpm_open_device(struct mpm_privdata *mpm) newtio.c_cc[VTIME] = 0; int err = tcsetattr(mpm->fd, TCSANOW, &newtio); - if (err < 0) { + if (err < 0) + { perror("tcsetattr(newtio)"); close(mpm->fd); return -1; @@ -360,58 +454,94 @@ static int mpm_open_device(struct mpm_privdata *mpm) mpm->connected = 1; return 0; -} +} /* mpm_open_device */ -static int mpm_switch_application(struct mpm_privdata *mpm, uint8_t application) + +/* ************************************************************************* + * mpm_switch_application + * ************************************************************************* */ +static int mpm_switch_application(struct mpm_privdata *mpm, + uint8_t application) { uint8_t data[] = { application }; + int ret = mpm_send(mpm, CMD_SWITCH_APPLICATION, data, sizeof(data)); if (ret < 0) + { return ret; + } uint8_t cause = CAUSE_SUCCESS; ret = mpm_recv(mpm, CMD_SWITCH_APPLICATION, &cause, NULL, 0); if (ret < 0) + { return ret; + } return (cause != CAUSE_SUCCESS); -} +} /* mpm_switch_application */ -static int mpm_read_version(struct mpm_privdata *mpm, uint8_t *version, uint16_t length) + +/* ************************************************************************* + * mpm_read_version + * ************************************************************************* */ +static int mpm_read_version(struct mpm_privdata *mpm, + uint8_t *version, uint16_t length) { memset(version, 0, length); int ret = mpm_send(mpm, CMD_GET_BOOTLOADER_VERSION, NULL, 0); if (ret < 0) + { return ret; + } uint8_t cause = CAUSE_SUCCESS; ret = mpm_recv(mpm, CMD_GET_BOOTLOADER_VERSION, &cause, version, length); if (ret < 0) + { return ret; + } int i; for (i = 0; i < length; i++) + { version[i] &= ~0x80; + } return (cause != CAUSE_SUCCESS); } -static int mpm_read_chipinfo(struct mpm_privdata *mpm, uint8_t *chipinfo, uint16_t length) + +/* ************************************************************************* + * mpm_read_chipinfo + * ************************************************************************* */ +static int mpm_read_chipinfo(struct mpm_privdata *mpm, + uint8_t *chipinfo, uint16_t length) { int ret = mpm_send(mpm, CMD_GET_CHIP_INFO, NULL, 0); if (ret < 0) + { return ret; + } uint8_t cause = CAUSE_SUCCESS; ret = mpm_recv(mpm, CMD_GET_CHIP_INFO, &cause, chipinfo, length); if (ret < 0) + { return ret; + } return (cause != CAUSE_SUCCESS); -} +} /* mpm_read_chipinfo */ -static int mpm_read_memory(struct mpm_privdata *mpm, uint8_t *buffer, uint16_t size, uint8_t memtype, uint16_t address) + +/* ************************************************************************* + * mpm_read_memory + * ************************************************************************* */ +static int mpm_read_memory(struct mpm_privdata *mpm, + uint8_t *buffer, uint16_t size, + uint8_t memtype, uint16_t address) { uint8_t param[5] = { memtype, @@ -423,33 +553,51 @@ static int mpm_read_memory(struct mpm_privdata *mpm, uint8_t *buffer, uint16_t s int ret = mpm_send(mpm, CMD_READ_MEMORY, param, sizeof(param)); if (ret < 0) + { return ret; + } uint8_t cause = CAUSE_SUCCESS; ret = mpm_recv(mpm, CMD_READ_MEMORY, &cause, buffer, size); if (ret < 0) + { return ret; + } return (cause != CAUSE_SUCCESS); -} +} /* mpm_read_memory */ -static int mpm_write_memory(struct mpm_privdata *mpm, uint8_t *buffer, uint16_t size, uint8_t memtype, uint16_t address) + +/* ************************************************************************* + * mpm_write_memory + * ************************************************************************* */ +static int mpm_write_memory(struct mpm_privdata *mpm, + uint8_t *buffer, uint16_t size, + uint8_t memtype, uint16_t address) { int bufsize; - if (memtype == MEMTYPE_FLASH) { - if ((address & (mpm->flashpage -1)) != 0x00) { + + if (memtype == MEMTYPE_FLASH) + { + if ((address & (mpm->flashpage -1)) != 0x00) + { fprintf(stderr, "mpm_write_memory(): address 0x%04x not aligned to pagesize 0x%02x\n", address, mpm->flashpage); return -1; } + bufsize = 5 + mpm->flashpage; - } else { + } + else + { bufsize = 5 + size; } uint8_t *cmd = malloc(bufsize); if (cmd == NULL) + { return -1; + } cmd[0] = memtype; cmd[1] = (address >> 8) & 0xFF; @@ -458,53 +606,73 @@ static int mpm_write_memory(struct mpm_privdata *mpm, uint8_t *buffer, uint16_t cmd[4] = ((bufsize -5) & 0xFF); memcpy(cmd +5, buffer, size); - if (memtype == MEMTYPE_FLASH) { + if (memtype == MEMTYPE_FLASH) + { memset(cmd +5 +size, 0xFF, mpm->flashpage - size); } int ret = mpm_send(mpm, CMD_WRITE_MEMORY, cmd, bufsize); if (ret < 0) + { return ret; + } free(cmd); uint8_t cause = CAUSE_SUCCESS; ret = mpm_recv(mpm, CMD_WRITE_MEMORY, &cause, NULL, 0); if (ret < 0) + { return ret; + } return (cause != CAUSE_SUCCESS); -} +} /* mpm_write_memory */ + +/* ************************************************************************* + * mpm_close + * ************************************************************************* */ static int mpm_close(struct multiboot *mboot) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; if (mpm->connected) + { mpm_switch_application(mpm, BOOTTYPE_APPLICATION); + } mpm_close_device(mpm); return 0; -} +} /* mpm_close */ + +/* ************************************************************************* + * mpm_open + * ************************************************************************* */ static int mpm_open(struct multiboot *mboot) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; - if (mpm->address == 0) { + if (mpm->address == 0) + { fprintf(stderr, "abort: no address given\n"); return -1; } - if (mpm->device == NULL) { + if (mpm->device == NULL) + { fprintf(stderr, "abort: no device given\n"); return -1; } if (mpm_open_device(mpm) < 0) + { return -1; + } - if (mpm_switch_application(mpm, BOOTTYPE_BOOTLOADER)) { + if (mpm_switch_application(mpm, BOOTTYPE_BOOTLOADER)) + { fprintf(stderr, "failed to switch to bootloader (invalid address?)\n"); mpm_close(mboot); return -1; @@ -514,14 +682,16 @@ static int mpm_open(struct multiboot *mboot) usleep(100000); char version[16]; - if (mpm_read_version(mpm, (uint8_t *)version, sizeof(version))) { + if (mpm_read_version(mpm, (uint8_t *)version, sizeof(version))) + { fprintf(stderr, "failed to get bootloader version\n"); mpm_close(mboot); return -1; } uint8_t chipinfo[8]; - if (mpm_read_chipinfo(mpm, chipinfo, sizeof(chipinfo))) { + if (mpm_read_chipinfo(mpm, chipinfo, sizeof(chipinfo))) + { fprintf(stderr, "failed to get bootloader version\n"); mpm_close(mboot); return -1; @@ -533,26 +703,41 @@ static int mpm_open(struct multiboot *mboot) mpm->flashsize = (chipinfo[4] << 8) + chipinfo[5]; mpm->eepromsize = (chipinfo[6] << 8) + chipinfo[7]; - printf("device : %-16s (address: 0x%02X)\n", mpm->device, mpm->address); - printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); - printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", mpm->flashsize, mpm->flashsize, mpm->flashpage); - printf("eeprom size : 0x%04x / %5d\n", mpm->eepromsize, mpm->eepromsize); + printf("device : %-16s (address: 0x%02X)\n", + mpm->device, mpm->address); + + printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", + version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); + + printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", + mpm->flashsize, mpm->flashsize, mpm->flashpage); + + printf("eeprom size : 0x%04x / %5d\n", + mpm->eepromsize, mpm->eepromsize); return 0; -} +} /* mpm_open */ -static int mpm_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) + +/* ************************************************************************* + * mpm_read + * ************************************************************************* */ +static int mpm_read(struct multiboot *mboot, + struct databuf *dbuf, int memtype) { 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; - while (pos < size) { + + while (pos < size) + { mboot->progress_cb(progress_msg, pos, size); int len = MIN(READ_BLOCK_SIZE, size - pos); - if (mpm_read_memory(mpm, dbuf->data + pos, len, memtype, pos)) { + if (mpm_read_memory(mpm, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -564,21 +749,28 @@ static int mpm_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) mboot->progress_cb(progress_msg, pos, size); return 0; -} +} /* mpm_read */ -static int mpm_write(struct multiboot *mboot, struct databuf *dbuf, int memtype) + +/* ************************************************************************* + * mpm_write + * ************************************************************************* */ +static int mpm_write(struct multiboot *mboot, + struct databuf *dbuf, int memtype) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; int pos = 0; - while (pos < dbuf->length) { + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int 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)) { + if (mpm_write_memory(mpm, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -588,25 +780,34 @@ static int mpm_write(struct multiboot *mboot, struct databuf *dbuf, int memtype) mboot->progress_cb(progress_msg, pos, dbuf->length); return 0; -} +} /* mpm_write */ -static int mpm_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype) + +/* ************************************************************************* + * mpm_verify + * ************************************************************************* */ +static int mpm_verify(struct multiboot *mboot, + struct databuf *dbuf, int memtype) { struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; int pos = 0; uint8_t comp[READ_BLOCK_SIZE]; - while (pos < dbuf->length) { + + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); - if (mpm_read_memory(mpm, comp, len, memtype, pos)) { + if (mpm_read_memory(mpm, comp, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } - if (memcmp(comp, dbuf->data + pos, len) != 0x00) { + if (memcmp(comp, dbuf->data + pos, len) != 0x00) + { mboot->progress_cb(progress_msg, -1, -1); fprintf(stderr, "verify failed at page 0x%04x!!\n", pos); return -1; @@ -619,9 +820,11 @@ static int mpm_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype mboot->progress_cb(progress_msg, pos, dbuf->length); return 0; -} +} /* mpm_verify */ -struct multiboot_ops mpm_ops = { + +struct multiboot_ops mpm_ops = +{ .alloc = mpm_alloc, .free = mpm_free, .get_memtype = mpm_get_memtype, diff --git a/multiboot.c b/multiboot.c index 5f21c3e..49b9f9c 100644 --- a/multiboot.c +++ b/multiboot.c @@ -45,7 +45,8 @@ static struct prog_mode prog_modes[] = { "funkboot", &funk_ops }, }; -struct mboot_action { +struct mboot_action +{ struct list_head list; char *filename; @@ -55,78 +56,110 @@ struct mboot_action { static LIST_HEAD(action_list); -static struct option main_optargs[] = { - {"help", 0, 0, 'h'}, /* [ -h ] */ - {"progress", 1, 0, 'p'}, /* [ -p <0|1|2> ] */ - {"read", 1, 0, 'r'}, /* [ -r : ] */ - {"write", 1, 0, 'w'}, /* [ -w : ] */ - {"no-verify", 0, 0, 'n'}, /* [ -n ] */ - {0, 0, 0, 0} +static struct option main_optargs[] = +{ + { "help", 0, 0, 'h'}, /* [ -h ] */ + { "progress", 1, 0, 'p'}, /* [ -p <0|1|2> ] */ + { "read", 1, 0, 'r'}, /* [ -r : ] */ + { "write", 1, 0, 'w'}, /* [ -w : ] */ + { "no-verify", 0, 0, 'n'}, /* [ -n ] */ + { 0, 0, 0, 0} }; +/* ************************************************************************* + * progress_mode0_cb + * ************************************************************************* */ static void progress_mode0_cb(const char *msg, int pos, int size) { /* no progress output */ -} +} /* progress_mode0_cb */ + +/* ************************************************************************* + * progress_mode1_cb + * ************************************************************************* */ static void progress_mode1_cb(const char *msg, int pos, int size) { - if (pos != -1 && size != -1) { + if (pos != -1 && size != -1) + { char stars[50]; - int i; int count = (pos * sizeof(stars) / size); + for (i = 0; i < sizeof(stars); i++) + { stars[i] = (i < count) ? '*' : ' '; + } printf("%-15s: [%s] (%d)\r", msg, stars, pos); } if (pos == size) + { printf("\n"); -} + } +} /* progress_mode1_cb */ + +/* ************************************************************************* + * progress_mode2_cb + * ************************************************************************* */ static void progress_mode2_cb(const char *msg, int pos, int size) { static int old_count; - if (pos != -1 && size != -1) { - if (pos == 0) { + if (pos != -1 && size != -1) + { + if (pos == 0) + { old_count = 0; printf("%-15s: [", msg); - } else if (pos <=size) { + } + else if (pos <=size) + { int i; int count = (pos * 50 / size); + for (i = old_count; i < count; i++) + { printf("*"); + } old_count = count; - if (pos == size) { + if (pos == size) + { printf("] (%d)\n", pos); } } } -} +} /* progress_mode2_cb */ + +/* ************************************************************************* + * add_action + * ************************************************************************* */ static int add_action(struct multiboot *mboot, int mode, const char *arg) { struct mboot_action *action = malloc(sizeof(struct mboot_action)); - if (action == NULL) { + if (action == NULL) + { perror("malloc()"); return -1; } char *argcopy = strdup(arg); - if (argcopy == NULL) { + if (argcopy == NULL) + { perror("strdup()"); free(action); return -1; } char *tok = strtok(argcopy, ":"); - if (tok == NULL) { + if (tok == NULL) + { fprintf(stderr, "invalid argument: '%s'\n", arg); free(argcopy); free(action); @@ -134,7 +167,8 @@ static int add_action(struct multiboot *mboot, int mode, const char *arg) } action->memtype = mboot->ops->get_memtype(mboot, tok); - if (action->memtype == -1) { + if (action->memtype == -1) + { fprintf(stderr, "invalid memtype: '%s'\n", tok); free(argcopy); free(action); @@ -142,7 +176,8 @@ static int add_action(struct multiboot *mboot, int mode, const char *arg) } tok = strtok(NULL, ":"); - if (tok == NULL) { + if (tok == NULL) + { fprintf(stderr, "invalid argument: '%s'\n", arg); free(argcopy); free(action); @@ -150,7 +185,8 @@ static int add_action(struct multiboot *mboot, int mode, const char *arg) } action->filename = strdup(tok); - if (action->filename == NULL) { + if (action->filename == NULL) + { perror("strdup()"); free(argcopy); free(action); @@ -162,57 +198,64 @@ static int add_action(struct multiboot *mboot, int mode, const char *arg) list_add_tail(&action->list, &action_list); free(argcopy); return 0; -} +} /* add_action */ + +/* ************************************************************************* + * main_optarg_cb + * ************************************************************************* */ static int main_optarg_cb(int val, const char *arg, void *privdata) { struct multiboot *mboot = (struct multiboot *)privdata; - switch (val) { - case 'r': /* read */ - { + switch (val) + { + case 'r': /* read */ if (add_action(mboot, ACTION_READ, arg) < 0) - return -1; - } - break; - - case 'w': /* write */ - { - if (add_action(mboot, ACTION_WRITE, arg) < 0) - return -1; - } - break; - - case 'n': /* no verify after write */ - mboot->verify = 0; - break; - - case 'p': - { - switch (*arg) { - case '0': - mboot->progress_cb = progress_mode0_cb; - break; - - case '1': - mboot->progress_cb = progress_mode1_cb; - break; - - case '2': - mboot->progress_cb = progress_mode2_cb; - break; - - default: - fprintf(stderr, "invalid progress bar mode: '%s'\n", arg); + { return -1; } - } - break; + break; + + case 'w': /* write */ + if (add_action(mboot, ACTION_WRITE, arg) < 0) + { + return -1; + } + break; + + case 'n': /* no verify after write */ + mboot->verify = 0; + break; + + case 'p': + switch (*arg) + { + case '0': + mboot->progress_cb = progress_mode0_cb; + break; + + case '1': + mboot->progress_cb = progress_mode1_cb; + break; + + case '2': + mboot->progress_cb = progress_mode2_cb; + break; + + default: + fprintf(stderr, "invalid progress bar mode: '%s'\n", arg); + return -1; + } + break; } return 0; } +/* ************************************************************************* + * main + * ************************************************************************* */ int main(int argc, char *argv[]) { struct multiboot *mboot = NULL; @@ -221,19 +264,23 @@ int main(int argc, char *argv[]) progname = (progname != NULL) ? (progname +1) : argv[0]; int i; - for (i = 0; i < ARRAY_SIZE(prog_modes); i++) { + for (i = 0; i < ARRAY_SIZE(prog_modes); i++) + { struct prog_mode *mode = &prog_modes[i]; - if (strcmp(progname, mode->progname) == 0) { + if (strcmp(progname, mode->progname) == 0) + { mboot = mode->ops->alloc(); - if (mboot == NULL) { + if (mboot == NULL) + { fprintf(stderr, "failed to allocate '%s'\n", progname); return -1; } } } - if (mboot == NULL) { + if (mboot == NULL) + { fprintf(stderr, "invalid progname\n"); return -1; } @@ -241,35 +288,49 @@ int main(int argc, char *argv[]) mboot->verify = 1; mboot->progress_cb = progress_mode1_cb; - optarg_register(main_optargs, ARRAY_SIZE(main_optargs), main_optarg_cb, (void *)mboot); + optarg_register(main_optargs, ARRAY_SIZE(main_optargs), + main_optarg_cb, (void *)mboot); + int abort = optarg_parse(argc, argv); - if (abort == -1 || mboot->ops->open(mboot) != 0) + if ((abort == -1) || + (mboot->ops->open(mboot) != 0) + ) + { return -1; + } setbuf(stdout, NULL); struct mboot_action *action, *tmp; - list_for_each_entry(action, &action_list, list) { + list_for_each_entry(action, &action_list, list) + { abort = 1; - if (action->mode == ACTION_READ) { + if (action->mode == ACTION_READ) + { int memsize = mboot->ops->get_memsize(mboot, action->memtype); if (memsize == 0) + { break; + } struct databuf *dbuf = dbuf_alloc(memsize); if (dbuf == NULL) + { break; + } int result = mboot->ops->read(mboot, dbuf, action->memtype); - if (result != 0) { + if (result != 0) + { fprintf(stderr, "failed to read from device\n"); dbuf_free(dbuf); break; } result = file_write(action->filename, dbuf); - if (result != 0) { + if (result != 0) + { fprintf(stderr, "failed to write file '%s'\n", action->filename); dbuf_free(dbuf); break; @@ -278,42 +339,53 @@ int main(int argc, char *argv[]) dbuf_free(dbuf); abort = 0; - } else if (action->mode == ACTION_WRITE) { + } + else if (action->mode == ACTION_WRITE) + { unsigned int size; int result; result = file_getsize(action->filename, &size); if (result != 0) + { break; + } struct databuf *dbuf = dbuf_alloc(size); if (dbuf == NULL) + { break; + } result = file_read(action->filename, dbuf); - if (result != 0) { + if (result != 0) + { fprintf(stderr, "failed to read file '%s'\n", action->filename); dbuf_free(dbuf); break; } int memsize = mboot->ops->get_memsize(mboot, action->memtype); - if (memsize == 0) { + if (memsize == 0) + { fprintf(stderr, "invalid memsize: 0x%04x > 0x%04x\n", dbuf->length, memsize); dbuf_free(dbuf); break; } result = mboot->ops->write(mboot, dbuf, action->memtype); - if (result != 0) { + if (result != 0) + { fprintf(stderr, "failed to write to device\n"); dbuf_free(dbuf); break; } - if (mboot->verify) { + if (mboot->verify) + { result = mboot->ops->verify(mboot, dbuf, action->memtype); - if (result != 0) { + if (result != 0) + { fprintf(stderr, "failed to verify\n"); dbuf_free(dbuf); break; @@ -325,7 +397,8 @@ int main(int argc, char *argv[]) } } - list_for_each_entry_safe(action, tmp, &action_list, list) { + list_for_each_entry_safe(action, tmp, &action_list, list) + { free(action->filename); free(action); } @@ -335,4 +408,4 @@ int main(int argc, char *argv[]) optarg_free(); return abort; -} +} /* main */ diff --git a/multiboot.h b/multiboot.h index 0f7fa13..264e528 100644 --- a/multiboot.h +++ b/multiboot.h @@ -4,7 +4,8 @@ #include #include "filedata.h" -struct multiboot { +struct multiboot +{ struct multiboot_ops *ops; void *privdata; @@ -12,7 +13,8 @@ struct multiboot { void (* progress_cb)(const char *msg, int pos, int max); }; -struct multiboot_ops { +struct multiboot_ops +{ struct multiboot * (* alloc)(void); void (* free)(struct multiboot *mboot); diff --git a/optarg.c b/optarg.c index c452b98..a2cfa08 100644 --- a/optarg.c +++ b/optarg.c @@ -28,7 +28,8 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) -struct optarg_entry { +struct optarg_entry +{ struct list_head list; const struct option *opts; int count; @@ -39,6 +40,10 @@ struct optarg_entry { static LIST_HEAD(option_list); + +/* ************************************************************************* + * optarg_register + * ************************************************************************* */ int optarg_register(const struct option *opts, int count, int (* parser_cb)(int val, const char *arg, void *privdata), void *privdata) @@ -47,7 +52,9 @@ int optarg_register(const struct option *opts, int count, entry = malloc(sizeof(struct optarg_entry)); if (entry == NULL) + { return -1; + } entry->opts = opts; /* TODO: copy? */ entry->count = count; @@ -56,18 +63,27 @@ int optarg_register(const struct option *opts, int count, list_add_tail(&entry->list, &option_list); return 0; -} +} /* optarg_register */ + +/* ************************************************************************* + * optarg_free + * ************************************************************************* */ void optarg_free(void) { struct optarg_entry *entry, *entry_tmp; - list_for_each_entry_safe(entry, entry_tmp, &option_list, list) { + list_for_each_entry_safe(entry, entry_tmp, &option_list, list) + { list_del(&entry->list); free(entry); } -} +} /* optarg_free */ + +/* ************************************************************************* + * optarg_getsize + * ************************************************************************* */ static void optarg_getsize(int *opt_count, int *optstring_len) { int count = 0; @@ -75,17 +91,21 @@ static void optarg_getsize(int *opt_count, int *optstring_len) struct optarg_entry *entry; - list_for_each_entry(entry, &option_list, list) { + list_for_each_entry(entry, &option_list, list) + { count += entry->count; int i; - for (i = 0; i < entry->count; i++) { - switch (entry->opts[i].has_arg) { + for (i = 0; i < entry->count; i++) + { + switch (entry->opts[i].has_arg) + { case 0: /* no arguments */ case 1: /* has argument */ case 2: /* optional argument */ length += entry->opts[i].has_arg +1; break; + default: break; } @@ -94,19 +114,26 @@ static void optarg_getsize(int *opt_count, int *optstring_len) *opt_count = count +1; *optstring_len = length +1; -} +} /* optarg_getsize */ + +/* ************************************************************************* + * optarg_copy + * ************************************************************************* */ static void optarg_copy(struct option *opts, char *optstring) { struct optarg_entry *entry; - list_for_each_entry(entry, &option_list, list) { + list_for_each_entry(entry, &option_list, list) + { memcpy(opts, entry->opts, sizeof(struct option) * entry->count); opts += entry->count; int i; - for (i = 0; i < entry->count; i++) { - switch (entry->opts[i].has_arg) { + for (i = 0; i < entry->count; i++) + { + switch (entry->opts[i].has_arg) + { case 0: /* no arguments */ *optstring++ = (char)entry->opts[i].val; break; @@ -130,8 +157,12 @@ static void optarg_copy(struct option *opts, char *optstring) memset(opts++, 0x00, sizeof(struct option)); *optstring++ = '\0'; -} +} /* optarg_copy */ + +/* ************************************************************************* + * optarg_parse + * ************************************************************************* */ int optarg_parse(int argc, char * const argv[]) { struct option *longopts; @@ -143,10 +174,13 @@ int optarg_parse(int argc, char * const argv[]) longopts = malloc(sizeof(struct option) * opt_count); if (longopts == NULL) + { return -1; + } optstring = malloc(optstring_len); - if (optstring == NULL) { + if (optstring == NULL) + { free(longopts); return -1; } @@ -155,32 +189,44 @@ int optarg_parse(int argc, char * const argv[]) int retval = 0; int val = 0; - while (val != -1 && retval == 0) { + while (val != -1 && retval == 0) + { opterr = 1; /* print error message to stderr */ val = getopt_long(argc, argv, optstring, longopts, NULL); - if (val == 0x00) /* variable assigned (not supported) */ + /* variable assigned (not supported) */ + if (val == 0x00) + { continue; + } struct optarg_entry *entry; - list_for_each_entry(entry, &option_list, list) { + list_for_each_entry(entry, &option_list, list) + { int ret = entry->parser_cb(val, optarg, entry->privdata); /* option recognized, with error */ - if (ret < 0) { + if (ret < 0) + { retval = ret; break; - + } /* option recognized, no error */ - } else if (ret == 0) { + else if (ret == 0) + { break; } } - if (val == -1) /* parsing completed */ + /* parsing completed */ + if (val == -1) + { break; + } - if (val == '?') { /* parsing error */ + /* parsing error */ + if (val == '?') + { retval = 1; break; } @@ -190,4 +236,4 @@ int optarg_parse(int argc, char * const argv[]) free(longopts); return retval; -} +} /* optarg_parse */ diff --git a/twi.c b/twi.c index a0589b0..bd0ae45 100644 --- a/twi.c +++ b/twi.c @@ -66,7 +66,8 @@ struct multiboot_ops twi_ops; -struct twi_privdata { +struct twi_privdata +{ char *device; uint8_t address; int fd; @@ -77,62 +78,103 @@ struct twi_privdata { uint16_t eepromsize; }; -static struct option twi_optargs[] = { - {"address", 1, 0, 'a'}, /* -a */ - {"device", 1, 0, 'd'}, /* [ -d ] */ +static struct option twi_optargs[] = +{ + { "address", 1, 0, 'a'}, /* -a */ + { "device", 1, 0, 'd'}, /* [ -d ] */ }; -static int twi_switch_application(struct twi_privdata *twi, uint8_t application) + +/* ************************************************************************* + * twi_switch_application + * ************************************************************************* */ +static int twi_switch_application(struct twi_privdata *twi, + uint8_t application) { uint8_t cmd[] = { CMD_SWITCH_APPLICATION, application }; return (write(twi->fd, cmd, sizeof(cmd)) != sizeof(cmd)); -} +} /* twi_switch_application */ -static int twi_read_version(struct twi_privdata *twi, char *version, int length) + +/* ************************************************************************* + * twi_switch_application + * ************************************************************************* */ +static int twi_read_version(struct twi_privdata *twi, + char *version, int length) { uint8_t cmd[] = { CMD_READ_VERSION }; if (write(twi->fd, cmd, sizeof(cmd)) != sizeof(cmd)) + { return -1; + } memset(version, 0, length); if (read(twi->fd, version, length) != length) + { return -1; + } int i; for (i = 0; i < length; i++) + { version[i] &= ~0x80; + } return 0; -} +} /* twi_read_version */ -static int twi_read_memory(struct twi_privdata *twi, uint8_t *buffer, uint8_t size, uint8_t memtype, uint16_t address) + +/* ************************************************************************* + * twi_read_memory + * ************************************************************************* */ +static int twi_read_memory(struct twi_privdata *twi, + uint8_t *buffer, uint8_t size, + uint8_t memtype, uint16_t address) { uint8_t cmd[] = { CMD_READ_MEMORY, memtype, (address >> 8) & 0xFF, (address & 0xFF) }; + if (write(twi->fd, cmd, sizeof(cmd)) != sizeof(cmd)) + { return -1; + } return (read(twi->fd, buffer, size) != size); -} +} /* twi_read_memory */ -static int twi_write_memory(struct twi_privdata *twi, uint8_t *buffer, uint8_t size, uint8_t memtype, uint16_t address) + +/* ************************************************************************* + * twi_write_memory + * ************************************************************************* */ +static int twi_write_memory(struct twi_privdata *twi, + uint8_t *buffer, uint8_t size, + uint8_t memtype, uint16_t address) { int bufsize; - if (memtype == MEMTYPE_FLASH) { - if ((address & (twi->pagesize -1)) != 0x00) { - fprintf(stderr, "twi_write_memory(): address 0x%04x not aligned to pagesize 0x%02x\n", address, twi->pagesize); + + if (memtype == MEMTYPE_FLASH) + { + if ((address & (twi->pagesize -1)) != 0x00) + { + fprintf(stderr, "twi_write_memory(): address 0x%04x not aligned to pagesize 0x%02x\n", + address, twi->pagesize); + return -1; } - bufsize = 4 + twi->pagesize; - } else { + bufsize = 4 + twi->pagesize; + } + else + { bufsize = 4 + size; } uint8_t *cmd = malloc(bufsize); if (cmd == NULL) + { return -1; + } cmd[0] = CMD_WRITE_MEMORY; cmd[1] = memtype; @@ -140,7 +182,8 @@ static int twi_write_memory(struct twi_privdata *twi, uint8_t *buffer, uint8_t s cmd[3] = (address & 0xFF); memcpy(cmd +4, buffer, size); - if (memtype == MEMTYPE_FLASH) { + if (memtype == MEMTYPE_FLASH) + { memset(cmd +4 +size, 0xFF, twi->pagesize - size); } @@ -148,80 +191,118 @@ static int twi_write_memory(struct twi_privdata *twi, uint8_t *buffer, uint8_t s free(cmd); return (result != bufsize); -} +} /* twi_write_memory */ + +/* ************************************************************************* + * twi_close_device + * ************************************************************************* */ static void twi_close_device(struct twi_privdata *twi) { if (twi->connected) + { close(twi->fd); + } twi->connected = 0; -} +} /* twi_close_device */ + +/* ************************************************************************* + * twi_open_device + * ************************************************************************* */ static int twi_open_device(struct twi_privdata *twi) { twi->fd = open(twi->device, O_RDWR); - if (twi->fd < 0) { - fprintf(stderr, "failed to open '%s': %s\n", twi->device, strerror(errno)); + if (twi->fd < 0) + { + fprintf(stderr, "failed to open '%s': %s\n", + twi->device, strerror(errno)); + return -1; } unsigned long funcs; - if (ioctl(twi->fd, I2C_FUNCS, &funcs)) { + if (ioctl(twi->fd, I2C_FUNCS, &funcs)) + { perror("ioctl(I2C_FUNCS)"); close(twi->fd); return -1; } - if (!(funcs & I2C_FUNC_I2C)) { - fprintf(stderr, "I2C_FUNC_I2C not supported on '%s'!\n", twi->device); + if (!(funcs & I2C_FUNC_I2C)) + { + fprintf(stderr, "I2C_FUNC_I2C not supported on '%s'!\n", + twi->device); + close(twi->fd); return -1; } - if (ioctl(twi->fd, I2C_SLAVE, twi->address) < 0) { - fprintf(stderr, "failed to select slave address '%d': %s\n", twi->address, strerror(errno)); + if (ioctl(twi->fd, I2C_SLAVE, twi->address) < 0) + { + fprintf(stderr, "failed to select slave address '%d': %s\n", + twi->address, strerror(errno)); + close(twi->fd); return -1; } twi->connected = 1; return 0; -} +} /* twi_open_device */ + +/* ************************************************************************* + * twi_close + * ************************************************************************* */ static int twi_close(struct multiboot *mboot) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; if (twi->connected) + { twi_switch_application(twi, BOOTTYPE_APPLICATION); + } twi_close_device(twi); return 0; -} +} /* twi_close */ + +/* ************************************************************************* + * twi_open + * ************************************************************************* */ static int twi_open(struct multiboot *mboot) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; - if (twi->address == 0) { + if (twi->address == 0) + { fprintf(stderr, "abort: no address given\n"); return -1; } - if (twi->device == NULL) { + if (twi->device == NULL) + { twi->device = strdup(TWI_DEFAULT_DEVICE); - if (twi->device == NULL) { + if (twi->device == NULL) + { perror("strdup()"); return -1; } } if (twi_open_device(twi) != 0) + { return -1; + } + + if (twi_switch_application(twi, BOOTTYPE_BOOTLOADER)) + { + fprintf(stderr, "failed to switch to bootloader (invalid address?): %s\n", + strerror(errno)); - if (twi_switch_application(twi, BOOTTYPE_BOOTLOADER)) { - fprintf(stderr, "failed to switch to bootloader (invalid address?): %s\n", strerror(errno)); twi_close(mboot); return -1; } @@ -230,14 +311,18 @@ static int twi_open(struct multiboot *mboot) usleep(100000); char version[16]; - if (twi_read_version(twi, version, sizeof(version))) { - fprintf(stderr, "failed to get bootloader version: %s\n", strerror(errno)); + if (twi_read_version(twi, version, sizeof(version))) + { + fprintf(stderr, "failed to get bootloader version: %s\n", + strerror(errno)); + twi_close(mboot); return -1; } uint8_t chipinfo[8]; - if (twi_read_memory(twi, chipinfo, sizeof(chipinfo), MEMTYPE_CHIPINFO, 0x0000)) { + if (twi_read_memory(twi, chipinfo, sizeof(chipinfo), MEMTYPE_CHIPINFO, 0x0000)) + { fprintf(stderr, "failed to get chipinfo: %s\n", strerror(errno)); twi_close(mboot); return -1; @@ -249,26 +334,43 @@ static int twi_open(struct multiboot *mboot) twi->flashsize = (chipinfo[4] << 8) + chipinfo[5]; twi->eepromsize = (chipinfo[6] << 8) + chipinfo[7]; - printf("device : %-16s (address: 0x%02X)\n", twi->device, twi->address); - printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); - printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", twi->flashsize, twi->flashsize, twi->pagesize); - printf("eeprom size : 0x%04x / %5d\n", twi->eepromsize, twi->eepromsize); + printf("device : %-16s (address: 0x%02X)\n", + twi->device, twi->address); + + printf("version : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n", + version, chipinfo[0], chipinfo[1], chipinfo[2], chipname); + + printf("flash size : 0x%04x / %5d (0x%02x bytes/page)\n", + twi->flashsize, twi->flashsize, twi->pagesize); + + printf("eeprom size : 0x%04x / %5d\n", + twi->eepromsize, twi->eepromsize); return 0; -} +} /* twi_open */ -static int twi_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) + +/* ************************************************************************* + * twi_read + * ************************************************************************* */ +static int twi_read(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) { 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; - while (pos < size) { + + while (pos < size) + { mboot->progress_cb(progress_msg, pos, size); int len = MIN(READ_BLOCK_SIZE, size - pos); - if (twi_read_memory(twi, dbuf->data + pos, len, memtype, pos)) { + + if (twi_read_memory(twi, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -280,21 +382,30 @@ static int twi_read(struct multiboot *mboot, struct databuf *dbuf, int memtype) mboot->progress_cb(progress_msg, pos, size); return 0; -} +} /* twi_read */ -static int twi_write(struct multiboot *mboot, struct databuf *dbuf, int memtype) + +/* ************************************************************************* + * twi_write + * ************************************************************************* */ +static int twi_write(struct multiboot *mboot, + struct databuf *dbuf, + int memtype) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; char *progress_msg = (memtype == MEMTYPE_FLASH) ? "writing flash" : "writing eeprom"; int pos = 0; - while (pos < dbuf->length) { + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int len = (memtype == MEMTYPE_FLASH) ? twi->pagesize : WRITE_BLOCK_SIZE; len = MIN(len, dbuf->length - pos); - if (twi_write_memory(twi, dbuf->data + pos, len, memtype, pos)) { + + if (twi_write_memory(twi, dbuf->data + pos, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } @@ -304,8 +415,12 @@ static int twi_write(struct multiboot *mboot, struct databuf *dbuf, int memtype) mboot->progress_cb(progress_msg, pos, dbuf->length); return 0; -} +} /* twi_write */ + +/* ************************************************************************* + * twi_verify + * ************************************************************************* */ static int twi_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; @@ -313,16 +428,20 @@ static int twi_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype int pos = 0; uint8_t comp[READ_BLOCK_SIZE]; - while (pos < dbuf->length) { + + while (pos < dbuf->length) + { mboot->progress_cb(progress_msg, pos, dbuf->length); int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); - if (twi_read_memory(twi, comp, len, memtype, pos)) { + if (twi_read_memory(twi, comp, len, memtype, pos)) + { mboot->progress_cb(progress_msg, -1, -1); return -1; } - if (memcmp(comp, dbuf->data + pos, len) != 0x00) { + if (memcmp(comp, dbuf->data + pos, len) != 0x00) + { mboot->progress_cb(progress_msg, -1, -1); fprintf(stderr, "verify failed at page 0x%04x!!\n", pos); return -1; @@ -335,71 +454,85 @@ static int twi_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype mboot->progress_cb(progress_msg, pos, dbuf->length); return 0; -} +} /* twi_verify */ + +/* ************************************************************************* + * twi_optarg_cb + * ************************************************************************* */ static int twi_optarg_cb(int val, const char *arg, void *privdata) { struct twi_privdata *twi = (struct twi_privdata *)privdata; - switch (val) { - case 'a': /* address */ - { - char *endptr; - twi->address = strtol(arg, &endptr, 16); - if (*endptr != '\0' || twi->address < 0x01 || twi->address > 0x7F) { - fprintf(stderr, "invalid address: '%s'\n", arg); - return -1; - } - } - break; + switch (val) + { + case 'a': /* address */ + { + char *endptr; - case 'd': /* device */ - { - if (twi->device != NULL) { + twi->address = strtol(arg, &endptr, 16); + if (*endptr != '\0' || twi->address < 0x01 || twi->address > 0x7F) + { + fprintf(stderr, "invalid address: '%s'\n", arg); + return -1; + } + } + break; + + case 'd': /* device */ + if (twi->device != NULL) + { fprintf(stderr, "invalid device: '%s'\n", optarg); return -1; } twi->device = strdup(optarg); - if (twi->device == NULL) { + if (twi->device == NULL) + { perror("strdup()"); return -1; } - } - break; + break; - case 'h': - case '?': /* error */ - fprintf(stderr, "Usage: twiboot [options]\n" - " -a
- selects i2c address (0x01 - 0x7F)\n" - " -d - selects i2c device (default: /dev/i2c-0)\n" - " -r : - reads flash/eeprom to file (.bin | .hex | -)\n" - " -w : - write flash/eeprom from file (.bin | .hex)\n" - " -n - disable verify after write\n" - " -p <0|1|2> - progress bar mode\n" - "\n" - "Example: twiboot -a 0x22 -w flash:blmc.hex -w flash:blmc_eeprom.hex\n" - "\n"); - return -1; + case 'h': + case '?': /* error */ + fprintf(stderr, "Usage: twiboot [options]\n" + " -a
- selects i2c address (0x01 - 0x7F)\n" + " -d - selects i2c device (default: /dev/i2c-0)\n" + " -r : - reads flash/eeprom to file (.bin | .hex | -)\n" + " -w : - write flash/eeprom from file (.bin | .hex)\n" + " -n - disable verify after write\n" + " -p <0|1|2> - progress bar mode\n" + "\n" + "Example: twiboot -a 0x22 -w flash:blmc.hex -w flash:blmc_eeprom.hex\n" + "\n"); + return -1; - default: - return 1; + default: + return 1; } return 0; -} +} /* twi_optarg_cb */ + +/* ************************************************************************* + * twi_alloc + * ************************************************************************* */ static struct multiboot * twi_alloc(void) { struct multiboot * mboot = malloc(sizeof(struct multiboot)); if (mboot == NULL) + { return NULL; + } memset(mboot, 0x00, sizeof(struct multiboot)); mboot->ops = &twi_ops; struct twi_privdata *twi = malloc(sizeof(struct twi_privdata)); - if (twi == NULL) { + if (twi == NULL) + { free(mboot); return NULL; } @@ -412,50 +545,74 @@ static struct multiboot * twi_alloc(void) mboot->privdata = twi; return mboot; -} +} /* twi_alloc */ + +/* ************************************************************************* + * twi_free + * ************************************************************************* */ static void twi_free(struct multiboot *mboot) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; if (twi->device != NULL) + { free(twi->device); + } free(twi); free(mboot); -} +} /* twi_free */ -static int twi_get_memtype(struct multiboot *mboot, const char *memname) + +/* ************************************************************************* + * twi_get_memtype + * ************************************************************************* */ +static int twi_get_memtype(struct multiboot *mboot, + const char *memname) { if (strcmp(memname, "flash") == 0) + { return MEMTYPE_FLASH; - + } else if (strcmp(memname, "eeprom") == 0) + { return MEMTYPE_EEPROM; + } return -1; -} +} /* twi_get_memtype */ -static int twi_get_memsize(struct multiboot *mboot, int memtype) + +/* ************************************************************************* + * twi_get_memsize + * ************************************************************************* */ +static int twi_get_memsize(struct multiboot *mboot, + int memtype) { struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; if (!twi->connected) - return 0; - - switch (memtype) { - case MEMTYPE_FLASH: - return twi->flashsize; - - case MEMTYPE_EEPROM: - return twi->eepromsize; - - default: + { return 0; } -} -struct multiboot_ops twi_ops = { + switch (memtype) + { + case MEMTYPE_FLASH: + return twi->flashsize; + + case MEMTYPE_EEPROM: + return twi->eepromsize; + + default: + return 0; + } +} /* twi_get_memsize */ + + +struct multiboot_ops twi_ops = +{ .alloc = twi_alloc, .free = twi_free, .get_memtype = twi_get_memtype,