1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 void record(uchar*, long); 7 void usage(void); 8 void segment(vlong, vlong); 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 uvlong addr; 21 uvlong 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 uvlong totsz; 31 32 ARGBEGIN{ 33 case 'd': 34 dsegonly++; 35 break; 36 case 's': 37 supressend++; 38 break; 39 case 'a': 40 addr = strtoull(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=%llud\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(vlong foff, vlong len) 124 { 125 int i; 126 long l, n; 127 uchar t, buf[2*Recordsize]; 128 129 Bseek(bio, foff, 0); 130 for(;;) { 131 l = len; 132 if(l > Recordsize) 133 l = Recordsize; 134 n = Bread(bio, buf, l); 135 if(n == 0) 136 break; 137 if(n < 0) { 138 fprint(2, "ms2: read error: %r\n"); 139 exits("read"); 140 } 141 if(halfswap) { 142 if(n & 1) { 143 fprint(2, "ms2: data must be even length\n"); 144 exits("even"); 145 } 146 for(i = 0; i < n; i += 2) { 147 t = buf[i]; 148 buf[i] = buf[i+1]; 149 buf[i+1] = t; 150 } 151 } 152 record(buf, l); 153 len -= l; 154 } 155 } 156 157 void 158 record(uchar *s, long l) 159 { 160 int i; 161 ulong cksum = 0; 162 163 switch(srec) { 164 case 1: 165 cksum = l+3; 166 Bprint(&stdout, "S1%.2lX%.4lluX", l+3, addr); 167 cksum += addr&0xff; 168 cksum += (addr>>8)&0xff; 169 break; 170 case 2: 171 cksum = l+4; 172 Bprint(&stdout, "S2%.2lX%.6lluX", l+4, addr); 173 cksum += addr&0xff; 174 cksum += (addr>>8)&0xff; 175 cksum += (addr>>16)&0xff; 176 break; 177 case 3: 178 cksum = l+5; 179 Bprint(&stdout, "S3%.2lX%.8lluX", l+5, addr); 180 cksum += addr&0xff; 181 cksum += (addr>>8)&0xff; 182 cksum += (addr>>16)&0xff; 183 cksum += (addr>>24)&0xff; 184 break; 185 } 186 187 for(i = 0; i < l; i++) { 188 cksum += *s; 189 Bprint(&stdout, "%.2X", *s++); 190 } 191 Bprint(&stdout, "%.2luX\n", (~cksum)&0xff); 192 addr += l; 193 } 194 195 void 196 usage(void) 197 { 198 fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n"); 199 exits("usage"); 200 } 201