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