1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 void record(uchar*, int); 7 void usage(void); 8 void dosegment(long, int); 9 void trailer(ulong); 10 11 enum 12 { 13 Recordsize = 32, 14 }; 15 16 int dsegonly; 17 int supressend; 18 int binary; 19 int addr4; 20 ulong addr; 21 ulong psize = 4096; 22 ulong startaddr = 0x030000; 23 Biobuf stdout; 24 Biobuf bio; 25 26 void 27 main(int argc, char **argv) 28 { 29 Dir dir; 30 Fhdr f; 31 int fd; 32 33 ARGBEGIN{ 34 case 'd': 35 dsegonly++; 36 break; 37 case 's': 38 supressend++; 39 break; 40 case 'a': 41 addr = strtoul(ARGF(), 0, 0); 42 break; 43 case 'p': 44 psize = strtoul(ARGF(), 0, 0); 45 break; 46 case 'b': 47 binary++; 48 break; 49 case 'S': 50 startaddr = strtoul(ARGF(), 0, 0); 51 break; 52 case '4': 53 addr4++; 54 break; 55 default: 56 usage(); 57 }ARGEND 58 59 if(argc != 1) 60 usage(); 61 62 Binit(&stdout, 1, OWRITE); 63 64 fd = open(argv[0], OREAD); 65 if(fd < 0) { 66 fprint(2, "ms2: open %s: %r\n", argv[0]); 67 exits("open"); 68 } 69 70 if(binary) { 71 if(dirfstat(fd, &dir) < 0) { 72 fprint(2, "ms2: stat failed %r"); 73 exits("dirfstat"); 74 } 75 Binit(&bio, fd, OREAD); 76 dosegment(0, dir.length); 77 if(supressend == 0) 78 trailer(startaddr); 79 Bterm(&stdout); 80 Bterm(&bio); 81 exits(0); 82 } 83 84 if(crackhdr(fd, &f) == 0){ 85 fprint(2, "ms2: bad magic: %r\n"); 86 exits("magic"); 87 } 88 seek(fd, 0, 0); 89 90 Binit(&bio, fd, OREAD); 91 92 if(dsegonly) 93 dosegment(f.datoff, f.datsz); 94 else { 95 dosegment(f.txtoff, f.txtsz); 96 addr = (addr+(psize-1))&~(psize-1); 97 dosegment(f.datoff, f.datsz); 98 } 99 100 if(supressend == 0) 101 trailer(startaddr); 102 103 Bterm(&stdout); 104 Bterm(&bio); 105 exits(0); 106 } 107 108 void 109 dosegment(long foff, int len) 110 { 111 int l, n; 112 uchar buf[2*Recordsize]; 113 114 Bseek(&bio, foff, 0); 115 for(;;) { 116 l = len; 117 if(l > Recordsize) 118 l = Recordsize; 119 n = Bread(&bio, buf, l); 120 if(n == 0) 121 break; 122 if(n < 0) { 123 fprint(2, "ms2: read error: %r\n"); 124 exits("read"); 125 } 126 record(buf, l); 127 len -= l; 128 } 129 } 130 131 void 132 record(uchar *s, int l) 133 { 134 int i; 135 ulong cksum; 136 137 if(addr4 || addr & (0xFF<<24)){ 138 Bprint(&stdout, "S3%.2X%.8luX", l+5, addr); 139 cksum = l+5; 140 cksum += (addr>>24)&0xff; 141 }else{ 142 Bprint(&stdout, "S2%.2X%.6X", l+4, addr); 143 cksum = l+4; 144 } 145 cksum += addr&0xff; 146 cksum += (addr>>8)&0xff; 147 cksum += (addr>>16)&0xff; 148 149 for(i = 0; i < l; i++) { 150 cksum += *s; 151 Bprint(&stdout, "%.2X", *s++); 152 } 153 Bprint(&stdout, "%.2X\n", (~cksum)&0xff); 154 addr += l; 155 } 156 157 void 158 trailer(ulong a) 159 { 160 ulong cksum; 161 162 cksum = 0; 163 if(addr4 || a & (0xFF<<24)){ 164 Bprint(&stdout, "S7%.8luX", a); 165 cksum += (a>>24)&0xff; 166 }else 167 Bprint(&stdout, "S9%.6X", a); 168 cksum += a&0xff; 169 cksum += (a>>8)&0xff; 170 cksum += (a>>16)&0xff; 171 Bprint(&stdout, "%.2X\n", (~cksum)&0xff); 172 } 173 174 void 175 usage(void) 176 { 177 fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n"); 178 exits("usage"); 179 } 180