Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}