avrdude: use sections instead of offsets

This commit is contained in:
Vojtech Kral 2018-06-25 18:19:51 +02:00 committed by bubnikv
parent 987fc4c6df
commit 6b801f250a
5 changed files with 61 additions and 46 deletions

View file

@ -98,11 +98,11 @@ static int fileio_num(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size, char * filename, FILE * f, AVRMEM * mem, int size,
FILEFMT fmt); FILEFMT fmt);
static int fmt_autodetect(char * fname, size_t offset); static int fmt_autodetect(char * fname, unsigned section);
static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset) static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
{ {
FILE *file; FILE *file;
// On Windows we need to convert the filename to UTF-16 // On Windows we need to convert the filename to UTF-16
@ -118,16 +118,38 @@ static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offse
file = fopen(filename, mode); file = fopen(filename, mode);
#endif #endif
if (file != NULL) { if (file == NULL) {
// Some systems allow seeking past the end of file, so we need check for that first and disallow return NULL;
if (fseek(file, 0, SEEK_END) != 0 }
|| offset >= ftell(file)
|| fseek(file, offset, SEEK_SET) != 0 // Seek to the specified 'section'
) { static const char *hex_terminator = ":00000001FF\r";
fclose(file); unsigned terms_seen = 0;
file = NULL; char buffer[MAX_LINE_LEN + 1];
errno = EINVAL;
while (terms_seen < section && fgets(buffer, MAX_LINE_LEN, file) != NULL) {
size_t len = strlen(buffer);
if (buffer[len - 1] == '\n') {
len--;
buffer[len] = 0;
} }
if (buffer[len - 1] != '\r') {
buffer[len] = '\r';
len++;
buffer[len] = 0;
}
if (strcmp(buffer, hex_terminator) == 0) {
// Found a section terminator
terms_seen++;
}
}
if (feof(file)) {
// Section not found
fclose(file);
return NULL;
} }
return file; return file;
@ -1392,7 +1414,7 @@ int fileio_setparms(int op, struct fioparms * fp,
static int fmt_autodetect(char * fname, size_t offset) static int fmt_autodetect(char * fname, unsigned section)
{ {
FILE * f; FILE * f;
unsigned char buf[MAX_LINE_LEN]; unsigned char buf[MAX_LINE_LEN];
@ -1402,9 +1424,9 @@ static int fmt_autodetect(char * fname, size_t offset)
int first = 1; int first = 1;
#if defined(WIN32NATIVE) #if defined(WIN32NATIVE)
f = fopen_and_seek(fname, "r", offset); f = fopen_and_seek(fname, "r", section);
#else #else
f = fopen_and_seek(fname, "rb", offset); f = fopen_and_seek(fname, "rb", section);
#endif #endif
if (f == NULL) { if (f == NULL) {
@ -1480,7 +1502,7 @@ static int fmt_autodetect(char * fname, size_t offset)
int fileio(int op, char * filename, FILEFMT format, int fileio(int op, char * filename, FILEFMT format,
struct avrpart * p, char * memtype, int size, size_t offset) struct avrpart * p, char * memtype, int size, unsigned section)
{ {
int rc; int rc;
FILE * f; FILE * f;
@ -1539,7 +1561,7 @@ int fileio(int op, char * filename, FILEFMT format,
return -1; return -1;
} }
format_detect = fmt_autodetect(fname, offset); format_detect = fmt_autodetect(fname, section);
if (format_detect < 0) { if (format_detect < 0) {
avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n", avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
progname, fname); progname, fname);
@ -1570,7 +1592,7 @@ int fileio(int op, char * filename, FILEFMT format,
if (format != FMT_IMM) { if (format != FMT_IMM) {
if (!using_stdio) { if (!using_stdio) {
f = fopen_and_seek(fname, fio.mode, offset); f = fopen_and_seek(fname, fio.mode, section);
if (f == NULL) { if (f == NULL) {
avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n", avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
progname, fio.iodesc, fname, strerror(errno)); progname, fio.iodesc, fname, strerror(errno));

View file

@ -821,7 +821,7 @@ extern "C" {
char * fmtstr(FILEFMT format); char * fmtstr(FILEFMT format);
int fileio(int op, char * filename, FILEFMT format, int fileio(int op, char * filename, FILEFMT format,
struct avrpart * p, char * memtype, int size, size_t offset); struct avrpart * p, char * memtype, int size, unsigned section);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -870,7 +870,7 @@ enum updateflags {
typedef struct update_t { typedef struct update_t {
char * memtype; char * memtype;
int op; int op;
size_t offset; unsigned section;
char * filename; char * filename;
int format; int format;
} UPDATE; } UPDATE;
@ -882,7 +882,7 @@ extern "C" {
extern UPDATE * parse_op(char * s); extern UPDATE * parse_op(char * s);
extern UPDATE * dup_update(UPDATE * upd); extern UPDATE * dup_update(UPDATE * upd);
extern UPDATE * new_update(int op, char * memtype, int filefmt, extern UPDATE * new_update(int op, char * memtype, int filefmt,
char * filename, size_t offset); char * filename, unsigned section);
extern void free_update(UPDATE * upd); extern void free_update(UPDATE * upd);
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
enum updateflags flags); enum updateflags flags);

View file

@ -194,7 +194,7 @@ static void usage(void)
" -F Override invalid signature check.\n" " -F Override invalid signature check.\n"
" -e Perform a chip erase.\n" " -e Perform a chip erase.\n"
" -O Perform RC oscillator calibration (see AVR053). \n" " -O Perform RC oscillator calibration (see AVR053). \n"
" -U <memtype>:r|w|v:<offset>:<filename>[:format]\n" " -U <memtype>:r|w|v:<section>:<filename>[:format]\n"
" Memory operation specification.\n" " Memory operation specification.\n"
" Multiple -U options are allowed, each request\n" " Multiple -U options are allowed, each request\n"
" is performed in the order specified.\n" " is performed in the order specified.\n"

View file

@ -101,22 +101,22 @@ UPDATE * parse_op(char * s)
p++; p++;
// Extension: Parse file contents offset // Extension: Parse file section number
size_t offset = 0; unsigned section = 0;
for (; *p != ':'; p++) { for (; *p != ':'; p++) {
if (*p >= '0' && *p <= '9') { if (*p >= '0' && *p <= '9') {
offset *= 10; section *= 10;
offset += *p - 0x30; section += *p - 0x30;
} else { } else {
avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname); avrdude_message(MSG_INFO, "%s: invalid update specification: <section> is not a number\n", progname);
free(upd->memtype); free(upd->memtype);
free(upd); free(upd);
return NULL; return NULL;
} }
} }
upd->offset = offset; upd->section = section;
p++; p++;
/* /*
@ -194,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd)
return u; return u;
} }
UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset) UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, unsigned section)
{ {
UPDATE * u; UPDATE * u;
@ -208,7 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t
u->filename = strdup(filename); u->filename = strdup(filename);
u->op = op; u->op = op;
u->format = filefmt; u->format = filefmt;
u->offset = offset; u->section = section;
return u; return u;
} }
@ -286,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname, progname,
strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename); strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
} }
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset); rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
progname, upd->filename); progname, upd->filename);
@ -351,7 +351,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname, mem->desc, upd->filename); progname, mem->desc, upd->filename);
} }
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset); rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
progname, upd->filename); progname, upd->filename);

View file

@ -95,7 +95,7 @@ struct FirmwareDialog::priv
void find_serial_ports(); void find_serial_ports();
void flashing_start(bool flashing_l10n); void flashing_start(bool flashing_l10n);
void flashing_done(AvrDudeComplete complete); void flashing_done(AvrDudeComplete complete);
size_t hex_lang_offset(const wxString &path); size_t hex_num_sections(const wxString &path);
void perform_upload(); void perform_upload();
void cancel(); void cancel();
void on_avrdude(const wxCommandEvent &evt); void on_avrdude(const wxCommandEvent &evt);
@ -158,7 +158,7 @@ void FirmwareDialog::priv::flashing_done(AvrDudeComplete complete)
} }
} }
size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path) size_t FirmwareDialog::priv::hex_num_sections(const wxString &path)
{ {
fs::ifstream file(fs::path(path.wx_str())); fs::ifstream file(fs::path(path.wx_str()));
if (! file.good()) { if (! file.good()) {
@ -175,18 +175,11 @@ size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path)
} }
if (line == hex_terminator) { if (line == hex_terminator) {
if (res == 0) { res++;
// This is the first terminator seen, save the position
res = file.tellg();
} else {
// We've found another terminator, return the offset just after the first one
// which is the start of the second 'section'.
return res;
}
} }
} }
return 0; return res;
} }
void FirmwareDialog::priv::perform_upload() void FirmwareDialog::priv::perform_upload()
@ -202,10 +195,10 @@ void FirmwareDialog::priv::perform_upload()
if (filename.IsEmpty() || port.empty()) { return; } if (filename.IsEmpty() || port.empty()) { return; }
const bool extra_verbose = false; // For debugging const bool extra_verbose = false; // For debugging
const auto lang_offset = hex_lang_offset(filename); const auto num_secions = hex_num_sections(filename);
const auto filename_utf8 = filename.utf8_str(); const auto filename_utf8 = filename.utf8_str();
flashing_start(lang_offset > 0); flashing_start(num_secions > 1);
// It is ok here to use the q-pointer to the FirmwareDialog // It is ok here to use the q-pointer to the FirmwareDialog
// because the dialog ensures it doesn't exit before the background thread is done. // because the dialog ensures it doesn't exit before the background thread is done.
@ -236,7 +229,7 @@ void FirmwareDialog::priv::perform_upload()
avrdude.push_args(std::move(args)); avrdude.push_args(std::move(args));
if (lang_offset > 0) { if (num_secions > 1) {
// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy) // The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
// This is done via another avrdude invocation, here we build arg list for that: // This is done via another avrdude invocation, here we build arg list for that:
std::vector<std::string> args_l10n {{ std::vector<std::string> args_l10n {{
@ -249,7 +242,7 @@ void FirmwareDialog::priv::perform_upload()
"-b", "115200", "-b", "115200",
"-D", "-D",
"-u", // disable safe mode "-u", // disable safe mode
"-U", (boost::format("flash:w:%1%:%2%:i") % lang_offset % filename_utf8.data()).str(), "-U", (boost::format("flash:w:1:%1%:i") % filename_utf8.data()).str(),
}}; }};
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: " BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "