Add partial urclock support for parts with bootloaders in low flash

This commit is contained in:
Stefan Rueger 2022-12-03 23:20:05 +00:00
parent ea2d7eec95
commit 8024bfd4fb
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
1 changed files with 129 additions and 84 deletions

View File

@ -266,7 +266,9 @@ typedef struct {
bloptiversion, // Optiboot version as (major<<8) + minor bloptiversion, // Optiboot version as (major<<8) + minor
blguessed; // Guessed the bootloader from hash data blguessed; // Guessed the bootloader from hash data
int32_t blstart; // Bootloader start address, eg, for bootloader write protection int boothigh; // 1: Bootloader sits in high flash; 0: low flash (UPDI parts)
int32_t blstart, blend; // Bootloader address range [blstart, blend] for write protection
int32_t pfstart, pfend; // Programmable flash address range [pfstart, pfend]
int idmchr; // Either 'E' or 'F' for the memory where the Urclock ID is located int idmchr; // Either 'E' or 'F' for the memory where the Urclock ID is located
int idaddr; // The address of the Urclock ID int idaddr; // The address of the Urclock ID
@ -282,9 +284,15 @@ typedef struct {
uint8_t freeflash[3]; // 24-bit little endian number (storesize) uint8_t freeflash[3]; // 24-bit little endian number (storesize)
uint8_t mcode; // 255 = no metadata, 0 = only freeflash, 1 = freeflash + date, uint8_t mcode; // 255 = no metadata, 0 = only freeflash, 1 = freeflash + date,
// 2-254 = freeflash + date + that many bytes filename incl nul // 2-254 = freeflash + date + that many bytes filename incl nul
// Note:
// blstart = application size + freeflash + nmeta(mcode, flashsize) /*
// FLASHEND+1 = application size + freeflash + nmeta(mcode, flashsize) + bootloader size * Examples:
* blend-blstart+1 = bootloader size
* FLASHEND+1 = application size + freeflash + nmeta(mcode, flashsize) + bootloader size
* Note for "classic" parts the bootloader is in high flash: blend = FLASHEND
* blstart = application size + freeflash + nmeta(mcode, flashsize)
* For "modern" parts the bootloader is in low flash: blstart = 0
*/
// Extended parameters for Urclock // Extended parameters for Urclock
int showall, // Show all pieces of info for connected part and exit int showall, // Show all pieces of info for connected part and exit
@ -315,7 +323,7 @@ typedef struct {
char iddesc[64]; // Location of Urclock ID, eg F.12324.6 or E.-4.4 (default E.257.6) char iddesc[64]; // Location of Urclock ID, eg F.12324.6 or E.-4.4 (default E.257.6)
} Urclock_t; } Urclock_t;
// Use private programmer data as if it were a global structure ur // Use private programmer data as if they were a global structure ur
#define ur (*(Urclock_t *)(pgm->cookie)) #define ur (*(Urclock_t *)(pgm->cookie))
#define Return(...) do { pmsg_error(__VA_ARGS__); msg_error("\n"); return -1; } while (0) #define Return(...) do { pmsg_error(__VA_ARGS__); msg_error("\n"); return -1; } while (0)
@ -613,7 +621,7 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
ur.mcode = ur.nometadata? 0xff: ur.nodate? 0: ur.nofilename? 1: strlen(ur.filename)+1; ur.mcode = ur.nometadata? 0xff: ur.nodate? 0: ur.nofilename? 1: strlen(ur.filename)+1;
nmdata = nmeta(ur.mcode, ur.uP.flashsize); nmdata = nmeta(ur.mcode, ur.uP.flashsize);
maxsize = ur.blstart? ur.blstart: flm->size; maxsize = ur.pfend+1;
// Compute begin and length of first contiguous block in input // Compute begin and length of first contiguous block in input
for(firstbeg=0; firstbeg < size; firstbeg++) for(firstbeg=0; firstbeg < size; firstbeg++)
@ -624,7 +632,7 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
break; break;
pmsg_notice2("%s %04d.%02d.%02d %02d.%02d meta %d boot %d\n", ur.filename, pmsg_notice2("%s %04d.%02d.%02d %02d.%02d meta %d boot %d\n", ur.filename,
ur.yyyy, ur.mm, ur.dd, ur.hr, ur.mn, nmdata, ur.blstart > 0? flm->size-ur.blstart: 0); ur.yyyy, ur.mm, ur.dd, ur.hr, ur.mn, nmdata, ur.blend > ur.blstart? ur.blend-ur.blstart+1: 0);
// Force upload of exactly this file, no patching, no metadata update, just trim if too big // Force upload of exactly this file, no patching, no metadata update, just trim if too big
if(ur.restore) { if(ur.restore) {
@ -635,29 +643,33 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
} }
// Sanity: no patching and no metadata if bootloader location is unknown // Sanity: no patching and no metadata if bootloader location is unknown
if(!ur.blstart) if(ur.blend <= ur.blstart)
goto nopatch_nometa; goto nopatch_nometa;
// Sanity check the bootloader start address // Sanity check the bootloader position
if(ur.blstart < 0 || ur.blstart >= flm->size) if(ur.blstart < 0 || ur.blstart >= flm->size || ur.blend < 0 || ur.blend >= flm->size)
Return("bootloader at 0x%04x outside flash [0, 0x%04x]?", ur.blstart, flm->size-1); Return("bootloader [0x%04x, 0x%04x] outside flash [0, 0x%04x]",
ur.blstart, ur.blend, flm->size-1);
// Check size of uploded application and protect bootloader from being overwritten // Check size of uploded application and protect bootloader from being overwritten
if(size > ur.blstart) if((ur.boothigh && size > ur.pfend+1) || (!ur.boothigh && firstbeg <= ur.blend))
Return("input [0x%04x, 0x%04x] overlaps bootloader [0x%04x, 0x%04x]", Return("input [0x%04x, 0x%04x] overlaps bootloader [0x%04x, 0x%04x]",
firstbeg, size-1, ur.blstart, flm->size-1); firstbeg, size-1, ur.blstart, ur.blend);
if(nmdata >= nmeta(0, ur.uP.flashsize) && size > ur.blstart - nmeta(0, ur.uP.flashsize)) if(nmdata >= nmeta(0, ur.uP.flashsize) && size > ur.pfend+1 - nmeta(0, ur.uP.flashsize))
Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnometadata", Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnometadata",
firstbeg, size-1, ur.blstart-nmeta(0, ur.uP.flashsize), ur.blstart-1); firstbeg, size-1, ur.pfend+1-nmeta(0, ur.uP.flashsize), ur.pfend);
if(nmdata >= nmeta(1, ur.uP.flashsize) && size > ur.blstart - nmeta(1, ur.uP.flashsize)) if(nmdata >= nmeta(1, ur.uP.flashsize) && size > ur.pfend+1 - nmeta(1, ur.uP.flashsize))
Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnodate", Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnodate",
firstbeg, size-1, ur.blstart-nmeta(1, ur.uP.flashsize), ur.blstart-1); firstbeg, size-1, ur.pfend+1-nmeta(1, ur.uP.flashsize), ur.pfend);
if(size > ur.blstart - nmdata) if(size > ur.pfend+1 - nmdata)
Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnofilename", Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnofilename",
firstbeg, size-1, ur.blstart-nmdata, ur.blstart-1); firstbeg, size-1, ur.pfend+1-nmdata, ur.pfend);
if(!ur.boothigh)
goto nopatch;
bool llcode = firstbeg == 0 && firstlen > ur.uP.ninterrupts*vecsz; // Looks like code bool llcode = firstbeg == 0 && firstlen > ur.uP.ninterrupts*vecsz; // Looks like code
bool llvectors = firstbeg == 0 && firstlen >= ur.uP.ninterrupts*vecsz; // Looks like vector table bool llvectors = firstbeg == 0 && firstlen >= ur.uP.ninterrupts*vecsz; // Looks like vector table
@ -724,10 +736,10 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
nopatch: nopatch:
if(nmdata) { if(nmdata) {
int32_t nfree = ur.blstart - size; int32_t nfree = ur.pfend+1 - size;
if(nfree >= nmdata) { if(nfree >= nmdata) {
unsigned char *p = flm->buf + ur.blstart - nmdata; unsigned char *p = flm->buf + ur.pfend+1 - nmdata;
if(ur.mcode > 1) { // Save filename (ur.mcode cannot be 0xff b/c nmdata is non-zero) if(ur.mcode > 1) { // Save filename (ur.mcode cannot be 0xff b/c nmdata is non-zero)
memcpy(p, ur.filename, ur.mcode); memcpy(p, ur.filename, ur.mcode);
@ -760,20 +772,20 @@ nopatch:
*p++ = ur.mcode; *p++ = ur.mcode;
// Set tags so metadata get burned onto chip // Set tags so metadata get burned onto chip
memset(flm->tags + ur.blstart - nmdata, TAG_ALLOCATED, nmdata); memset(flm->tags + ur.pfend+1 - nmdata, TAG_ALLOCATED, nmdata);
if(ur.initstore) // Zap the pgm store if(ur.initstore) // Zap the pgm store
memset(flm->tags + size, TAG_ALLOCATED, nfree); memset(flm->tags + size, TAG_ALLOCATED, nfree);
size = ur.blstart; size = ur.pfend+1;
} }
} }
// Storing no metadata: put a 0xff byte just below bootloader // Storing no metadata: put a 0xff byte just below bootloader
if(size < ur.blstart && nmdata == 0) { if(size < ur.pfend+1 && nmdata == 0) {
flm->buf[ur.blstart-1] = 0xff; flm->buf[ur.pfend] = 0xff;
flm->tags[ur.blstart-1] = TAG_ALLOCATED; flm->tags[ur.pfend] = TAG_ALLOCATED;
size = ur.blstart; size = ur.pfend+1;
} }
nopatch_nometa: nopatch_nometa:
@ -781,10 +793,10 @@ nopatch_nometa:
// Delete metadata on device (if any) that's between new input and metadata // Delete metadata on device (if any) that's between new input and metadata
if(!ur.urprotocol || (ur.urfeatures & UB_READ_FLASH)) { // Flash readable? if(!ur.urprotocol || (ur.urfeatures & UB_READ_FLASH)) { // Flash readable?
uint8_t devmcode; // Metadata marker on the device uint8_t devmcode; // Metadata marker on the device
if(ur.blstart && ur_readEF(pgm, p, &devmcode, ur.blstart-1, 1, 'F') == 0) { if(ur_readEF(pgm, p, &devmcode, ur.pfend, 1, 'F') == 0) {
int devnmeta=nmeta(devmcode, ur.uP.flashsize); int devnmeta=nmeta(devmcode, ur.uP.flashsize);
for(int addr=ur.blstart-devnmeta; addr < ur.blstart; addr++) { for(int addr=ur.pfend+1-devnmeta; addr < ur.pfend+1; addr++) {
if(!(flm->tags[addr] & TAG_ALLOCATED)) { if(addr >=0 && addr < flm->size && !(flm->tags[addr] & TAG_ALLOCATED)) {
flm->tags[addr] |= TAG_ALLOCATED; flm->tags[addr] |= TAG_ALLOCATED;
flm->buf[addr] = 0xff; flm->buf[addr] = 0xff;
} }
@ -801,7 +813,7 @@ nopatch_nometa:
// Ensure that vector bootloaders have correct r/jmp at address 0 // Ensure that vector bootloaders have correct r/jmp at address 0
if(ur.blstart && ur.vbllevel==1) { if(ur.boothigh && ur.blstart && ur.vbllevel == 1) {
int rc, set=0; int rc, set=0;
for(int i=0; i < vecsz; i++) for(int i=0; i < vecsz; i++)
if(flm->tags[i] & TAG_ALLOCATED) if(flm->tags[i] & TAG_ALLOCATED)
@ -1180,7 +1192,10 @@ static void guessblstart(const PROGRAMMER *pgm, const AVRPART *p) {
for(ii = 0; ii < (int) (sizeof blist/sizeof*blist); ii++) for(ii = 0; ii < (int) (sizeof blist/sizeof*blist); ii++)
if(blist[ii].hash == hash && sz == blist[ii].sz && !(sz & (ur.uP.pagesize-1))) { if(blist[ii].hash == hash && sz == blist[ii].sz && !(sz & (ur.uP.pagesize-1))) {
// Page aligned bootloader size matches // Page aligned bootloader size matches
ur.blstart = ur.uP.flashsize-sz; ur.blstart = ur.uP.flashsize - sz;
ur.blend = ur.uP.flashsize - 1;
ur.pfend = ur.blstart - 1;
if(blist[ii].ee) if(blist[ii].ee)
ur.bleepromrw = 1; ur.bleepromrw = 1;
ur.blguessed = 1; ur.blguessed = 1;
@ -1297,26 +1312,42 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
"use correct -p ... or override with -F", "use correct -p ... or override with -F",
ur.uP.name, ur.uP.ninterrupts, p->desc, p->n_interrupts); ur.uP.name, ur.uP.ninterrupts, p->desc, p->n_interrupts);
// No urboot bootloaders on AVR32 parts, neither on really small devices // Initialse so that programmable flash is all flash and no bootloader
if((p->prog_modes & PM_aWire) || flm->size < 512) ur.pfstart = 0;
goto alldone; ur.pfend = flm->size-1;
ur.blstart = 0; ur.blstart = 0;
ur.blend = 0;
ur.vbllevel = 0; ur.vbllevel = 0;
ur.vblvectornum = -1; ur.vblvectornum = -1;
ur.bleepromrw = 0; ur.bleepromrw = 0;
// No urboot bootloaders on AVR32 parts, neither on really small devices
if((p->prog_modes & PM_aWire) || flm->size < 512)
goto alldone;
// UPDI parts have bootloader in low flash
ur.boothigh = !(p->prog_modes & PM_UPDI);
// Manual provision of above bootloader parameters // Manual provision of above bootloader parameters
if(ur.xbootsize) { if(ur.xbootsize) {
if(ur.xbootsize % ur.uP.pagesize) if(ur.boothigh && ur.xbootsize % ur.uP.pagesize)
Return("-xbootsize=%d size not a multiple of flash page size %d", Return("-xbootsize=%d size not a multiple of flash page size %d",
ur.xbootsize, ur.uP.pagesize); ur.xbootsize, ur.uP.pagesize);
if(ur.xbootsize < 64 || ur.xbootsize > urmin(8192, ur.uP.flashsize/4)) if(ur.xbootsize < 64 || ur.xbootsize > urmin(8192, ur.uP.flashsize/4))
Return("implausible -xbootsize=%d, should be in [64, %d]", Return("implausible -xbootsize=%d, should be in [64, %d]",
ur.xbootsize, urmin(8192, ur.uP.flashsize/4)); ur.xbootsize, urmin(8192, ur.uP.flashsize/4));
ur.blstart = ur.uP.flashsize - ur.xbootsize; if(ur.boothigh) {
ur.blstart = flm->size - ur.xbootsize;
ur.blend = flm->size - 1;
ur.pfend = ur.blstart - 1;
} else {
ur.blstart = 0;
ur.blend = ur.xbootsize - 1;
ur.pfstart = ur.blend + 1;
}
} }
if(ur.boothigh) {
if((int8_t) ur.uP.ninterrupts >= 0) // valid range is 0..127 if((int8_t) ur.uP.ninterrupts >= 0) // valid range is 0..127
if(ur.xvectornum < -1 || ur.xvectornum > ur.uP.ninterrupts) if(ur.xvectornum < -1 || ur.xvectornum > ur.uP.ninterrupts)
Return("unknown interrupt vector #%d for vector bootloader -- should be in [-1, %d]", Return("unknown interrupt vector #%d for vector bootloader -- should be in [-1, %d]",
@ -1325,15 +1356,19 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
ur.vbllevel = 1; ur.vbllevel = 1;
ur.vblvectornum = ur.xvectornum; ur.vblvectornum = ur.xvectornum;
} }
} else if(ur.xvectornum != -1) {
Return("UPDI part %s does not support vector bootloaders", ur.uP.name);
}
if(ur.urprotocol && !(ur.urfeatures & UB_READ_FLASH)) // Bootloader that cannot read flash? if(ur.urprotocol && !(ur.urfeatures & UB_READ_FLASH)) // Bootloader that cannot read flash?
if(!ur.blstart) if(ur.blend <= ur.blstart)
Return("please specify -xbootsize=<num> and, if needed, -xvectornum=<num> or -xeepromrw"); Return("please specify -xbootsize=<num> and, if needed, %s-xeepromrw",
ur.boothigh? "-xvectornum=<num> or ": "");
uint16_t v16 = 0xffff, rjmpwp = ret_opcode; uint16_t v16 = 0xffff, rjmpwp = ret_opcode;
// Sporting chance that we can read top flash to get intell about bootloader // Sporting chance that we can read top flash to get intell about bootloader?
if(!ur.urprotocol || (ur.urfeatures & UB_READ_FLASH)) { if(ur.boothigh && (!ur.urprotocol || (ur.urfeatures & UB_READ_FLASH))) {
// Read top 6 bytes from flash memory to obtain extended information about bootloader and type // Read top 6 bytes from flash memory to obtain extended information about bootloader and type
if((rc = ur_readEF(pgm, p, spc, flm->size-6, 6, 'F'))) if((rc = ur_readEF(pgm, p, spc, flm->size-6, 6, 'F')))
return rc; return rc;
@ -1369,14 +1404,17 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
return -1; return -1;
} }
} }
} else } else {
ur.blstart = flm->size - blsize; ur.blstart = flm->size - blsize;
ur.blend = flm->size - 1;
ur.pfend = ur.blstart - 1;
}
if(ur.xvectornum != -1) { if(ur.xvectornum != -1) {
if(ur.vblvectornum != vectnum) { if(ur.vblvectornum != vectnum) {
pmsg_warning("urboot vector number %d overwritten by -xvectornum=%d\n", pmsg_warning("urboot vector number %d overwritten by -xvectornum=%d\n",
vectnum, ur.xvectornum); vectnum, ur.xvectornum);
imsg_warning("the application might not start\n"); imsg_warning("the application might not start correctly\n");
} }
} else } else
ur.vblvectornum = vectnum; ur.vblvectornum = vectnum;
@ -1387,7 +1425,7 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
ur.bloptiversion = (urver<<8) + cap; ur.bloptiversion = (urver<<8) + cap;
} }
if(!ur.blstart && ur.vbllevel) { // An older version urboot vector bootloader? if(ur.blend <= ur.blstart && ur.vbllevel) { // An older version urboot vector bootloader?
int vecsz = ur.uP.flashsize <= 8192? 2: 4; int vecsz = ur.uP.flashsize <= 8192? 2: 4;
// Reset vector points to the bootloader and the bootloader has r/jmp to application? // Reset vector points to the bootloader and the bootloader has r/jmp to application?
@ -1402,21 +1440,27 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
while(guess < 0) // Convert to absolute address while(guess < 0) // Convert to absolute address
guess += flm->size; guess += flm->size;
if((guess & (flm->page_size-1)) == 0) // Page aligned? Good if((guess & (flm->page_size-1)) == 0) // Page aligned? Good
if(flm->size - guess <= 2048) // Accept unless size of bootloader exceeds 2048 bytes if(flm->size - guess <= 2048) { // Accept unless size of bootloader exceeds 2048 bytes
ur.blstart = guess; ur.blstart = guess;
ur.blend = flm->size - 1;
ur.pfend = guess - 1;
}
} }
} else if(vecsz == 4 && isJmp(reset16)) { // Jmp op code } else if(vecsz == 4 && isJmp(reset16)) { // Jmp op code
int guess = addr_jmp(buf2uint32(spc)); int guess = addr_jmp(buf2uint32(spc));
if(guess < flm->size) if(guess < flm->size)
if((guess & (flm->page_size-1)) == 0) // Page aligned? Good if((guess & (flm->page_size-1)) == 0) // Page aligned? Good
if(flm->size - guess <= 2048) // Accept unless size of bootloader exceeds 2048 bytes if(flm->size - guess <= 2048) { // Accept unless size of bootloader exceeds 2048 bytes
ur.blstart = guess; ur.blstart = guess;
ur.blend = flm->size - 1;
ur.pfend = guess - 1;
}
} }
if(ur.blstart && ur.vblvectornum > 0) if(ur.blend > ur.blstart && ur.vblvectornum > 0)
goto vblvecfound; goto vblvecfound;
if(ur.blstart) { // Read bootloader to identify jump to vbl vector if(ur.blend > ur.blstart) { // Read bootloader to identify jump to vbl vector
int i, npages, j, n, toend, dist, wasop32, wasjmp, op16; int i, npages, j, n, toend, dist, wasop32, wasjmp, op16;
uint8_t *q; uint8_t *q;
uint16_t opcode; uint16_t opcode;
@ -1459,30 +1503,31 @@ static int ur_initstruct(const PROGRAMMER *pgm, const AVRPART *p) {
} }
// Still no bootloader start address? Read in top flash and guess bootloader start // Still no bootloader start address? Read in top flash and guess bootloader start
if(!ur.blstart) if(ur.blend <= ur.blstart)
guessblstart(pgm, p); guessblstart(pgm, p);
// Still no bootloader start address? // Still no bootloader start address?
if(!ur.blstart) { if(ur.blend <= ur.blstart) {
if(ur. bloptiversion) if(ur. bloptiversion)
Return("bootloader might be optiboot %d.%d? Please use -xbootsize=<num>\n", Return("bootloader might be optiboot %d.%d? Please use -xbootsize=<num>\n",
ur.bloptiversion>>8, ur.bloptiversion & 255); ur.bloptiversion>>8, ur.bloptiversion & 255);
Return("unknown bootloader ... please specify -xbootsize=<num>\n"); Return("unknown bootloader ... please specify -xbootsize=<num>\n");
} }
} else if(!ur.boothigh) { // Fixme: guess bootloader size from low flash
} }
vblvecfound: vblvecfound:
urbootPutVersion(pgm, ur.desc, v16, rjmpwp); urbootPutVersion(pgm, ur.desc, v16, rjmpwp);
ur.mcode = 0xff; ur.mcode = 0xff;
if(ur.blstart) { if(ur.pfend >= nmeta(254, flm->size)) {
int nm = nmeta(1, ur.uP.flashsize); // 6 for date + size of store struct + 1 for mcode byte int nm = nmeta(1, ur.uP.flashsize); // 6 for date + size of store struct + 1 for mcode byte
// Showing properties mostly requires examining the bytes below bootloader for metadata // Showing properties mostly requires examining the bytes below bootloader for metadata
if(ur.showall || (ur.showid && *ur.iddesc && *ur.iddesc != 'E') || ur.showapp || if(ur.showall || (ur.showid && *ur.iddesc && *ur.iddesc != 'E') || ur.showapp ||
ur.showstore || ur.showmeta || ur.showboot || ur.showversion || ur.showvector || ur.showstore || ur.showmeta || ur.showboot || ur.showversion || ur.showvector ||
ur.showpart || ur.showdate || ur.showfilename) { ur.showpart || ur.showdate || ur.showfilename) {
if((rc = ur_readEF(pgm, p, spc, ur.blstart-nm, nm, 'F'))) if((rc = ur_readEF(pgm, p, spc, ur.pfend+1-nm, nm, 'F')))
return rc; return rc;
if(spc[nm-1] != 0xff) { if(spc[nm-1] != 0xff) {
@ -1492,7 +1537,7 @@ vblvecfound:
int nmdata = nmeta(mcode, ur.uP.flashsize); int nmdata = nmeta(mcode, ur.uP.flashsize);
// Check plausibility of metadata header just below bootloader // Check plausibility of metadata header just below bootloader
if(storestart > 0 && storestart == ur.blstart-nmdata-storesize) { if(storestart > 0 && storestart == ur.pfend+1-nmdata-storesize) {
ur.storestart = storestart; ur.storestart = storestart;
ur.storesize = storesize; ur.storesize = storesize;
ur.mcode = mcode; ur.mcode = mcode;
@ -1515,7 +1560,7 @@ vblvecfound:
ur.hr = hr; ur.hr = hr;
ur.mn = mn; ur.mn = mn;
if(mcode > 1) { // Copy application name over if(mcode > 1) { // Copy application name over
rc = ur_readEF(pgm, p, spc, ur.blstart-nmeta(mcode, ur.uP.flashsize), mcode, 'F'); rc = ur_readEF(pgm, p, spc, ur.pfend+1-nmeta(mcode, ur.uP.flashsize), mcode, 'F');
if(rc < 0) if(rc < 0)
return rc; return rc;
int len = mcode<sizeof ur.filename? mcode: sizeof ur.filename; int len = mcode<sizeof ur.filename? mcode: sizeof ur.filename;
@ -1553,7 +1598,7 @@ vblvecfound:
if(ur.showmeta || ur.showall) if(ur.showmeta || ur.showall)
term_out(&" %s%d"[first], single? "": "meta ", nmeta(ur.mcode, ur.uP.flashsize)), first=0; term_out(&" %s%d"[first], single? "": "meta ", nmeta(ur.mcode, ur.uP.flashsize)), first=0;
if(ur.showboot || ur.showall) if(ur.showboot || ur.showall)
term_out(&" %s%d"[first], single? "": "boot ", ur.blstart? flm->size-ur.blstart: 0), first=0; term_out(&" %s%d"[first], single? "": "boot ", ur.blend>ur.blstart? ur.blend-ur.blstart+1: 0), first=0;
if(ur.showversion || ur.showall) if(ur.showversion || ur.showall)
term_out(&" %s"[first], ur.desc+(*ur.desc==' ')), first=0; term_out(&" %s"[first], ur.desc+(*ur.desc==' ')), first=0;
if(ur.showvector || ur.showall) { if(ur.showvector || ur.showall) {
@ -1640,7 +1685,7 @@ static int urclock_paged_rdwr(const PROGRAMMER *pgm, const AVRPART *part, char r
if(len != ur.uP.pagesize) if(len != ur.uP.pagesize)
Return("len %d must be page size %d for paged flash writes", len, ur.uP.pagesize); Return("len %d must be page size %d for paged flash writes", len, ur.uP.pagesize);
if(badd < 4U && ur.blstart && ur.vbllevel==1) { if(badd < 4U && ur.boothigh && ur.blstart && ur.vbllevel==1) {
int vecsz = ur.uP.flashsize <= 8192? 2: 4; int vecsz = ur.uP.flashsize <= 8192? 2: 4;
unsigned char jmptoboot[4]; unsigned char jmptoboot[4];
int resetsize = set_reset(pgm, jmptoboot, vecsz); int resetsize = set_reset(pgm, jmptoboot, vecsz);
@ -1941,7 +1986,7 @@ static int urclock_getsync(const PROGRAMMER *pgm) {
break; break;
} else { // Board not yet out of reset or bootloader twiddles lights } else { // Board not yet out of reset or bootloader twiddles lights
int slp = 32<<(attempt<3? attempt: 3); int slp = 32<<(attempt<3? attempt: 3);
pmsg_debug("%4d ms: sleeping for %d ms\n", avr_mstimestamp(), slp); pmsg_debug("%4ld ms: sleeping for %d ms\n", avr_mstimestamp(), slp);
usleep(slp*1000); usleep(slp*1000);
} }
if(attempt > 5) { // Don't report first six attempts if(attempt > 5) { // Don't report first six attempts
@ -2105,7 +2150,7 @@ static int urclock_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
ur.done_ce = 1; ur.done_ce = 1;
if(!emulated) { // Write jump to boot section to reset vector if(!emulated) { // Write jump to boot section to reset vector
if(ur.blstart && ur.vbllevel==1) { if(ur.boothigh && ur.blstart && ur.vbllevel==1) {
AVRMEM *flm = avr_locate_mem(p, "flash"); AVRMEM *flm = avr_locate_mem(p, "flash");
int vecsz = ur.uP.flashsize <= 8192? 2: 4; int vecsz = ur.uP.flashsize <= 8192? 2: 4;
if(flm && flm->page_size >= vecsz) { if(flm && flm->page_size >= vecsz) {
@ -2202,10 +2247,10 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) {
serial_drain_timeout = 20; // ms serial_drain_timeout = 20; // ms
serial_drain(&pgm->fd, 0); serial_drain(&pgm->fd, 0);
pmsg_debug("%4d ms: enter urclock_getsync()\n", avr_mstimestamp()); pmsg_debug("%4ld ms: enter urclock_getsync()\n", avr_mstimestamp());
if(urclock_getsync(pgm) < 0) if(urclock_getsync(pgm) < 0)
return -1; return -1;
pmsg_debug("%4d ms: all good, ready to rock\n", avr_mstimestamp()); pmsg_debug("%4ld ms: all good, ready to rock\n", avr_mstimestamp());
return 0; return 0;
} }
@ -2282,7 +2327,7 @@ static int urclock_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR
if(addr == 0 && mchr == 'F') { // Ensure reset vector points to bl if(addr == 0 && mchr == 'F') { // Ensure reset vector points to bl
int vecsz = ur.uP.flashsize <= 8192? 2: 4; int vecsz = ur.uP.flashsize <= 8192? 2: 4;
if(chunk >= vecsz && ur.blstart && ur.vbllevel == 1) { if(chunk >= vecsz && ur.boothigh && ur.blstart && ur.vbllevel == 1) {
unsigned char jmptoboot[4]; unsigned char jmptoboot[4];
int resetsize = set_reset(pgm, jmptoboot, vecsz); int resetsize = set_reset(pgm, jmptoboot, vecsz);
int resetdest; int resetdest;
@ -2365,10 +2410,11 @@ static int urclock_readonly(const struct programmer_t *pgm, const AVRPART *p_unu
const AVRMEM *mem, unsigned int addr) { const AVRMEM *mem, unsigned int addr) {
if(avr_mem_is_flash_type(mem)) { if(avr_mem_is_flash_type(mem)) {
if(ur.blstart) { if(addr > (unsigned int) ur.pfend)
if(addr >= (unsigned int) ur.blstart)
return 1; return 1;
if(addr < 512 && ur.vbllevel) { if(addr < (unsigned int) ur.pfstart)
return 1;
if(ur.boothigh && addr < 512 && ur.vbllevel) {
unsigned int vecsz = ur.uP.flashsize <= 8192? 2u: 4u; unsigned int vecsz = ur.uP.flashsize <= 8192? 2u: 4u;
if(addr < vecsz) if(addr < vecsz)
return 1; return 1;
@ -2378,7 +2424,6 @@ static int urclock_readonly(const struct programmer_t *pgm, const AVRPART *p_unu
return 1; return 1;
} }
} }
}
} else if(!avr_mem_is_eeprom_type(mem)) } else if(!avr_mem_is_eeprom_type(mem))
return 1; return 1;