/*
* S-records dump routine -- dumps S-records on the console
*/
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include <minmax.h>
#include "upload_backend.h"
/* Write a single S-record */
static int write_srecord(unsigned int len, unsigned int alen,
uint32_t addr, uint8_t type, const void *data)
{
char buf[2+2+8+255*2+2+2];
char *p = buf;
uint8_t csum;
const uint8_t *dptr = data;
unsigned int i;
switch (alen) {
case 2:
addr &= 0xffff;
break;
case 3:
addr &= 0xffffff;
break;
case 4:
break;
}
csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
for (i = 0; i < len; i++)
csum += dptr[i];
csum = 0xff-csum;
p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
for (i = 0; i < len; i++)
p += sprintf(p, "%02X", dptr[i]);
p += sprintf(p, "%02X\n", csum);
fputs(buf, stdout);
return 0;
}
static int upload_srec_write(struct upload_backend *be)
{
char name[33];
const char *buf;
size_t len, chunk, offset, hdrlen;
buf = be->outbuf;
len = be->zbytes;
putchar('\n');
hdrlen = snprintf(name, sizeof name, "%.32s",
be->argv[0] ? be->argv[0] : "");
/* Write head record */
write_srecord(hdrlen, 2, 0, '0', name);
/* Write data records */
offset = 0;
while (len) {
chunk = min(len, (size_t)32);
write_srecord(chunk, 4, offset, '3', buf);
buf += chunk;
len -= chunk;
offset += chunk;
}
/* Write termination record */
write_srecord(0, 4, 0, '7', NULL);
return 0;
}
struct upload_backend upload_srec = {
.name = "srec",
.helpmsg = "[filename]",
.minargs = 0,
.write = upload_srec_write,
};