diff --git a/linux/.gitignore b/linux/.gitignore deleted file mode 100644 index 3e26448..0000000 --- a/linux/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.o -*.d -twiboot diff --git a/linux/Makefile b/linux/Makefile deleted file mode 100644 index 718f5fa..0000000 --- a/linux/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -TARGET = twiboot -TARGET2 = mpmboot - -CFLAGS = -Wall -Wno-unused-result -O2 -MMD -MP -MF $(*F).d - -# ------ - -SRC := $(wildcard *.c) - -all: $(TARGET) - -$(TARGET): $(SRC:.c=.o) - @echo " Linking file: $@" - @$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) > /dev/null - @ln -sf $@ $(TARGET2) - -%.o: %.c - @echo " Building file: $<" - @$(CC) -c $(CFLAGS) $< -o $@ - -clean: - rm -rf $(TARGET) $(TARGET2) *.o *.d - --include $(shell find . -name \*.d 2> /dev/null) diff --git a/linux/chipinfo_avr.c b/linux/chipinfo_avr.c deleted file mode 100644 index 8d84ace..0000000 --- a/linux/chipinfo_avr.c +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** -* Copyright (C) 10/2010 by Olaf Rempel * -* razzor@kopf-tisch.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; version 2 of the License, * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include -#include -#include -#include - -#include - -#include "chipinfo_avr.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -struct chipinfo { - uint8_t sig[3]; - const char name[16]; -}; - -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" }, -}; - -const char * chipinfo_get_avr_name(const uint8_t *sig) -{ - int 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"; -} diff --git a/linux/chipinfo_avr.h b/linux/chipinfo_avr.h deleted file mode 100644 index aebdda2..0000000 --- a/linux/chipinfo_avr.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _CHIPINFO_H_ -#define _CHIPINFO_H_ - -#include - -const char * chipinfo_get_avr_name(const uint8_t *sig); - -#endif /* _CHIPINFO_H_ */ diff --git a/linux/filedata.c b/linux/filedata.c deleted file mode 100644 index 9d9de03..0000000 --- a/linux/filedata.c +++ /dev/null @@ -1,423 +0,0 @@ -/*************************************************************************** -* Copyright (C) 10/2010 by Olaf Rempel * -* razzor@kopf-tisch.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; version 2 of the License, * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include -#include -#include -#include - -#include -#include -#include - -#include "filedata.h" - -#define FILETYPE_UNKNOWN 0 -#define FILETYPE_BINARY 1 -#define FILETYPE_INTELHEX 2 - -struct databuf * dbuf_alloc(uint32_t size) -{ - struct databuf *dbuf = malloc(sizeof(struct databuf) + size); - if (dbuf == NULL) { - perror("dbuf_alloc"); - return NULL; - } - - memset(dbuf->data, 0xFF, size); - dbuf->size = size; - dbuf->length = 0; - return dbuf; -} - -void dbuf_free(struct databuf *dbuf) -{ - free(dbuf); -} - -static void dbuf_dump(struct databuf *dbuf) -{ - int pos = 0, oldskip = 0; - - while (pos < dbuf->length) { - char buf[128]; - int j, i = 0; - - int skip = 1; - for (j = 0; j < 16; j++) { - if (pos + j < dbuf->length) - i += sprintf(buf + i, "%02X", dbuf->data[pos + j]); - 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) { - buf[i++] = '\0'; - printf("%04X: %s\r\n", pos, buf); - oldskip = 0; - - } else if (skip == 1 && oldskip == 0) { - printf("****\n"); - oldskip = 1; - } - - pos += 16; - } -} - -static int binfile_getsize(const char *filename, uint32_t *size) -{ - int fd = open(filename, O_RDONLY); - if (fd < 0) { - perror("binfile_getsize(): open()"); - return -1; - } - - struct stat filestat; - if (fstat(fd, &filestat) < 0) { - perror("binfile_getsize(): fstat()"); - close(fd); - return -1; - } - - *size = filestat.st_size; - - close(fd); - return 0; -} - -static int binfile_read(const char *filename, struct databuf *dbuf) -{ - int fd = open(filename, O_RDONLY); - if (fd < 0) { - perror("binfile_read(): open()"); - return -1; - } - - ssize_t readsize = read(fd, dbuf->data, dbuf->size); - if (readsize <= 0) { - perror("binfile_read(): read()"); - close(fd); - return -1; - } - - dbuf->length = readsize; - - close(fd); - return 0; -} - -static int binfile_write(const char *filename, struct databuf *dbuf) -{ - int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (fd < 0) { - perror("binfile_write(): open()"); - return -1; - } - - ssize_t writesize = write(fd, dbuf->data, dbuf->length); - if (writesize != dbuf->length) { - perror("binfile_write(): write()"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - -struct ihex_record { - uint8_t byte_count; - uint16_t address; - uint8_t type; - - uint8_t *data; - uint8_t chksum; -}; - -static uint8_t hex2byte(const char *ptr) -{ - int i; - uint8_t result = 0; - - 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); - } - - return result; -} - -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)) { - perror("hexfile_getrecord(): getline()"); - } - return -1; - } - - if (length < 12) { - fprintf(stderr, "record too short (%d)\n", length); - free(hexline); - return -1; - } - - int pos = 0; - if (hexline[pos] != ':') { - fprintf(stderr, "invalid startcode\n"); - free(hexline); - return -1; - } - pos++; - - uint8_t chksum = 0x00; - - record->byte_count = hex2byte(&hexline[pos]); - chksum += record->byte_count; - pos += 2; - - if (record->byte_count > 0) { - record->data = malloc(record->byte_count); - if (record->data == NULL) { - perror("hexfile_getrecord(): malloc()"); - free(hexline); - return -1; - } - } - - uint8_t hiaddr = hex2byte(&hexline[pos]); - uint8_t loaddr = hex2byte(&hexline[pos +2]); - record->address = (hiaddr << 8) + loaddr; - chksum += hiaddr + loaddr; - pos += 4; - - record->type = hex2byte(&hexline[pos]); - chksum += record->type; - pos += 2; - - int i; - for (i = 0; i < record->byte_count; i++) { - record->data[i] = hex2byte(&hexline[pos]); - chksum += record->data[i]; - pos += 2; - } - - record->chksum = hex2byte(&hexline[pos]); - chksum += record->chksum; - pos += 2; - - 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; -} - -static int hexfile_putrecord(FILE *stream, struct ihex_record *record) -{ - uint8_t chksum = record->byte_count; - chksum += (record->address >> 8) & 0xFF; - chksum += (record->address & 0xFF); - chksum += record->type; - - int i, len = 0; - char buf[64]; - - buf[0] = '\0'; - 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; -} - -static int hexfile_getsize(const char *filename, uint32_t *size) -{ - *size = 0x10000; - return 0; -} - -static int hexfile_read(const char *filename, struct databuf *dbuf) -{ - FILE *stream = fopen(filename, "r"); - if (stream == NULL) { - perror("hexfile_read(): fopen()"); - return -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) { - fprintf(stderr, "hexfile_read(): data out of bounds\n"); - break; - } - - memcpy(&dbuf->data[record.address], record.data, record.byte_count); - dbuf->length = record.address + record.byte_count; - } - } - - fclose(stream); - return 0; -} - -static int hexfile_write(const char *filename, struct databuf *dbuf) -{ - FILE *stream = fopen(filename, "w"); - if (stream == NULL) { - perror("hexfile_write(): fopen()"); - return -1; - } - - int i; - int addr_min = dbuf->length; - int addr_max = 0; - 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) { - record.byte_count = 0x10; - record.address = i; - record.type = 0x00; - record.data = &dbuf->data[i]; - - hexfile_putrecord(stream, &record); - } - - record.byte_count = 0x00; - record.address = addr_min; - record.type = 0x01; - record.data = NULL; - hexfile_putrecord(stream, &record); - - fclose(stream); - return 0; -} - -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; -} - -int file_getsize(const char *filename, uint32_t *size) -{ - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_getsize(filename, size); - - case FILETYPE_INTELHEX: - return hexfile_getsize(filename, size); - - default: - return -1; - } -} - -int file_read(const char *filename, struct databuf *dbuf) -{ - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_read(filename, dbuf); - - case FILETYPE_INTELHEX: - return hexfile_read(filename, dbuf); - - default: - return -1; - } -} - -int file_write(const char *filename, struct databuf *dbuf) -{ - if (strncmp(filename, "-", 1) == 0) { - dbuf_dump(dbuf); - return 0; - } - - switch (get_filetype(filename)) { - case FILETYPE_BINARY: - return binfile_write(filename, dbuf); - - case FILETYPE_INTELHEX: - return hexfile_write(filename, dbuf); - - default: - return -1; - } -} diff --git a/linux/filedata.h b/linux/filedata.h deleted file mode 100644 index 4a32ee1..0000000 --- a/linux/filedata.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _FILEDATA_H_ -#define _FILEDATA_H_ - -#include - -struct databuf { - uint32_t size; // allocation size - uint32_t length; // used size - uint8_t data[0]; -}; - -struct databuf * dbuf_alloc(uint32_t size); -void dbuf_free(struct databuf *dbuf); - -int file_getsize(const char *filename, uint32_t *size); -int file_read(const char *filename, struct databuf *dbuf); -int file_write(const char *filename, struct databuf *dbuf); - -#endif /* _FILEDATA_H_ */ diff --git a/linux/list.h b/linux/list.h deleted file mode 100644 index 61f8d93..0000000 --- a/linux/list.h +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef _LIST_H_ -#define _LIST_H_ - -/* - * stolen from linux kernel 2.6.11 (http://kernel.org/) - * linux/include/linux/stddef.h (offsetoff) - * linux/include/linux/kernel.h (container_of) - * linux/include/linux/list.h (*list*) - * linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND) - * - * modified by Olaf Rempel - */ -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/* - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/* - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/* - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = NULL; - entry->prev = NULL; -} - -/* - * list_del_init - deletes entry from list and reinitialize it. - * entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/* - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/* - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/* - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/* - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/* - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/* - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/* - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/* - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) - -/* - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/* - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/* - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member)) - -/* - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - - -/* Return pointer to first true entry, if any, or NULL. A macro - required to allow inlining of cmpfn. */ -#define LIST_FIND(head, cmpfn, type, args...) \ -({ \ - const struct list_head *__i, *__j = NULL; \ - \ - list_for_each(__i, (head)) \ - if (cmpfn((const type)__i , ## args)) { \ - __j = __i; \ - break; \ - } \ - (type)__j; \ -}) - -#endif /* _LIST_H_ */ diff --git a/linux/mpm.c b/linux/mpm.c deleted file mode 100644 index e71a003..0000000 --- a/linux/mpm.c +++ /dev/null @@ -1,635 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "chipinfo_avr.h" -#include "multiboot.h" -#include "optarg.h" - -#define READ_BLOCK_SIZE 256 /* bytes in one flash/eeprom read request */ -#define WRITE_BLOCK_SIZE 16 /* bytes in one eeprom write request */ - -#define CMD_SWITCH_APPLICATION 0x01 -#define CMD_GET_BOOTLOADER_VERSION 0x02 -#define CMD_GET_CHIP_INFO 0x03 -#define CMD_READ_MEMORY 0x11 -#define CMD_WRITE_MEMORY 0x12 - -#define CAUSE_SUCCESS 0x00 -#define CAUSE_COMMAND_NOT_SUPPORTED 0xF0 -#define CAUSE_INVALID_PARAMETER 0xF1 -#define CAUSE_UNSPECIFIED_ERROR 0xFF - -/* CMD_SWITCH_APPLICATION parameter */ -#define BOOTTYPE_BOOTLOADER 0x00 -#define BOOTTYPE_APPLICATION 0x80 - -#define MEMTYPE_FLASH 0x01 -#define MEMTYPE_EEPROM 0x02 - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -struct multiboot_ops mpm_ops; - -struct mpm_privdata { - char *device; - int fd; - int connected; - - int address; - - int flashsize; - int flashpage; - int eepromsize; - - struct termios oldtio; -}; - -static struct option mpm_optargs[] = { - {"address", 1, 0, 'a'}, /* -a */ - {"device", 1, 0, 'd'}, /* [ -d ] */ -}; - -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; - - case 'd': /* device */ - { - if (mpm->device != NULL) { - fprintf(stderr, "invalid device: '%s'\n", optarg); - return -1; - } - - mpm->device = strdup(optarg); - if (mpm->device == NULL) { - perror("strdup()"); - return -1; - } - } - break; - - case 'h': - case '?': /* error */ - fprintf(stderr, "Usage: mpmboot [options]\n" - " -a
- selects mpm address (0x01 - 0xFF)\n" - " -d - selects mpm device\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: mpmboot -d /dev/ttyUSB0 -a 0x22 -w flash:blmc.hex -w flash:blmc_eeprom.hex\n" - "\n"); - return -1; - - default: - return 1; - } - - return 0; -} - -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) { - free(mboot); - return NULL; - } - - memset(mpm, 0x00, sizeof(struct mpm_privdata)); - mpm->device = NULL; - mpm->address = 0; - - optarg_register(mpm_optargs, ARRAY_SIZE(mpm_optargs), mpm_optarg_cb, (void *)mpm); - - mboot->privdata = mpm; - return mboot; -} - -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); -} - -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; -} - -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) -{ - struct termios tio; - - if (tcgetattr(mpm->fd, &tio) < 0) { - perror("tcgetattr(tio)"); - return -1; - } - - tio.c_cflag |= PARODD; - - if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) { - perror("tcsetattr(tio)"); - return -1; - } - -// usleep(5000); - - uint8_t address = mpm->address; - if (write(mpm->fd, &address, sizeof(address)) != sizeof(address)) { - perror("write(address)"); - return -1; - } - - usleep(500); - - tio.c_cflag &= ~(PARODD); - - if (tcsetattr(mpm->fd, TCSAFLUSH, &tio) < 0) { - perror("tcsetattr(tio)"); - return -1; - } - - uint8_t header[3]; - header[0] = command; - header[1] = (length >> 8) & 0xFF; - header[2] = length & 0xFF; - - 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) { - perror("write(data)"); - return -1; - } - } - - return 0; -} - -static int myread(int fd, void *data, int size) -{ - int pos = 0; - - while (1) { - fd_set fdset; - struct timeval timeout = { .tv_sec = 1, .tv_usec = 0 }; - - FD_ZERO(&fdset); - FD_SET(fd, &fdset); - - int ret = select(fd +1, &fdset, NULL, NULL, &timeout); - if (ret == -1) { - perror("select"); - return -1; - - } else if (ret == 0) { - break; - - } else if (FD_ISSET(fd, &fdset)) { - int len = read(fd, data + pos, size - pos); - if (len < 0) { - return -1; - - } else { - pos += len; - if (pos == size) { - break; - } - } - } - } - - return pos; -} - -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)) { - fprintf(stderr, "short read() from device (not addressed?)\n"); - return -1; - } - - if (header[0] != command) { - fprintf(stderr, "invalid command response (0x%02x != 0x%02x)\n", header[0], command); - return -1; - } - - *cause = header[1]; - - uint16_t length = (header[2] << 8) | header[3]; -// printf("mpm_recv() cmd=0x%02x cause=0x%02x length=0x%04x\n", command, *cause, length); - - uint16_t bufferpos = 0; - while (length > 0) { - - /* free space in output buffer? */ - if ((bufferpos < buffersize) && (buffer != NULL)) { - - uint16_t size = MIN(buffersize - bufferpos, length); - len = myread(mpm->fd, buffer + bufferpos, size); - if (len <= 0) { - fprintf(stderr, "short read() from device (%d != %d)\n", len, size); - return -1; - } - bufferpos += len; - length -= len; - - } 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) { - fprintf(stderr, "short read() from device (%d != %d)\n", len, size); - return -1; - } - length -= len; - } - } - - return bufferpos; -} - -static void mpm_close_device(struct mpm_privdata *mpm) -{ - /* delay close() / tcsetattr() */ - usleep(100000); - - tcsetattr(mpm->fd, TCSANOW, &mpm->oldtio); - close(mpm->fd); -} - -static int mpm_open_device(struct mpm_privdata *mpm) -{ - mpm->fd = open(mpm->device, O_RDWR | O_NOCTTY | O_CLOEXEC); - if (mpm->fd < 0) { - perror("open()"); - return -1; - } - - if (tcgetattr(mpm->fd, &mpm->oldtio) < 0) { - perror("tcgetattr(oldtio)"); - close(mpm->fd); - return -1; - } - - struct termios newtio; - memset(&newtio, 0, sizeof(newtio)); - - newtio.c_iflag |= IGNBRK; - newtio.c_cflag |= B115200 | CS8 | CLOCAL | CREAD | PARENB | CMSPAR; - - newtio.c_cc[VMIN] = 1; - newtio.c_cc[VTIME] = 0; - - int err = tcsetattr(mpm->fd, TCSANOW, &newtio); - if (err < 0) { - perror("tcsetattr(newtio)"); - close(mpm->fd); - return -1; - } - - mpm->connected = 1; - return 0; -} - -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); -} - -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) -{ - 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); -} - -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, - (address >> 8) & 0xFF, - (address & 0xFF), - (size >> 8) & 0xFF, - (size & 0xFF) - }; - - 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); -} - -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) { - 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 { - bufsize = 5 + size; - } - - uint8_t *cmd = malloc(bufsize); - if (cmd == NULL) - return -1; - - cmd[0] = memtype; - cmd[1] = (address >> 8) & 0xFF; - cmd[2] = (address & 0xFF); - cmd[3] = ((bufsize -5) >> 8) & 0xFF; - cmd[4] = ((bufsize -5) & 0xFF); - memcpy(cmd +5, buffer, size); - - 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); -} - -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; -} - -static int mpm_open(struct multiboot *mboot) -{ - struct mpm_privdata *mpm = (struct mpm_privdata *)mboot->privdata; - - if (mpm->address == 0) { - fprintf(stderr, "abort: no address given\n"); - return -1; - } - - 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)) { - fprintf(stderr, "failed to switch to bootloader (invalid address?)\n"); - mpm_close(mboot); - return -1; - } - - /* wait for watchdog and startup time */ - usleep(100000); - - char version[16]; - if (mpm_read_version(mpm, (uint8_t *)version, sizeof(version))) { - fprintf(stderr, "failed to get bootloader version"); - mpm_close(mboot); - return -1; - } - - uint8_t chipinfo[8]; - if (mpm_read_chipinfo(mpm, chipinfo, sizeof(chipinfo))) { - fprintf(stderr, "failed to get bootloader version"); - mpm_close(mboot); - return -1; - } - - const char *chipname = chipinfo_get_avr_name(chipinfo); - - mpm->flashpage = chipinfo[3]; - 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); - - return 0; -} - -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) { - 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)) { - mboot->progress_cb(progress_msg, -1, -1); - return -1; - } - - pos += len; - } - - dbuf->length = pos; - - mboot->progress_cb(progress_msg, pos, size); - return 0; -} - -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) { - 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)) { - mboot->progress_cb(progress_msg, -1, -1); - return -1; - } - - pos += len; - } - - mboot->progress_cb(progress_msg, pos, dbuf->length); - return 0; -} - -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) { - 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)) { - mboot->progress_cb(progress_msg, -1, -1); - return -1; - } - - if (memcmp(comp, dbuf->data + pos, len) != 0x00) { - mboot->progress_cb(progress_msg, -1, -1); - fprintf(stderr, "verify failed at page 0x%04x!!\n", pos); - return -1; - } - - pos += len; - } - - dbuf->length = pos; - - mboot->progress_cb(progress_msg, pos, dbuf->length); - return 0; -} - -struct multiboot_ops mpm_ops = { - .alloc = mpm_alloc, - .free = mpm_free, - .get_memtype = mpm_get_memtype, - .get_memsize = mpm_get_memsize, - - .open = mpm_open, - .close = mpm_close, - .read = mpm_read, - .write = mpm_write, - .verify = mpm_verify, -}; diff --git a/linux/multiboot.c b/linux/multiboot.c deleted file mode 100644 index 3fb88b9..0000000 --- a/linux/multiboot.c +++ /dev/null @@ -1,320 +0,0 @@ -/*************************************************************************** -* Copyright (C) 10/2010 by Olaf Rempel * -* razzor@kopf-tisch.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; version 2 of the License, * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include -#include -#include -#include - -#include - -#include "filedata.h" -#include "list.h" -#include "multiboot.h" -#include "optarg.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -#define ACTION_READ 0x01 -#define ACTION_WRITE 0x02 - -struct mboot_action { - struct list_head list; - - char *filename; - int memtype; - int mode; -}; - -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 void progress_mode0_cb(const char *msg, int pos, int size) -{ - /* no progress output */ -} - -static void progress_mode1_cb(const char *msg, int pos, int size) -{ - 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"); -} - -static void progress_mode2_cb(const char *msg, int pos, int size) -{ - static int old_count; - - if (pos != -1 && size != -1) { - if (pos == 0) { - old_count = 0; - printf("%-15s: [", msg); - - } 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) { - printf("] (%d)\n", pos); - } - } - } -} - -static int add_action(struct multiboot *mboot, int mode, const char *arg) -{ - struct mboot_action *action = malloc(sizeof(struct mboot_action)); - if (action == NULL) { - perror("malloc()"); - return -1; - } - - char *argcopy = strdup(arg); - if (argcopy == NULL) { - perror("strdup()"); - free(action); - return -1; - } - - char *tok = strtok(argcopy, ":"); - if (tok == NULL) { - fprintf(stderr, "invalid argument: '%s'\n", arg); - free(argcopy); - free(action); - return -1; - } - - action->memtype = mboot->ops->get_memtype(mboot, tok); - if (action->memtype == -1) { - fprintf(stderr, "invalid memtype: '%s'\n", tok); - free(argcopy); - free(action); - return -1; - } - - tok = strtok(NULL, ":"); - if (tok == NULL) { - fprintf(stderr, "invalid argument: '%s'\n", arg); - free(argcopy); - free(action); - return -1; - } - - action->filename = strdup(tok); - if (action->filename == NULL) { - perror("strdup()"); - free(argcopy); - free(action); - return -1; - } - - action->mode = mode; - - list_add_tail(&action->list, &action_list); - free(argcopy); - return 0; -} - -static int main_optarg_cb(int val, const char *arg, void *privdata) -{ - struct multiboot *mboot = (struct multiboot *)privdata; - - 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; - } - - return 0; -} - -int main(int argc, char *argv[]) -{ - struct multiboot *mboot; - - char *progname = strrchr(argv[0], '/'); - progname = (progname != NULL) ? (progname +1) : argv[0]; - - if (strcmp(progname, "twiboot") == 0) { - mboot = twi_ops.alloc(); - } else if (strcmp(progname, "mpmboot") == 0) { - mboot = mpm_ops.alloc(); - } else { - fprintf(stderr, "invalid progname, use 'twiboot' or 'mpmboot'\n"); - return -1; - } - - if (mboot == NULL) - return -1; - - mboot->verify = 1; - mboot->progress_cb = progress_mode1_cb; - - 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) - return -1; - - setbuf(stdout, NULL); - - struct mboot_action *action, *tmp; - list_for_each_entry(action, &action_list, list) { - abort = 1; - 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) { - fprintf(stderr, "failed to read from device\n"); - dbuf_free(dbuf); - break; - } - - result = file_write(action->filename, dbuf); - if (result != 0) { - fprintf(stderr, "failed to write file '%s'\n", action->filename); - dbuf_free(dbuf); - break; - } - - dbuf_free(dbuf); - abort = 0; - - } 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) { - 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) { - 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) { - fprintf(stderr, "failed to write to device\n"); - dbuf_free(dbuf); - break; - } - - if (mboot->verify) { - result = mboot->ops->verify(mboot, dbuf, action->memtype); - if (result != 0) { - fprintf(stderr, "failed to verify\n"); - dbuf_free(dbuf); - break; - } - } - - dbuf_free(dbuf); - abort = 0; - } - } - - list_for_each_entry_safe(action, tmp, &action_list, list) { - free(action->filename); - free(action); - } - - mboot->ops->close(mboot); - mboot->ops->free(mboot); - - optarg_free(); - return abort; -} diff --git a/linux/multiboot.h b/linux/multiboot.h deleted file mode 100644 index fea08e7..0000000 --- a/linux/multiboot.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _MULTIBOOT_H_ -#define _MULTIBOOT_H_ - -#include -#include "filedata.h" - -struct multiboot { - struct multiboot_ops *ops; - void *privdata; - - int verify; - void (* progress_cb)(const char *msg, int pos, int max); -}; - -struct multiboot_ops { - struct multiboot * (* alloc)(void); - void (* free)(struct multiboot *mboot); - - int (* get_memtype)(struct multiboot *mboot, const char *memname); - int (* get_memsize)(struct multiboot *mboot, int memtype); - - int (* open)(struct multiboot *mboot); - int (* close)(struct multiboot *mboot); - - int (* read)(struct multiboot *mboot, struct databuf *dbuf, int memtype); - int (* verify)(struct multiboot *mboot, struct databuf *dbuf, int memtype); - int (* write)(struct multiboot *mboot, struct databuf *dbuf, int memtype); -}; - -extern struct multiboot_ops twi_ops; -extern struct multiboot_ops mpm_ops; - -#endif /* _MULTIBOOT_H_ */ diff --git a/linux/optarg.c b/linux/optarg.c deleted file mode 100644 index c452b98..0000000 --- a/linux/optarg.c +++ /dev/null @@ -1,193 +0,0 @@ -/*************************************************************************** -* Copyright (C) 10/2010 by Olaf Rempel * -* razzor@kopf-tisch.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; version 2 of the License, * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include -#include -#include -#include - -#include - -#include "list.h" -#include "optarg.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -struct optarg_entry { - struct list_head list; - const struct option *opts; - int count; - - int (* parser_cb)(int val, const char *arg, void *privdata); - void *privdata; -}; - -static LIST_HEAD(option_list); - -int optarg_register(const struct option *opts, int count, - int (* parser_cb)(int val, const char *arg, void *privdata), - void *privdata) -{ - struct optarg_entry *entry; - - entry = malloc(sizeof(struct optarg_entry)); - if (entry == NULL) - return -1; - - entry->opts = opts; /* TODO: copy? */ - entry->count = count; - entry->parser_cb = parser_cb; - entry->privdata = privdata; - - list_add_tail(&entry->list, &option_list); - return 0; -} - -void optarg_free(void) -{ - struct optarg_entry *entry, *entry_tmp; - - list_for_each_entry_safe(entry, entry_tmp, &option_list, list) { - list_del(&entry->list); - free(entry); - } -} - -static void optarg_getsize(int *opt_count, int *optstring_len) -{ - int count = 0; - int length = 0; - - struct optarg_entry *entry; - - 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) { - case 0: /* no arguments */ - case 1: /* has argument */ - case 2: /* optional argument */ - length += entry->opts[i].has_arg +1; - break; - default: - break; - } - } - } - - *opt_count = count +1; - *optstring_len = length +1; -} - -static void optarg_copy(struct option *opts, char *optstring) -{ - struct optarg_entry *entry; - - 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) { - case 0: /* no arguments */ - *optstring++ = (char)entry->opts[i].val; - break; - - case 1: /* has argument */ - *optstring++ = (char)entry->opts[i].val; - *optstring++ = ':'; - break; - - case 2: /* optional argument */ - *optstring++ = (char)entry->opts[i].val; - *optstring++ = ':'; - *optstring++ = ':'; - break; - - default: - break; - } - } - } - - memset(opts++, 0x00, sizeof(struct option)); - *optstring++ = '\0'; -} - -int optarg_parse(int argc, char * const argv[]) -{ - struct option *longopts; - char *optstring; - - int opt_count; - int optstring_len; - optarg_getsize(&opt_count, &optstring_len); - - longopts = malloc(sizeof(struct option) * opt_count); - if (longopts == NULL) - return -1; - - optstring = malloc(optstring_len); - if (optstring == NULL) { - free(longopts); - return -1; - } - - optarg_copy(longopts, optstring); - - int retval = 0; - int val = 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) */ - continue; - - struct optarg_entry *entry; - list_for_each_entry(entry, &option_list, list) { - int ret = entry->parser_cb(val, optarg, entry->privdata); - - /* option recognized, with error */ - if (ret < 0) { - retval = ret; - break; - - /* option recognized, no error */ - } else if (ret == 0) { - break; - } - } - - if (val == -1) /* parsing completed */ - break; - - if (val == '?') { /* parsing error */ - retval = 1; - break; - } - } - - free(optstring); - free(longopts); - - return retval; -} diff --git a/linux/optarg.h b/linux/optarg.h deleted file mode 100644 index 4249d81..0000000 --- a/linux/optarg.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _OPTARG_H_ -#define _OPTARG_H_ - -#include - -int optarg_register(const struct option *opts, int count, - int (* parser_cb)(int val, const char *arg, void *privdata), - void *privdata); - - -void optarg_free(void); - -int optarg_parse(int argc, char * const argv[]); - -#endif /* _OPTARG_H_ */ diff --git a/linux/twi.c b/linux/twi.c deleted file mode 100644 index a0589b0..0000000 --- a/linux/twi.c +++ /dev/null @@ -1,469 +0,0 @@ -/*************************************************************************** -* Copyright (C) 10/2010 by Olaf Rempel * -* razzor@kopf-tisch.de * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; version 2 of the License, * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "chipinfo_avr.h" -#include "filedata.h" -#include "list.h" -#include "multiboot.h" -#include "optarg.h" - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - -#define TWI_DEFAULT_DEVICE "/dev/i2c-0" - -#define READ_BLOCK_SIZE 128 /* bytes in one flash/eeprom read request */ -#define WRITE_BLOCK_SIZE 16 /* bytes in one eeprom write request */ - -/* SLA+R */ -#define CMD_WAIT 0x00 -#define CMD_READ_VERSION 0x01 -#define CMD_READ_MEMORY 0x02 - -/* SLA+W */ -#define CMD_SWITCH_APPLICATION CMD_READ_VERSION -#define CMD_WRITE_MEMORY CMD_READ_MEMORY - -/* CMD_SWITCH_APPLICATION parameter */ -#define BOOTTYPE_BOOTLOADER 0x00 /* only in APP */ -#define BOOTTYPE_APPLICATION 0x80 - -/* CMD_{READ|WRITE}_* parameter */ -#define MEMTYPE_CHIPINFO 0x00 -#define MEMTYPE_FLASH 0x01 -#define MEMTYPE_EEPROM 0x02 -#define MEMTYPE_PARAMETERS 0x03 /* only in APP */ - -struct multiboot_ops twi_ops; - -struct twi_privdata { - char *device; - uint8_t address; - int fd; - int connected; - - uint8_t pagesize; - uint16_t flashsize; - uint16_t eepromsize; -}; - -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) -{ - uint8_t cmd[] = { CMD_SWITCH_APPLICATION, application }; - - return (write(twi->fd, cmd, sizeof(cmd)) != sizeof(cmd)); -} - -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; -} - -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); -} - -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); - return -1; - } - 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; - cmd[2] = (address >> 8) & 0xFF; - cmd[3] = (address & 0xFF); - memcpy(cmd +4, buffer, size); - - if (memtype == MEMTYPE_FLASH) { - memset(cmd +4 +size, 0xFF, twi->pagesize - size); - } - - int result = write(twi->fd, cmd, bufsize); - free(cmd); - - return (result != bufsize); -} - -static void twi_close_device(struct twi_privdata *twi) -{ - if (twi->connected) - close(twi->fd); - - twi->connected = 0; -} - -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)); - return -1; - } - - unsigned long 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); - 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)); - close(twi->fd); - return -1; - } - - twi->connected = 1; - return 0; -} - -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; -} - -static int twi_open(struct multiboot *mboot) -{ - struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; - - if (twi->address == 0) { - fprintf(stderr, "abort: no address given\n"); - return -1; - } - - if (twi->device == NULL) { - twi->device = strdup(TWI_DEFAULT_DEVICE); - 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)); - twi_close(mboot); - return -1; - } - - /* wait for watchdog and startup time */ - usleep(100000); - - char version[16]; - 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)) { - fprintf(stderr, "failed to get chipinfo: %s\n", strerror(errno)); - twi_close(mboot); - return -1; - } - - const char *chipname = chipinfo_get_avr_name(chipinfo); - - twi->pagesize = chipinfo[3]; - 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); - - return 0; -} - -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) { - 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)) { - mboot->progress_cb(progress_msg, -1, -1); - return -1; - } - - pos += len; - } - - dbuf->length = pos; - - mboot->progress_cb(progress_msg, pos, size); - return 0; -} - -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) { - 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)) { - mboot->progress_cb(progress_msg, -1, -1); - return -1; - } - - pos += len; - } - - mboot->progress_cb(progress_msg, pos, dbuf->length); - return 0; -} - -static int twi_verify(struct multiboot *mboot, struct databuf *dbuf, int memtype) -{ - struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata; - char *progress_msg = (memtype == MEMTYPE_FLASH) ? "verifing flash" : "verifing eeprom"; - - int pos = 0; - uint8_t comp[READ_BLOCK_SIZE]; - while (pos < dbuf->length) { - mboot->progress_cb(progress_msg, pos, dbuf->length); - - int len = MIN(READ_BLOCK_SIZE, dbuf->length - pos); - 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) { - mboot->progress_cb(progress_msg, -1, -1); - fprintf(stderr, "verify failed at page 0x%04x!!\n", pos); - return -1; - } - - pos += len; - } - - dbuf->length = pos; - - mboot->progress_cb(progress_msg, pos, dbuf->length); - return 0; -} - -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; - - case 'd': /* device */ - { - if (twi->device != NULL) { - fprintf(stderr, "invalid device: '%s'\n", optarg); - return -1; - } - - twi->device = strdup(optarg); - if (twi->device == NULL) { - perror("strdup()"); - return -1; - } - } - 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; - - default: - return 1; - } - - return 0; -} - -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) { - free(mboot); - return NULL; - } - - memset(twi, 0x00, sizeof(struct twi_privdata)); - twi->device = NULL; - twi->address = 0; - - optarg_register(twi_optargs, ARRAY_SIZE(twi_optargs), twi_optarg_cb, (void *)twi); - - mboot->privdata = twi; - return mboot; -} - -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); -} - -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; -} - -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 = { - .alloc = twi_alloc, - .free = twi_free, - .get_memtype = twi_get_memtype, - .get_memsize = twi_get_memsize, - - .open = twi_open, - .close = twi_close, - .read = twi_read, - .write = twi_write, - .verify = twi_verify, -};