ref: c3ba64f6935322f09b6de5c2285544fd471c605d
dir: /sys/src/cmd/aux/ms2.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <mach.h> void record(uchar*, long); void usage(void); void segment(vlong, vlong); enum { Recordsize = 32, }; int dsegonly; int supressend; int binary; int halfswap; int srec = 2; uvlong addr; uvlong psize = 4096; Biobuf stdout; Fhdr exech; Biobuf *bio; void main(int argc, char **argv) { Dir *dir; uvlong totsz; ARGBEGIN{ case 'd': dsegonly++; break; case 's': supressend++; break; case 'a': addr = strtoull(ARGF(), 0, 0); break; case 'p': psize = strtoul(ARGF(), 0, 0); break; case 'b': binary++; break; case 'h': halfswap++; break; case '1': srec = 1; break; case '2': srec = 2; break; case '3': srec = 3; break; default: usage(); }ARGEND if(argc != 1) usage(); Binit(&stdout, 1, OWRITE); bio = Bopen(argv[0], OREAD); if(bio == 0) { fprint(2, "ms2: open %s: %r\n", argv[0]); exits("open"); } if(binary) { if((dir = dirfstat(Bfildes(bio))) == nil) { fprint(2, "ms2: stat failed %r"); exits("dirfstat"); } segment(0, dir->length); Bprint(&stdout, "S9030000FC\n"); Bterm(&stdout); Bterm(bio); free(dir); exits(0); } if(!crackhdr(Bfildes(bio), &exech)) { fprint(2, "ms2: can't decode file header\n"); return; } totsz = exech.txtsz + exech.datsz + exech.bsssz; fprint(2, "%s: %lud+%lud+%lud=%llud\n", exech.name, exech.txtsz, exech.datsz, exech.bsssz, totsz); if(dsegonly) segment(exech.datoff, exech.datsz); else { segment(exech.txtoff, exech.txtsz); addr = (addr+(psize-1))&~(psize-1); segment(exech.datoff, exech.datsz); } if(supressend == 0) { switch(srec) { case 1: case 2: Bprint(&stdout, "S9030000FC\n"); break; case 3: Bprint(&stdout, "S705000000FA\n"); break; } } Bterm(&stdout); Bterm(bio); exits(0); } void segment(vlong foff, vlong len) { int i; long l, n; uchar t, buf[2*Recordsize]; Bseek(bio, foff, 0); for(;;) { l = len; if(l > Recordsize) l = Recordsize; n = Bread(bio, buf, l); if(n == 0) break; if(n < 0) { fprint(2, "ms2: read error: %r\n"); exits("read"); } if(halfswap) { if(n & 1) { fprint(2, "ms2: data must be even length\n"); exits("even"); } for(i = 0; i < n; i += 2) { t = buf[i]; buf[i] = buf[i+1]; buf[i+1] = t; } } record(buf, l); len -= l; } } void record(uchar *s, long l) { int i; ulong cksum = 0; switch(srec) { case 1: cksum = l+3; Bprint(&stdout, "S1%.2lX%.4lluX", l+3, addr); cksum += addr&0xff; cksum += (addr>>8)&0xff; break; case 2: cksum = l+4; Bprint(&stdout, "S2%.2lX%.6lluX", l+4, addr); cksum += addr&0xff; cksum += (addr>>8)&0xff; cksum += (addr>>16)&0xff; break; case 3: cksum = l+5; Bprint(&stdout, "S3%.2lX%.8lluX", l+5, addr); cksum += addr&0xff; cksum += (addr>>8)&0xff; cksum += (addr>>16)&0xff; cksum += (addr>>24)&0xff; break; } for(i = 0; i < l; i++) { cksum += *s; Bprint(&stdout, "%.2X", *s++); } Bprint(&stdout, "%.2luX\n", (~cksum)&0xff); addr += l; } void usage(void) { fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n"); exits("usage"); }