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