avrdude: use sections instead of offsets
This commit is contained in:
parent
987fc4c6df
commit
6b801f250a
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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 <memtype>:r|w|v:<offset>:<filename>[:format]\n"
|
||||
" -U <memtype>:r|w|v:<section>:<filename>[:format]\n"
|
||||
" Memory operation specification.\n"
|
||||
" Multiple -U options are allowed, each request\n"
|
||||
" is performed in the order specified.\n"
|
||||
|
@ -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: <section> 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 ? "<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) {
|
||||
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);
|
||||
|
@ -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<std::string> 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: "
|
||||
|
Loading…
Reference in New Issue
Block a user