Home | History | Annotate | Download | only in libupload
      1 /*
      2  * S-records dump routine -- dumps S-records on the console
      3  */
      4 
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <inttypes.h>
      8 #include <minmax.h>
      9 #include "upload_backend.h"
     10 
     11 /* Write a single S-record */
     12 static int write_srecord(unsigned int len,  unsigned int alen,
     13                          uint32_t addr, uint8_t type, const void *data)
     14 {
     15     char buf[2+2+8+255*2+2+2];
     16     char *p = buf;
     17     uint8_t csum;
     18     const uint8_t *dptr = data;
     19     unsigned int i;
     20 
     21     switch (alen) {
     22     case 2:
     23         addr &= 0xffff;
     24         break;
     25     case 3:
     26         addr &= 0xffffff;
     27         break;
     28     case 4:
     29         break;
     30     }
     31 
     32     csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
     33     for (i = 0; i < len; i++)
     34         csum += dptr[i];
     35     csum = 0xff-csum;
     36 
     37     p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
     38     for (i = 0; i < len; i++)
     39         p += sprintf(p, "%02X", dptr[i]);
     40     p += sprintf(p, "%02X\n", csum);
     41 
     42     fputs(buf, stdout);
     43     return 0;
     44 }
     45 
     46 static int upload_srec_write(struct upload_backend *be)
     47 {
     48     char name[33];
     49     const char *buf;
     50     size_t len, chunk, offset, hdrlen;
     51 
     52     buf = be->outbuf;
     53     len = be->zbytes;
     54 
     55     putchar('\n');
     56 
     57     hdrlen = snprintf(name, sizeof name, "%.32s",
     58 		      be->argv[0] ? be->argv[0] : "");
     59 
     60     /* Write head record */
     61     write_srecord(hdrlen, 2, 0, '0', name);
     62 
     63     /* Write data records */
     64     offset = 0;
     65     while (len) {
     66 	chunk = min(len, (size_t)32);
     67 
     68 	write_srecord(chunk, 4, offset, '3', buf);
     69 	buf += chunk;
     70 	len -= chunk;
     71 	offset += chunk;
     72     }
     73 
     74     /* Write termination record */
     75     write_srecord(0, 4, 0, '7', NULL);
     76 
     77     return 0;
     78 }
     79 
     80 struct upload_backend upload_srec = {
     81     .name       = "srec",
     82     .helpmsg    = "[filename]",
     83     .minargs    = 0,
     84     .write      = upload_srec_write,
     85 };
     86