Hash known bootloaders for urclock; they don't need -xbootsize=....

This commit is contained in:
Stefan Rueger 2022-11-22 00:47:26 +00:00
parent 7f4474f049
commit 2e398916a7
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
1 changed files with 123 additions and 12 deletions

View File

@ -263,7 +263,9 @@ typedef struct {
vbllevel, // 0=n/a, 1=patch externally, 2=bl patches, 3=bl patches & verifies
blurversion, // Octal byte 076 means v7.6 (minor version number is lowest 3 bit)
// Small numbers < 070 probably are optiboot major version number
bloptiversion; // Optiboot version as (major<<8) + minor
bloptiversion, // Optiboot version as (major<<8) + minor
blguessed; // Guessed the bootloader from hash data
int32_t blstart; // Bootloader start address, eg, for bootloader write protection
int idmchr; // Either 'E' or 'F' for the memory where the Urclock ID is located
@ -940,7 +942,7 @@ nopatch_nometa:
// Put version string into a buffer of max 19 characters incl nul (normally 15-16 bytes incl nul)
static void urbootPutVersion(char *buf, uint16_t ver, uint16_t rjmpwp) {
static void urbootPutVersion(const PROGRAMMER *pgm, char *buf, uint16_t ver, uint16_t rjmpwp) {
uint8_t hi = ver>>8, type = ver & 0xff, flags;
if(ver == 0xffff) // Unknown provenance
@ -968,9 +970,11 @@ static void urbootPutVersion(char *buf, uint16_t ver, uint16_t rjmpwp) {
*buf++ = hi >= 077 && (type & UR_AUTOBAUD)? 'a': '-'; // - means no
*buf++ = hi >= 077 && (type & UR_HAS_CE)? 'c': hi >= 077? '-': '.'; // . means don't know
*buf = 0;
} else if(hi) // Version number in binary from optiboot v4.1
sprintf(buf, "o%d.%d -?s-?-r--", hi, type);
else
} else if(hi) { // Version number in binary from optiboot v4.1
sprintf(buf, "o%d.%d -%cs-%c-r--", hi, type,
ur.blguessed? (ur.bleepromrw? 'e': '-'): '?',
ur.blguessed? "hjvV"[ur.vbllevel & 3]: '?');
} else
sprintf(buf, "x0.0 .........");
return;
@ -1096,6 +1100,107 @@ static void set_uP(const PROGRAMMER *pgm, const AVRPART *p, int mcuid, int mcuid
}
// https://en.wikipedia.org/wiki/Jenkins_hash_function
static uint32_t jenkins_hash(const uint8_t* key, size_t length) {
size_t i = 0;
uint32_t hash = 0;
while (i != length) {
hash += key[i++];
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
typedef struct {
uint16_t sz, ee;
uint32_t h256, hash;
} Blhash_t;
static int cmpblhash(const void *va, const void *vb) {
const Blhash_t *a = va, *b = vb;
return a->sz > b->sz? 1: a->sz < b->sz? -1: a->hash > b->hash? 1: a->hash < b->hash? -1: 0;
}
static void guessblstart(const PROGRAMMER *pgm, const AVRPART *p) {
if(ur.urprotocol && !(ur.urfeatures & UB_READ_FLASH)) // Cannot read flash
return;
Blhash_t blist[] = {
{ 1024, 0, 0x35445c45, 0x9ef77953 }, // ATmegaBOOT-prod-firmware-2009-11-07.hex
{ 1024, 0, 0x32b1376c, 0xceba80bb }, // ATmegaBOOT.hex
{ 2048, 0, 0x08426ba2, 0x29e81e21 }, // ATmegaBOOT_168.hex
{ 4096, 0, 0x1bf8ed1b, 0x272e49ed }, // ATmegaBOOT_168_atmega1280.hex
{ 2048, 0, 0x9774b926, 0x335016ed }, // ATmegaBOOT_168_atmega328.hex
{ 4096, 0, 0x3242ddd3, 0x809632a3 }, // ATmegaBOOT_168_atmega328_bt.hex
{ 2048, 0, 0xc553f5b4, 0x56be91cb }, // ATmegaBOOT_168_atmega328_pro_8MHz.hex
{ 2048, 0, 0x12ab8da0, 0xca46a3ca }, // ATmegaBOOT_168_diecimila.hex
{ 2048, 0, 0x3242ddd3, 0xf3e94dba }, // ATmegaBOOT_168_ng.hex
{ 2048, 0, 0x2eed30b3, 0x47d14ffa }, // ATmegaBOOT_168_pro_8MHz.hex
{ 4096, 0, 0xc52edd05, 0xa3371f94 }, // Caterina-LilyPadUSB.hex
{ 4096, 0, 0x663b8f7e, 0x7efdda2b }, // Caterina-Robot-Control.hex
{ 4096, 0, 0x3c6387e7, 0x7e96eea2 }, // Caterina-Robot-Motor.hex
{ 2048, 0, 0x1cef0d75, 0x6cfbac49 }, // LilyPadBOOT_168.hex
{ 1024, 1, 0x6ca0f37b, 0x31bae545 }, // bigboot_328.hex
{ 512, 0, 0x035cbc07, 0x24ba435e }, // optiboot_atmega168.hex
{ 512, 0, 0x455050db, 0x1d53065f }, // optiboot_atmega328-Mini.hex
{ 512, 0, 0xd2001ddb, 0x16c9663b }, // optiboot_atmega328.hex v4.4
{ 512, 0, 0x49c1e9a4, 0xa450759b }, // optiboot_atmega328.hex v8.3
{ 512, 0, 0xc54dcd6c, 0x5bfc5d06 }, // optiboot_atmega8.hex
{ 256, 0, 0x5a01c55b, 0x5a01c55b }, // picobootArduino168.hex
{ 256, 0, 0x1451061b, 0x1451061b }, // picobootArduino168v3b2.hex
{ 512, 0, 0x3242ddd3, 0x53348738 }, // picobootArduino328.hex
{ 512, 0, 0x858e12de, 0xc80a44a4 }, // picobootArduino328v3beta.hex
{ 256, 0, 0xaa62bafc, 0xaa62bafc }, // picobootArduino8v3rc1.hex
{ 256, 0, 0x56263965, 0x56263965 }, // picobootSTK500-168p.hex
{ 512, 0, 0x3242ddd3, 0x5ba5f5f6 }, // picobootSTK500-328p.hex
};
uint8_t buf[4096], b128[128];
qsort(blist, sizeof blist/sizeof*blist, sizeof*blist, cmpblhash);
for(int ii, si = 0, sz = 0, bi = 0; si < (int) sizeof blist/sizeof*blist; si++) {
if(blist[si].sz > sz) { // Read in and compare
sz = blist[si].sz;
if(sz > ur.uP.flashsize/2 || (sz+127)/128*128 > (int) sizeof buf)
return;
while(bi < sz) {
if(ur_readEF(pgm, p, b128, ur.uP.flashsize-bi-128, 128, 'F') < 0)
return;
for(int ti=127; ti >= 0; ti--) // read in backwards
buf[bi++] = b128[ti];
}
// Does the hash for the full size match? OK: found a known bootloader
uint32_t hash = jenkins_hash(buf, sz);
for(ii = 0; ii < (int) sizeof blist/sizeof*blist; ii++)
if(blist[ii].hash == hash && sz == blist[ii].sz && !(sz & (ur.uP.pagesize-1))) {
// Page aligned bootloader size matches
ur.blstart = ur.uP.flashsize-sz;
if(blist[ii].ee)
ur.bleepromrw = 1;
ur.blguessed = 1;
return;
}
// Can we exclude the top 256 byte flash from the botloader list?
if(sz == 256) {
for(ii = 0; ii < (int) sizeof blist/sizeof*blist; ii++)
if(hash == blist[ii].h256)
break;
if(ii >= (int) sizeof blist/sizeof*blist)
return;
}
}
}
}
/*
* Read signature bytes - Urclock version
*
@ -1242,8 +1347,8 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
uint8_t urver = spc[5]; // Urboot version (low three bits are minor version: 076 is v7.6)
v16 = buf2uint16(spc+4); // Combo word for neatly printed version line of urboot bootloader
// Extensively check this is an urboot bootloader, and if OK extract properties
if(urver >= 072 && urver != 0xff && (isRjmp(rjmpwp) || rjmpwp == ret_opcode)) { // Prob urboot
// Extensively check this is an urboot bootloader v7.2 .. v12.7 == 0147 and extract properties
if(urver >= 072 && urver <= 0147 && (isRjmp(rjmpwp) || rjmpwp == ret_opcode)) { // Prob urboot
ur.blurversion = urver;
ur.bleepromrw = iseeprom_cap(cap);
// Vector bootloader: 0 = none, 1 = external patching, 2 = bl patches, 3 = patches + verifies
@ -1281,11 +1386,9 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
}
} else if(urver != 0xff) { // Probably optiboot where the version number is two bytes
ur.bloptiversion = (urver<<8) + cap;
if(!ur.blstart)
Return("bootloader might be optiboot %d.%d? Please use -xbootsize=<num>\n", urver, cap);
}
if(!ur.blstart && ur.vbllevel) { // An older version urboot vector bootloader
if(!ur.blstart && ur.vbllevel) { // An older version urboot vector bootloader?
int vecsz = ur.uP.flashsize <= 8192? 2: 4;
// Reset vector points to the bootloader and the bootloader has r/jmp to application?
@ -1356,13 +1459,21 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
}
}
// Still no bootloader start address?
// Still no bootloader start address? Read in top flash and guess bootloader start
if(!ur.blstart)
guessblstart(pgm, p);
// Still no bootloader start address?
if(!ur.blstart) {
if(ur. bloptiversion)
Return("bootloader might be optiboot %d.%d? Please use -xbootsize=<num>\n",
ur.bloptiversion>>8, ur.bloptiversion & 255);
Return("unknown bootloader ... please specify -xbootsize=<num>\n");
}
}
vblvecfound:
urbootPutVersion(ur.desc, v16, rjmpwp);
urbootPutVersion(pgm, ur.desc, v16, rjmpwp);
ur.mcode = 0xff;
if(ur.blstart) {