xref: /inferno-os/os/boot/rpcg/ms2.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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