Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve signature check for UPDI parts #1840

Merged
merged 6 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/avrpart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,12 +1071,16 @@ AVRPART *locate_part_by_avr910_devcode(const LISTID parts, int devcode) {
return NULL;
}

// Return pointer to first part that has signature sig (unless all 0xff or all 0x00); NULL if no match
AVRPART *locate_part_by_signature_pm(const LISTID parts, unsigned char *sig, int sigsize, int prog_modes) {
if(parts && sigsize == 3) {
for(LNODEID ln=lfirst(parts); ln; ln=lnext(ln)) {
AVRPART *p = ldata(ln);
if(memcmp(p->signature, sig, 3) == 0 && p->prog_modes & prog_modes)
return p;
if(!*p->id || *p->id == '.') // Skip stump entries
continue;
if(!is_memset(p->signature, 0xff, 3) && !is_memset(p->signature, 0, 3))
if(!memcmp(p->signature, sig, 3) && p->prog_modes & prog_modes)
return p;
}
}
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/config_gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ part_def :
if(mem_is_signature(m))
m->type &= ~MEM_IN_SIGROW;
}
if(fileio_mem_offset(current_part, m) == -1U)
if(fileio_mem_offset(current_part, m) == ~0U)
yywarning("revise fileio_mem_offset(), avrdude.conf entry or memory type assignment");
}

