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
main(int argc,char ** argv)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
dosegment(long foff,int len)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
record(uchar * s,int l)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
trailer(ulong a)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
usage(void)175 usage(void)
176 {
177 fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
178 exits("usage");
179 }
180