Progressively shrink metadata for -c urclock

This commit is contained in:
Stefan Rueger
2023-05-03 00:19:52 +01:00
parent bda26d3984
commit a894dbb908
4 changed files with 156 additions and 77 deletions

View File

@@ -1405,10 +1405,24 @@ On writing to flash do not store the application input filename (nor a title).
.It Ar nodate
On writing to flash do not store the application input filename (nor a
title) and no date either.
.It Ar nostore
On writing to flash do not store metadata except the metadata code byte
0xff saying there are no metadata. In particular, no data store frame is
programmed.
.It Ar nometadata
On writing to flash do not store any metadata. The full flash below the
bootloader is available for the application. In particular, no data store
frame is programmed.
Do not support any metadata. The full flash besides the bootloader is
available for the application. If the application is smaller than the
available space then a metadata code byte 0xff is stored nevertheless to
indicate there are no further metadata available. In absence of
-xnometadata, the default for the urclock programmer is to write as much
metadata (filename, data and store information) as the size of the
uploaded application and the other extended options allow. The subtle
difference between -xnometadata and -xnostore is that the latter always
explicitly stores in flash that no further metadata are available, so that
a such prepared flash can always be queried with
.Nm
-xshowall. In contrast to this, it cannot be guaranteed that a -xshowall
query on flash prepared with -xnometadata yields useful results.
.It Ar delay=<n>
Add a <n> ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. <n> can be negative,

View File

@@ -1166,10 +1166,24 @@ On writing to flash do not store the application input filename (nor a title).
@item @samp{nodate}
On writing to flash do not store the application input filename (nor a
title) and no date either.
@item @samp{nometadata}
On writing to flash do not store any metadata. The full flash below the
bootloader is available for the application. In particular, no data store
@item @samp{nostore}
On writing to flash do not store metadata except the metadata code byte
@code{0xff} saying there are no metadata. In particular, no data store
frame is programmed.
@item @samp{nometadata}
Do not support any metadata. The full flash besides the bootloader is
available for the application. If the application is smaller than the
available space then a metadata code byte @code{0xff} is stored
nevertheless to indicate there are no further metadata available. In
absence of @code{-xnometadata}, the default for the urclock programmer is
to write as much metadata (filename, data and store information) as the
size of the uploaded application and the other extended options allow. The
subtle difference between @code{-xnometadata} and @code{-xnostore} is that
the latter always explicitly stores in flash that no further metadata are
available, so that a such prepared flash can always be queried with
@code{avrdude -xshowall}. In contrast to this, it cannot be guaranteed
that a @code{-xshowall} query on flash prepared with @code{-xnometadata}
yields useful results.
@item @samp{delay=<n>}
Add a <n> ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. <n> can be negative,

View File