Expand Down
16 changes: 12 additions & 4 deletions src/dryrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,22 @@ static int flashlayout(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *fl
// Write a vector table to flash addr and return number of bytes written
static int putvectortable(const AVRPART *p, const AVRMEM *flm, int addr) {
int vecsz = flm->size <= 8192? 2: 4, ret = p->n_interrupts * vecsz;
int app = (ret + vecsz - 2)/2; // Distance to application in words

for(int i = 0; i < ret; i += vecsz) { // First store rjmps
flm->buf[addr + i] = 255-i/2;
flm->buf[addr + i + 1] = 0xcf; // rjmp .-2, rjmp .-6, ...
for(int i = 0; i < ret; i += vecsz) { // First store rjmps to after table
flm->buf[addr + i] = app;
flm->buf[addr + i + 1] = 0xc0 + (app>>8); // rjmp app, rjmp app, ...
app -= vecsz/2;
}
for(int i=0; i < vecsz; i++) // Leave one vector gap
flm->buf[addr + ret++] = ' ';

flm->buf[addr + ret++] = 0xff; // Put endless lopp as application
flm->buf[addr + ret++] = 0xcf;

// Then round up to multiples of 32
while(ret%32)
flm->buf[ret++] = ' ';
flm->buf[addr + ret++] = ' ';

return ret;
}
Expand Down
19 changes: 9 additions & 10 deletions src/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,22 +232,22 @@ unsigned fileio_mem_offset(const AVRPART *p, const AVRMEM *mem) {
mem_is_sib(mem)? MBASE(SIGROW) + 0x1000: // Arbitrary 0x1000 offset in signature section for sib
mem_is_userrow(mem)? MBASE(USERROW):
mem_is_bootrow(mem)? MBASE(BOOTROW):
-1U;
~0U;

if(location == -1U)
if(location == ~0U)
pmsg_error("unable to locate %s's %s in multi-memory address space\n", p->desc, mem->desc);
else if(location >= ANY_MEM_SIZE || location + mem->size > ANY_MEM_SIZE) { // Overflow
pmsg_error("%s's %s location [0x%06x, 0x%06x] outside flat address space [0, 0x%06x]\n",
p->desc, mem->desc, location, location + mem->size-1, ANY_MEM_SIZE-1);
location = -1U;
location = ~0U;
} else if(location <= MEND(FLASH) && location + mem->size > MEND(FLASH)+1) {
pmsg_error("%s's %s location [0x%06x, 0x%06x] straddles flash section boundary 0x%06x\n",
p->desc, mem->desc, location, location + mem->size-1, MEND(FLASH)+1);
location = -1U;
location = ~0U;
} else if(location > MEND(FLASH) && location/0x10000 != (location + mem->size-1)/0x10000) {
pmsg_error("%s's %s memory location [0x%06x, 0x%06x] straddles memory section boundary 0x%02x0000\n",
p->desc, mem->desc, location, location + mem->size-1, 1+location/0x10000);
location = -1U;
location = ~0U;
}

return location;
Expand Down Expand Up @@ -352,8 +352,7 @@ static int b2ihex(const AVRPART *p, const AVRMEM *mem, const Segment *segp, Sego
if(name) {
fprintf(outf, " %s", name);
if((str_eq(name, "sigrow") || str_eq(name, "signature")) && !nextaddr) {
char mculist[1024] = {0};
str_mcunames_signature(buf, mculist, sizeof mculist);
const char *mculist = str_ccmcunames_signature(buf, PM_ALL);
if(*mculist)
fprintf(outf, " (%s)", mculist);
}
Expand Down Expand Up @@ -466,7 +465,7 @@ static int any2mem(const AVRPART *p, const AVRMEM *mem, const Segment *segp,
// Compute location for multi-memory file input
unsigned location = maxsize > MEND(FLASH)+1? fileio_mem_offset(p, mem): 0;

if(location == -1U)
if(location == ~0U)
return -1;

unsigned ret = 0;
Expand Down Expand Up @@ -580,7 +579,7 @@ static int ihex2b(const char *infile, FILE *inf, const AVRPART *p, const AVRMEM
if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && ihex.reclen >= 3)
if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) {
pmsg_error("signature of %s incompatible with file's (%s)\n", p->desc,
str_ccmcunames_signature(any->buf+nextaddr));
str_ccmcunames_signature(any->buf+nextaddr, PM_ALL));
imsg_error("use -F to override this check\n");
mmt_free(buffer);
goto error;
Expand Down Expand Up @@ -935,7 +934,7 @@ static int srec2b(const char *infile, FILE * inf, const AVRPART *p,
if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && srec.reclen >= 3)
if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) {
pmsg_error("signature of %s incompatible with file's (%s)\n", p->desc,
str_ccmcunames_signature(any->buf+nextaddr));
str_ccmcunames_signature(any->buf+nextaddr, PM_ALL));
imsg_error("use -F to override this check\n");
mmt_free(buffer);
goto error;
Expand Down
6 changes: 3 additions & 3 deletions src/libavrdude.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ typedef struct avrmem {
int initval; /* factory setting of fuses and lock bits */
int bitmask; /* bits used in fuses and lock bits */
int n_word_writes; /* TPI only: number words to write at a time */
unsigned int offset; /* offset in IO memory (ATxmega) */
unsigned int offset; /* offset in IO memory (ATxmega, UPDI, some classic memories) */
int min_write_delay; /* microseconds */
int max_write_delay; /* microseconds */
int pwroff_after_write; /* after this memory is written to,
Expand Down Expand Up @@ -1524,8 +1524,8 @@ char *str_nexttok(char *buf, const char *delim, char **next);
const char *str_ccfrq(double f, int n);
int str_levenshtein(const char *str1, const char *str2, int swap, int subst, int add, int del);
size_t str_weighted_damerau_levenshtein(const char *str1, const char *str2);
int str_mcunames_signature(const unsigned char *sigs, char *p, size_t n);
const char *str_ccmcunames_signature(const unsigned char *sigs);
int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n);
const char *str_ccmcunames_signature(const unsigned char *sigs, int pm);

int led_set(const PROGRAMMER *pgm, int led);
int led_clr(const PROGRAMMER *pgm, int led);
Expand Down
55 changes: 35 additions & 20 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,7 @@ int main(int argc, char * argv [])
if (uflags & UF_NOWRITE) {
pmsg_warning("conflicting -e and -n options specified, NOT erasing chip\n");
} else {
pmsg_info("erasing chip\n");
pmsg_info("trying to unlock the chip\n");
exitrc = avr_unlock(pgm, p);
if(exitrc)
goto main_exit;
Expand All @@ -1619,33 +1619,48 @@ int main(int argc, char * argv [])
sig = avr_locate_signature(p);
if (sig == NULL)
pmsg_warning("signature memory not defined for device %s\n", p->desc);
else {
const char *mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes);
if(!*mculist) {
if(p->prog_modes & PM_UPDI) { // UPDI parts have different(!) offsets for signature
int k, n = 0; // Gather list of known different signature offsets
unsigned myoff = sig->offset, offlist[10];
for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) {
AVRMEM *m = avr_locate_signature(ldata(ln1));
if(m && m->offset != myoff) {
for(k=0; k<n; k++)
if(m->offset == offlist[k])
break;
if(k == n && k < (int) (sizeof offlist/sizeof*offlist))
offlist[n++] = m->offset;
}
}
// Now go through the list of other(!) sig offsets and try these
for(k=0; k<n; k++) {
sig->offset = offlist[k];
if(avr_signature(pgm, p) >= 0)
if(*(mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes)))
break;
}
sig->offset = myoff;
}
}

if (sig != NULL) {
int ff, zz;

pmsg_info("device signature = 0x");
ff = zz = 1;
pmsg_info("device signature =");
int ff = 1, zz = 1;
for (i=0; i<sig->size; i++) {
msg_info("%02x", sig->buf[i]);
msg_info(" %02X", sig->buf[i]);
if (sig->buf[i] != 0xff)
ff = 0;
if (sig->buf[i] != 0x00)
zz = 0;
}
if(*mculist)
msg_info(" (%s)", mculist);

bool signature_matches =
sig->size == 3 &&
sig->buf[0] == p->signature[0] &&
sig->buf[1] == p->signature[1] &&
sig->buf[2] == p->signature[2];

if (quell_progress < 2) {
AVRPART *part;
if((part = locate_part_by_signature_pm(part_list, sig->buf, sig->size, pgm->prog_modes)) ||
(part = locate_part_by_signature(part_list, sig->buf, sig->size)))
msg_info(" (probably %s)", signature_matches? p->id: part->id);
}
if (ff || zz) {
bool signature_matches = sig->size >= 3 && !memcmp(sig->buf, p->signature, 3);

if (ff || zz) { // All three bytes are 0xff or all three bytes are 0x00
if (++attempt < 3) {
waittime *= 5;
msg_info(" (retrying)\n");
Expand Down
57 changes: 42 additions & 15 deletions src/strutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -1330,29 +1330,56 @@ size_t str_weighted_damerau_levenshtein(const char *s1, const char *s2) {


// Puts a comma-separated list of matching MCU names into array p with n chars space
int str_mcunames_signature(const unsigned char *sigs, char *p, size_t n) {
int matching = 0;

for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) {
if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs)) {
if(matching && n > 2)
strcpy(p, ", "), n -= 2, p += 2;
size_t len = strlen(uP_table[i].name);
if(n > len) {
strcpy(p, uP_table[i].name);
n -= len; p += len;
int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n) {
const char *matches[100];
int matching = 0, k, N = sizeof matches/sizeof*matches;

if(!pm || (pm & PM_ALL) == PM_ALL) // Look up uP table when unrestricted by prog modes
for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++)
if(!is_memset(uP_table[i].sigs, 0xff, 3) && !is_memset(uP_table[i].sigs, 0, 3))
if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs) && matching < N)
matches[matching++] = uP_table[i].name;

for(LNODEID lp = lfirst(part_list); lp; lp = lnext(lp)) {
AVRPART *pp = ldata(lp);
if(!*pp->id || *pp->id == '.') // Skip invalid entries
continue;
if(is_memset(pp->signature, 0xff, 3) || is_memset(pp->signature, 0, 3))
continue;
if(!memcmp(sigs, pp->signature, 3) && (!pm || (pp->prog_modes & pm))) {
for(k = 0; k < matching; k++)
if(str_eq(matches[k], pp->desc))
break;
if(k == matching && matching < N)
matches[matching++] = pp->desc;
}
}

if(n && p) {
*p = 0;

for(int i = 0; i < matching; i++) {
size_t len = strlen(matches[i]);
if(n > len + 2) {
if(i) {
strcpy(p, ", ");
n -= 2, p += 2;
}
strcpy(p, matches[i]);
n -= len, p += len;
}
matching++;
}
}

return matching;
}

// Returns a comma-separated list of matching MCU names in closed-circuit space
const char *str_ccmcunames_signature(const unsigned char *sigs) {
char names[1024] = {0};
(void) str_mcunames_signature(sigs, names, sizeof names);
const char *str_ccmcunames_signature(const unsigned char *sigs, int pm) {
char names[1024];
// If no match is found, given required prog_modes, relax the match to any prog mode
if(!str_mcunames_signature(sigs, pm, names, sizeof names) && pm && (pm & PM_ALL) != PM_ALL)
(void) str_mcunames_signature(sigs, 0, names, sizeof names);

return str_ccprintf("%s", names);
}
2 changes: 1 addition & 1 deletion src/update.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat
continue;
}
unsigned off = fileio_mem_offset(p, m);
if(off == -1U) {
if(off == ~0U) {
pmsg_warning("cannot map %s to flat address space, skipping ...\n", m_name);
rwvproblem = 1;
continue;
Expand Down
Loading