diff --git a/xs/src/avrdude/fileio.c b/xs/src/avrdude/fileio.c index aa57f5587..708159295 100644 --- a/xs/src/avrdude/fileio.c +++ b/xs/src/avrdude/fileio.c @@ -98,11 +98,11 @@ static int fileio_num(struct fioparms * fio, char * filename, FILE * f, AVRMEM * mem, int size, 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; // 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); #endif - if (file != NULL) { - // Some systems allow seeking past the end of file, so we need check for that first and disallow - if (fseek(file, 0, SEEK_END) != 0 - || offset >= ftell(file) - || fseek(file, offset, SEEK_SET) != 0 - ) { - fclose(file); - file = NULL; - errno = EINVAL; + if (file == NULL) { + return NULL; + } + + // Seek to the specified 'section' + static const char *hex_terminator = ":00000001FF\r"; + unsigned terms_seen = 0; + char buffer[MAX_LINE_LEN + 1]; + + 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; @@ -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; unsigned char buf[MAX_LINE_LEN]; @@ -1402,9 +1424,9 @@ static int fmt_autodetect(char * fname, size_t offset) int first = 1; #if defined(WIN32NATIVE) - f = fopen_and_seek(fname, "r", offset); + f = fopen_and_seek(fname, "r", section); #else - f = fopen_and_seek(fname, "rb", offset); + f = fopen_and_seek(fname, "rb", section); #endif if (f == NULL) { @@ -1480,7 +1502,7 @@ static int fmt_autodetect(char * fname, size_t offset) 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; FILE * f; @@ -1539,7 +1561,7 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - format_detect = fmt_autodetect(fname, offset); + format_detect = fmt_autodetect(fname, section); if (format_detect < 0) { avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n", progname, fname); @@ -1570,7 +1592,7 @@ int fileio(int op, char * filename, FILEFMT format, if (format != FMT_IMM) { if (!using_stdio) { - f = fopen_and_seek(fname, fio.mode, offset); + f = fopen_and_seek(fname, fio.mode, section); if (f == NULL) { avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n", progname, fio.iodesc, fname, strerror(errno)); diff --git a/xs/src/avrdude/libavrdude.h b/xs/src/avrdude/libavrdude.h index 536f1a2f7..aef792476 100644 --- a/xs/src/avrdude/libavrdude.h +++ b/xs/src/avrdude/libavrdude.h @@ -821,7 +821,7 @@ extern "C" { char * fmtstr(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 } @@ -870,7 +870,7 @@ enum updateflags { typedef struct update_t { char * memtype; int op; - size_t offset; + unsigned section; char * filename; int format; } UPDATE; @@ -882,7 +882,7 @@ extern "C" { extern UPDATE * parse_op(char * s); extern UPDATE * dup_update(UPDATE * upd); 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 int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags); diff --git a/xs/src/avrdude/main.c b/xs/src/avrdude/main.c index d4c34fe44..5d73403b0 100644 --- a/xs/src/avrdude/main.c +++ b/xs/src/avrdude/main.c @@ -194,7 +194,7 @@ static void usage(void) " -F Override invalid signature check.\n" " -e Perform a chip erase.\n" " -O Perform RC oscillator calibration (see AVR053). \n" - " -U :r|w|v::[:format]\n" + " -U :r|w|v:
:[:format]\n" " Memory operation specification.\n" " Multiple -U options are allowed, each request\n" " is performed in the order specified.\n" diff --git a/xs/src/avrdude/update.c b/xs/src/avrdude/update.c index e9dd6e325..417cbf71d 100644 --- a/xs/src/avrdude/update.c +++ b/xs/src/avrdude/update.c @@ -101,22 +101,22 @@ UPDATE * parse_op(char * s) p++; - // Extension: Parse file contents offset - size_t offset = 0; + // Extension: Parse file section number + unsigned section = 0; for (; *p != ':'; p++) { if (*p >= '0' && *p <= '9') { - offset *= 10; - offset += *p - 0x30; + section *= 10; + section += *p - 0x30; } else { - avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname); + avrdude_message(MSG_INFO, "%s: invalid update specification:
is not a number\n", progname); free(upd->memtype); free(upd); return NULL; } } - upd->offset = offset; + upd->section = section; p++; /* @@ -194,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd) 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; @@ -208,7 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t u->filename = strdup(filename); u->op = op; u->format = filefmt; - u->offset = offset; + u->section = section; return u; } @@ -286,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f progname, strcmp(upd->filename, "-")==0 ? "" : 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) { avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", 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); } - 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) { avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", progname, upd->filename); diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/xs/src/slic3r/GUI/FirmwareDialog.cpp index d74743055..17ff42245 100644 --- a/xs/src/slic3r/GUI/FirmwareDialog.cpp +++ b/xs/src/slic3r/GUI/FirmwareDialog.cpp @@ -95,7 +95,7 @@ struct FirmwareDialog::priv void find_serial_ports(); void flashing_start(bool flashing_l10n); 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 cancel(); 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())); if (! file.good()) { @@ -175,18 +175,11 @@ size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path) } if (line == hex_terminator) { - if (res == 0) { - // 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; - } + res++; } } - return 0; + return res; } void FirmwareDialog::priv::perform_upload() @@ -202,10 +195,10 @@ void FirmwareDialog::priv::perform_upload() if (filename.IsEmpty() || port.empty()) { return; } 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(); - flashing_start(lang_offset > 0); + flashing_start(num_secions > 1); // 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. @@ -236,7 +229,7 @@ void FirmwareDialog::priv::perform_upload() 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) // This is done via another avrdude invocation, here we build arg list for that: std::vector args_l10n {{ @@ -249,7 +242,7 @@ void FirmwareDialog::priv::perform_upload() "-b", "115200", "-D", "-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: "