Skip to content

Commit

Permalink
Merge pull request #1840 from stefanrueger/signature-check
Browse files Browse the repository at this point in the history
Improve signature check for UPDI parts
  • Loading branch information
stefanrueger authored Jul 15, 2024
2 parents 6039247 + f3caabf commit 96090dd
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 56 deletions.
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 @@ -1525,8 +1525,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

0 comments on commit 96090dd

Please sign in to comment.