@@ -290,8 +290,8 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
* by outbuf. The size of outbuf, 'bufsize' is honored; if data would
* fall outsize of the memory buffer outbuf, an error is generated.
*
* Return the maximum memory address within 'outbuf' that was written.
* If an error occurs, return -1.
* Return the maximum memory address within 'outbuf' that was written
* plus one. If an error occurs, return -1.
*
* */
static int ihex2b(const char *infile, FILE *inf,

View File

@@ -315,7 +315,8 @@ typedef struct {
restore, // Restore a flash backup exactly as it is trimming the bootloader
nofilename, // Don't store application filename when writing the application
nodate, // Don't store application filename and no date either
nometadata, // Don't store any metadata at all (implies no store support)
nostore, // Don't store metadata except a flag saying so
nometadata, // Don't support metadata at all
delay, // Additional delay [ms] after resetting the board, can be negative
strict; // Use strict synchronisation protocol
@@ -334,7 +335,7 @@ static int nmeta(int mcode, int flashsize) {
// The size of the structure that holds info about metadata (sits just below bootloader)
int nheader = 2*(flashsize > (1<<16)? 4: 2) + 1;
return mcode == 0xff? 0: // No metadata at all
return mcode == 0xff? 1: // No metadata except 0xff byte itself saying no further metadata
mcode > 1? mcode+6+nheader: // Application filename, app date and structure for pgm store
mcode? 6+nheader: // Application date and structure describing pgm store
nheader; // Structure describing pgm store
@@ -610,16 +611,17 @@ static int set_reset(const PROGRAMMER *pgm, unsigned char *jmptoboot, int vecsz)
// Called after the input file has been read for writing or verifying flash
static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *flm,
const char *fname, int size) {
const char *fname, int size) { // size is max memory address + 1
int nmdata, maxsize, firstbeg, firstlen;
int vecsz = ur.uP.flashsize <= 8192? 2: 4; // Small parts use rjmp, large parts need 4-byte jmp
set_date_filename(pgm, fname);
// Record how extensive the metadata should be, given the command line options (default: all)
ur.mcode = ur.nometadata? 0xff: ur.nodate? 0: ur.nofilename? 1: strlen(ur.filename)+1;
nmdata = nmeta(ur.mcode, ur.uP.flashsize);
// Record extent of metadata, given the command line options (default: max possible)
ur.mcode = ur.nometadata || ur.nostore? 0xff:
ur.nodate? 0: ur.nofilename? 1: strlen(ur.filename)+1;
nmdata = ur.nometadata? 0: nmeta(ur.mcode, ur.uP.flashsize);
maxsize = ur.pfend+1;
@@ -652,21 +654,43 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
ur.blstart, ur.blend, flm->size-1);
// Check size of uploded application and protect bootloader from being overwritten
if((ur.boothigh && size > ur.pfend+1) || (!ur.boothigh && firstbeg <= ur.blend))
if((ur.boothigh && size > maxsize) || (!ur.boothigh && firstbeg <= ur.blend))
Return("input [0x%04x, 0x%04x] overlaps bootloader [0x%04x, 0x%04x]",
firstbeg, size-1, ur.blstart, ur.blend);
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",
firstbeg, size-1, ur.pfend+1-nmeta(0, ur.uP.flashsize), ur.pfend);
if(size > maxsize)
Return("input [0x%04x, 0x%04x] extends programmable area [0x%04x, 0x%04x]",
firstbeg, size-1, ur.pfstart, ur.pfend);
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",
firstbeg, size-1, ur.pfend+1-nmeta(1, ur.uP.flashsize), ur.pfend);
if(!ur.nometadata) {
if(size == maxsize)
Return("input [0x%04x, 0x%04x] overlaps metadata code byte at 0x%04x, consider -xnometadata",
firstbeg, size-1, ur.pfend);
if(size > ur.pfend+1 - nmdata)
Return("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], consider -xnofilename",
firstbeg, size-1, ur.pfend+1-nmdata, ur.pfend);
if(nmdata >= nmeta(0, ur.uP.flashsize) && size > maxsize - nmeta(0, ur.uP.flashsize)) {
pmsg_warning("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], selecting -xnostore\n",
firstbeg, size-1, maxsize-nmdata, ur.pfend);
ur.mcode = 0xff;
ur.nostore = 1;
nmdata = 1;
}
if(nmdata >= nmeta(1, ur.uP.flashsize) && size > maxsize - nmeta(1, ur.uP.flashsize)) {
pmsg_warning("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], selecting -xnodate\n",
firstbeg, size-1, maxsize-nmdata, ur.pfend);
ur.mcode = 0;
ur.nodate = 1;
nmdata = nmeta(0, ur.uP.flashsize);
}
if(size > maxsize - nmdata) {
pmsg_warning("input [0x%04x, 0x%04x] overlaps metadata [0x%04x, 0x%04x], selecting -xnofilename\n",
firstbeg, size-1, maxsize-nmdata, ur.pfend);
ur.mcode = 1;
ur.nofilename = 1;
nmdata = nmeta(1, ur.uP.flashsize);
}
}
if(!ur.boothigh)
goto nopatch;
@@ -736,53 +760,56 @@ static int urclock_flash_readhook(const PROGRAMMER *pgm, const AVRPART *p, const
nopatch:
if(nmdata) {
int32_t nfree = ur.pfend+1 - size;
int32_t nfree = maxsize - size;
if(nfree >= nmdata) {
unsigned char *p = flm->buf + ur.pfend+1 - nmdata;
unsigned char *p = flm->buf + maxsize - nmdata;
if(ur.mcode > 1) { // Save filename (ur.mcode cannot be 0xff b/c nmdata is non-zero)
memcpy(p, ur.filename, ur.mcode);
p += ur.mcode;
if(ur.mcode != 0xff) {
if(ur.mcode > 1) { // Save filename
memcpy(p, ur.filename, ur.mcode);
p += ur.mcode;
}
if(ur.mcode >= 1) { // Save date
*p++ = ur.yyyy;
*p++ = ur.yyyy>>8;
*p++ = ur.mm;
*p++ = ur.dd;
*p++ = ur.hr;
*p++ = ur.mn;
}
*p++ = size; // Save where the pgm store begins
*p++ = size >> 8;
if(ur.uP.flashsize > (1<<16)) {
*p++ = size >> 16;
*p++ = size >> 24;
}
nfree -= nmdata;
*p++ = nfree; // Save how much is free
*p++ = nfree >> 8;
if(ur.uP.flashsize > (1<<16)) {
*p++ = nfree >> 16;
*p++ = nfree >> 24;
}
}
if(ur.mcode >= 1) { // Save date
*p++ = ur.yyyy;
*p++ = ur.yyyy>>8;
*p++ = ur.mm;
*p++ = ur.dd;
*p++ = ur.hr;
*p++ = ur.mn;
}
*p++ = size; // Save where the pgm store begins
*p++ = size >> 8;
if(ur.uP.flashsize > (1<<16)) {
*p++ = size >> 16;
*p++ = size >> 24;
}
nfree -= nmdata;
*p++ = nfree; // Save how much is free
*p++ = nfree >> 8;
if(ur.uP.flashsize > (1<<16)) {
*p++ = nfree >> 16;
*p++ = nfree >> 24;
}
*p++ = ur.mcode;
*p++ = ur.mcode; // Save metadata code
// Set tags so metadata get burned onto chip
memset(flm->tags + ur.pfend+1 - nmdata, TAG_ALLOCATED, nmdata);
memset(flm->tags + maxsize - nmdata, TAG_ALLOCATED, nmdata);
if(ur.initstore) // Zap the pgm store
memset(flm->tags + size, TAG_ALLOCATED, nfree);
size = ur.pfend+1;
size = maxsize;
}
}
// Storing no metadata: put a 0xff byte just below bootloader
if(size < ur.pfend+1 && nmdata == 0) {
// Storing no metadata? Still put a 0xff byte just below bootloader if there is space
if(size < maxsize && nmdata == 0) {
flm->buf[ur.pfend] = 0xff;
flm->tags[ur.pfend] = TAG_ALLOCATED;
size = ur.pfend+1;
@@ -796,7 +823,7 @@ nopatch_nometa:
if(ur_readEF(pgm, p, &devmcode, ur.pfend, 1, 'F') == 0) {
int devnmeta=nmeta(devmcode, ur.uP.flashsize);
for(int addr=ur.pfend+1-devnmeta; addr < ur.pfend+1; addr++) {
if(addr >=0 && addr < flm->size && !(flm->tags[addr] & TAG_ALLOCATED)) {
if(addr >= 0 && addr < flm->size && !(flm->tags[addr] & TAG_ALLOCATED)) {
flm->tags[addr] |= TAG_ALLOCATED;
flm->buf[addr] = 0xff;
}
@@ -1523,7 +1550,9 @@ vblvecfound:
urbootPutVersion(pgm, ur.desc, v16, rjmpwp);
ur.mcode = 0xff;
if(ur.pfend >= nmeta(254, flm->size)) {
int havemetadata = !ur.nometadata;
if(havemetadata && ur.pfend >= nmeta(254, flm->size)) {
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
if(ur.showall || (ur.showid && *ur.iddesc && *ur.iddesc != 'E') || ur.showapp ||
@@ -1540,11 +1569,14 @@ vblvecfound:
int nmdata = nmeta(mcode, ur.uP.flashsize);
// Check plausibility of metadata header just below bootloader
havemetadata = 0;
if(storestart > 0 && storestart == ur.pfend+1-nmdata-storesize) {
ur.storestart = storestart;
ur.storesize = storesize;
ur.mcode = mcode;
if(mcode) {
if(!mcode) {
havemetadata = 1;
} else {
int16_t yyyy;
int8_t mm, dd, hr, mn;
mn = spc[5];
@@ -1562,6 +1594,7 @@ vblvecfound:
ur.dd = dd;
ur.hr = hr;
ur.mn = mn;
havemetadata = 1;
if(mcode > 1) { // Copy application name over
rc = ur_readEF(pgm, p, spc, ur.pfend+1-nmeta(mcode, ur.uP.flashsize), mcode, 'F');
if(rc < 0)
@@ -1577,7 +1610,6 @@ vblvecfound:
}
}
// Print and exit when option show... was given
int first=1;
int single = !ur.showall && (!!ur.showid + !!ur.showapp + !!ur.showstore + !!ur.showmeta +
@@ -1590,23 +1622,41 @@ vblvecfound:
return rc;
term_out("%0*lx", 2*ur.idlen, urclockID), first=0;
}
if(ur.showdate || ur.showall)
term_out(&" %04d-%02d-%02d %02d.%02d"[first], ur.yyyy, ur.mm, ur.dd, ur.hr, ur.mn), first=0;
if(ur.showfilename || ur.showall)
term_out(&" %s"[first], *ur.filename? ur.filename: ""), first=0;
if(ur.showapp || ur.showall)
term_out(&" %s%d"[first], single || *ur.filename? "": "application ", ur.storestart), first=0;
if(ur.showstore || ur.showall)
term_out(&" %s%d"[first], single? "": "store ", ur.storesize), first=0;
if(ur.showmeta || ur.showall)
term_out(&" %s%d"[first], single? "": "meta ", nmeta(ur.mcode, ur.uP.flashsize)), first=0;
if(ur.showboot || ur.showall)
term_out(&" %s%d"[first], single? "": "boot ", ur.blend>ur.blstart? ur.blend-ur.blstart+1: 0), first=0;
if(ur.showversion || ur.showall)
term_out(&" %s"[first], ur.desc+(*ur.desc==' ')), first=0;
if(havemetadata) {
if(ur.showdate || ur.showall) {
term_out(&" %04d-%02d-%02d %02d.%02d"[first], ur.yyyy, ur.mm, ur.dd, ur.hr, ur.mn);
first=0;
}
if(ur.showfilename || ur.showall) {
term_out(&" %s"[first], *ur.filename? ur.filename: "");
first=0;
}
if(ur.showapp || ur.showall) {
term_out(&" %s%d"[first], single || *ur.filename? "": "application ", ur.storestart);
first=0;
}
if(ur.showstore || ur.showall) {
term_out(&" %s%d"[first], single? "": "store ", ur.storesize);
first=0;
}
}
if(ur.showmeta || ur.showall) {
int nmdata = havemetadata? nmeta(ur.mcode, ur.uP.flashsize): 0;
term_out(&" %s%d"[first], single? "": "meta ", nmdata);
first=0;
}
if(ur.showboot || ur.showall) {
term_out(&" %s%d"[first], single? "": "boot ", ur.blend>ur.blstart? ur.blend-ur.blstart+1: 0);
first=0;
}
if(ur.showversion || ur.showall) {
term_out(&" %s"[first], ur.desc+(*ur.desc==' '));
first=0;
}
if(ur.showvector || ur.showall) {
int vnum = ur.vbllevel? ur.vblvectornum & 0x7f: 0;
term_out(&" vector %d (%s)"[first], vnum, vblvecname(pgm, vnum)), first=0;
term_out(&" vector %d (%s)"[first], vnum, vblvecname(pgm, vnum));
first=0;
}
if(ur.showall || ur.showpart)
term_out(&" %s"[first], ur.uP.name);
@@ -2466,7 +2516,8 @@ static int urclock_parseextparms(const PROGRAMMER *pgm, LISTID extparms) {
//@@@ {"copystore", &ur.copystore, NA, "Copy over store on writing to flash"},
{"nofilename", &ur.nofilename, NA, "Do not store filename on writing to flash"},
{"nodate", &ur.nodate, NA, "Do not store application filename and no date either"},
{"nometadata", &ur.nometadata, NA, "Do not store metadata at all (ie, no store support)"},
{"nostore", &ur.nostore, NA, "Do not store metadata except a flag saying so"},
{"nometadata", &ur.nometadata, NA, "Do not support metadata at all"},
{"delay", &ur.delay, ARG, "Add delay [ms] after reset, can be negative"},
{"strict", &ur.strict, NA, "Use strict synchronisation protocol"},
{"help", &help, NA, "Show this help menu and exit"},