xref: /plan9-contrib/sys/src/cmd/aux/ms2.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <a.out.h>
4 #include <bio.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 ulong	addr;
19 ulong 	psize = 4096;
20 Biobuf 	stdout;
21 Exec	exech;
22 Biobuf *bio;
23 
24 void
25 main(int argc, char **argv)
26 {
27 	int n;
28 	Dir dir;
29 
30 	ARGBEGIN{
31 	case 'd':
32 		dsegonly++;
33 		break;
34 	case 's':
35 		supressend++;
36 		break;
37 	case 'a':
38 		addr = strtoul(ARGF(), 0, 0);
39 		break;
40 	case 'p':
41 		psize = strtoul(ARGF(), 0, 0);
42 		break;
43 	case 'b':
44 		binary++;
45 		break;
46 	default:
47 		usage();
48 	}ARGEND
49 
50 	if(argc != 1)
51 		usage();
52 
53 	Binit(&stdout, 1, OWRITE);
54 
55 	bio = Bopen(argv[0], OREAD);
56 	if(bio == 0) {
57 		fprint(2, "ms2: open %s: %r\n", argv[0]);
58 		exits("open");
59 	}
60 
61 	if(binary) {
62 		if(dirfstat(Bfildes(bio), &dir) < 0) {
63 			fprint(2, "ms2: stat failed %r");
64 			exits("dirfstat");
65 		}
66 		segment(0, dir.length);
67 		Bprint(&stdout, "S9030000FC\n");
68 		Bterm(&stdout);
69 		Bterm(bio);
70 		exits(0);
71 	}
72 
73 	n = Bread(bio, &exech, sizeof(Exec));
74 	if(n != sizeof(Exec)) {
75 		fprint(2, "ms2: read failed: %r\n");
76 		exits("read");
77 	}
78 
79 	switch(exech.magic) {
80 	default:
81 		fprint(2, "ms2: bad magic\n");
82 		exits("magic");
83 	case A_MAGIC:
84 	case I_MAGIC:
85 	case J_MAGIC:
86 	case K_MAGIC:
87 	case V_MAGIC:
88 		break;
89 	}
90 
91 	if(dsegonly)
92 		segment(exech.text+sizeof(exech), exech.data);
93 	else {
94 		segment(sizeof(exech), exech.text);
95 		addr = (addr+(psize-1))&~(psize-1);
96 		segment(exech.text+sizeof(exech), exech.data);
97 	}
98 
99 	if(supressend == 0)
100 		Bprint(&stdout, "S9030000FC\n");
101 
102 	Bterm(&stdout);
103 	Bterm(bio);
104 	exits(0);
105 }
106 
107 void
108 segment(long foff, int len)
109 {
110 	int l, n;
111 	uchar buf[2*Recordsize];
112 
113 	Bseek(bio, foff, 0);
114 	for(;;) {
115 		l = len;
116 		if(l > Recordsize)
117 			l = Recordsize;
118 		n = Bread(bio, buf, l);
119 		if(n == 0)
120 			break;
121 		if(n < 0) {
122 			fprint(2, "ms2: read error: %r\n");
123 			exits("read");
124 		}
125 		record(buf, l);
126 		len -= l;
127 	}
128 }
129 
130 void
131 record(uchar *s, int l)
132 {
133 	int i;
134 	ulong cksum;
135 
136 	cksum = l+4;
137 	Bprint(&stdout, "S2%.2X%.6X", l+4, addr);
138 	cksum += addr&0xff;
139 	cksum += (addr>>8)&0xff;
140 	cksum += (addr>>16)&0xff;
141 
142 	for(i = 0; i < l; i++) {
143 		cksum += *s;
144 		Bprint(&stdout, "%.2X", *s++);
145 	}
146 	Bprint(&stdout, "%.2X\n", (~cksum)&0xff);
147 	addr += l;
148 }
149 
150 void
151 usage(void)
152 {
153 	fprint(2, "usage: ms2 [-ds] [-a address] [-p pagesize] ?.out\n");
154 	exits("usage");
155 }
156