174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include <mach.h>
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth void record(uchar*, int);
674a4d8c2SCharles.Forsyth void usage(void);
774a4d8c2SCharles.Forsyth void dosegment(long, int);
874a4d8c2SCharles.Forsyth void trailer(ulong);
974a4d8c2SCharles.Forsyth void header(void);
1074a4d8c2SCharles.Forsyth
1174a4d8c2SCharles.Forsyth enum
1274a4d8c2SCharles.Forsyth {
1374a4d8c2SCharles.Forsyth Recordsize = 32
1474a4d8c2SCharles.Forsyth };
1574a4d8c2SCharles.Forsyth
1674a4d8c2SCharles.Forsyth int dsegonly;
1774a4d8c2SCharles.Forsyth int supressend;
1874a4d8c2SCharles.Forsyth int binary;
1974a4d8c2SCharles.Forsyth ulong addr;
2074a4d8c2SCharles.Forsyth ulong psize = 4096;
2174a4d8c2SCharles.Forsyth ulong startaddr = 0x030000;
2274a4d8c2SCharles.Forsyth Biobuf bout;
2374a4d8c2SCharles.Forsyth Biobuf bio;
2474a4d8c2SCharles.Forsyth
2574a4d8c2SCharles.Forsyth void
main(int argc,char ** argv)2674a4d8c2SCharles.Forsyth main(int argc, char **argv)
2774a4d8c2SCharles.Forsyth {
2874a4d8c2SCharles.Forsyth Dir *dir;
2974a4d8c2SCharles.Forsyth Fhdr f;
3074a4d8c2SCharles.Forsyth int fd;
3174a4d8c2SCharles.Forsyth
3274a4d8c2SCharles.Forsyth ARGBEGIN{
3374a4d8c2SCharles.Forsyth case 'd':
3474a4d8c2SCharles.Forsyth dsegonly++;
3574a4d8c2SCharles.Forsyth break;
3674a4d8c2SCharles.Forsyth case 's':
3774a4d8c2SCharles.Forsyth supressend++;
3874a4d8c2SCharles.Forsyth break;
3974a4d8c2SCharles.Forsyth case 'a':
4074a4d8c2SCharles.Forsyth case 'T':
4174a4d8c2SCharles.Forsyth addr = strtoul(ARGF(), 0, 0);
4274a4d8c2SCharles.Forsyth break;
4374a4d8c2SCharles.Forsyth case 'p':
4474a4d8c2SCharles.Forsyth case 'R':
4574a4d8c2SCharles.Forsyth psize = strtoul(ARGF(), 0, 0);
4674a4d8c2SCharles.Forsyth break;
4774a4d8c2SCharles.Forsyth case 'b':
4874a4d8c2SCharles.Forsyth binary++;
4974a4d8c2SCharles.Forsyth break;
5074a4d8c2SCharles.Forsyth case 'S':
5174a4d8c2SCharles.Forsyth startaddr = strtoul(ARGF(), 0, 0);
5274a4d8c2SCharles.Forsyth break;
5374a4d8c2SCharles.Forsyth default:
5474a4d8c2SCharles.Forsyth usage();
5574a4d8c2SCharles.Forsyth }ARGEND
5674a4d8c2SCharles.Forsyth
5774a4d8c2SCharles.Forsyth if(argc != 1)
5874a4d8c2SCharles.Forsyth usage();
5974a4d8c2SCharles.Forsyth
6074a4d8c2SCharles.Forsyth Binit(&bout, 1, OWRITE);
6174a4d8c2SCharles.Forsyth
6274a4d8c2SCharles.Forsyth fd = open(argv[0], OREAD);
6374a4d8c2SCharles.Forsyth if(fd < 0) {
6474a4d8c2SCharles.Forsyth fprint(2, "ms2: open %s: %r\n", argv[0]);
6574a4d8c2SCharles.Forsyth exits("open");
6674a4d8c2SCharles.Forsyth }
6774a4d8c2SCharles.Forsyth
6874a4d8c2SCharles.Forsyth if(binary) {
6974a4d8c2SCharles.Forsyth if((dir = dirfstat(fd)) == nil) {
7074a4d8c2SCharles.Forsyth fprint(2, "ms2: stat failed %r");
7174a4d8c2SCharles.Forsyth exits("dirfstat");
7274a4d8c2SCharles.Forsyth }
7374a4d8c2SCharles.Forsyth Binit(&bio, fd, OREAD);
7474a4d8c2SCharles.Forsyth header();
7574a4d8c2SCharles.Forsyth dosegment(0, dir->length);
7674a4d8c2SCharles.Forsyth if(supressend == 0)
7774a4d8c2SCharles.Forsyth trailer(startaddr);
7874a4d8c2SCharles.Forsyth Bterm(&bout);
7974a4d8c2SCharles.Forsyth Bterm(&bio);
8074a4d8c2SCharles.Forsyth free(dir);
8174a4d8c2SCharles.Forsyth exits(0);
8274a4d8c2SCharles.Forsyth }
8374a4d8c2SCharles.Forsyth
8474a4d8c2SCharles.Forsyth if(crackhdr(fd, &f) == 0){
8574a4d8c2SCharles.Forsyth fprint(2, "ms2: bad magic: %r\n");
8674a4d8c2SCharles.Forsyth exits("magic");
8774a4d8c2SCharles.Forsyth }
8874a4d8c2SCharles.Forsyth seek(fd, 0, 0);
8974a4d8c2SCharles.Forsyth
9074a4d8c2SCharles.Forsyth Binit(&bio, fd, OREAD);
9174a4d8c2SCharles.Forsyth
9274a4d8c2SCharles.Forsyth header();
9374a4d8c2SCharles.Forsyth if(dsegonly)
9474a4d8c2SCharles.Forsyth dosegment(f.datoff, f.datsz);
9574a4d8c2SCharles.Forsyth else {
9674a4d8c2SCharles.Forsyth dosegment(f.txtoff, f.txtsz);
9774a4d8c2SCharles.Forsyth addr = (addr+(psize-1))&~(psize-1);
9874a4d8c2SCharles.Forsyth dosegment(f.datoff, f.datsz);
9974a4d8c2SCharles.Forsyth }
10074a4d8c2SCharles.Forsyth
10174a4d8c2SCharles.Forsyth if(supressend == 0)
10274a4d8c2SCharles.Forsyth trailer(startaddr);
10374a4d8c2SCharles.Forsyth
10474a4d8c2SCharles.Forsyth Bterm(&bout);
10574a4d8c2SCharles.Forsyth Bterm(&bio);
10674a4d8c2SCharles.Forsyth exits(0);
10774a4d8c2SCharles.Forsyth }
10874a4d8c2SCharles.Forsyth
10974a4d8c2SCharles.Forsyth void
dosegment(long foff,int len)11074a4d8c2SCharles.Forsyth dosegment(long foff, int len)
11174a4d8c2SCharles.Forsyth {
11274a4d8c2SCharles.Forsyth int l, n;
11374a4d8c2SCharles.Forsyth uchar buf[2*Recordsize];
11474a4d8c2SCharles.Forsyth
11574a4d8c2SCharles.Forsyth Bseek(&bio, foff, 0);
11674a4d8c2SCharles.Forsyth for(;;) {
11774a4d8c2SCharles.Forsyth l = len;
11874a4d8c2SCharles.Forsyth if(l > Recordsize)
11974a4d8c2SCharles.Forsyth l = Recordsize;
12074a4d8c2SCharles.Forsyth n = Bread(&bio, buf, l);
12174a4d8c2SCharles.Forsyth if(n == 0)
12274a4d8c2SCharles.Forsyth break;
12374a4d8c2SCharles.Forsyth if(n < 0) {
12474a4d8c2SCharles.Forsyth fprint(2, "ms2: read error: %r\n");
12574a4d8c2SCharles.Forsyth exits("read");
12674a4d8c2SCharles.Forsyth }
12774a4d8c2SCharles.Forsyth record(buf, l);
12874a4d8c2SCharles.Forsyth len -= l;
12974a4d8c2SCharles.Forsyth }
13074a4d8c2SCharles.Forsyth }
13174a4d8c2SCharles.Forsyth
13274a4d8c2SCharles.Forsyth void
record(uchar * s,int l)13374a4d8c2SCharles.Forsyth record(uchar *s, int l)
13474a4d8c2SCharles.Forsyth {
13574a4d8c2SCharles.Forsyth int i;
13674a4d8c2SCharles.Forsyth ulong cksum;
13774a4d8c2SCharles.Forsyth
13874a4d8c2SCharles.Forsyth if(addr & (0xFF<<24)){
139*ce8e0d60Sforsyth Bprint(&bout, "S3%.2X%.8lX", l+5, addr);
14074a4d8c2SCharles.Forsyth cksum = l+5;
14174a4d8c2SCharles.Forsyth cksum += (addr>>24)&0xff;
14274a4d8c2SCharles.Forsyth }else{
143*ce8e0d60Sforsyth Bprint(&bout, "S2%.2X%.6lX", l+4, addr);
14474a4d8c2SCharles.Forsyth cksum = l+4;
14574a4d8c2SCharles.Forsyth }
14674a4d8c2SCharles.Forsyth cksum += addr&0xff;
14774a4d8c2SCharles.Forsyth cksum += (addr>>8)&0xff;
14874a4d8c2SCharles.Forsyth cksum += (addr>>16)&0xff;
14974a4d8c2SCharles.Forsyth
15074a4d8c2SCharles.Forsyth for(i = 0; i < l; i++) {
15174a4d8c2SCharles.Forsyth cksum += *s;
15274a4d8c2SCharles.Forsyth Bprint(&bout, "%.2X", *s++);
15374a4d8c2SCharles.Forsyth }
154*ce8e0d60Sforsyth Bprint(&bout, "%.2lX\n", (~cksum)&0xff);
15574a4d8c2SCharles.Forsyth addr += l;
15674a4d8c2SCharles.Forsyth }
15774a4d8c2SCharles.Forsyth
15874a4d8c2SCharles.Forsyth void
header(void)15974a4d8c2SCharles.Forsyth header(void)
16074a4d8c2SCharles.Forsyth {
16174a4d8c2SCharles.Forsyth Bprint(&bout, "S0030000FC\n");
16274a4d8c2SCharles.Forsyth }
16374a4d8c2SCharles.Forsyth
16474a4d8c2SCharles.Forsyth void
trailer(ulong a)16574a4d8c2SCharles.Forsyth trailer(ulong a)
16674a4d8c2SCharles.Forsyth {
16774a4d8c2SCharles.Forsyth ulong cksum;
16874a4d8c2SCharles.Forsyth
16974a4d8c2SCharles.Forsyth cksum = 0;
17074a4d8c2SCharles.Forsyth if(a & (0xFF<<24)){
171*ce8e0d60Sforsyth Bprint(&bout, "S7%.8lX", a);
17274a4d8c2SCharles.Forsyth cksum += (a>>24)&0xff;
17374a4d8c2SCharles.Forsyth }else
174*ce8e0d60Sforsyth Bprint(&bout, "S9%.6lX", a);
17574a4d8c2SCharles.Forsyth cksum += a&0xff;
17674a4d8c2SCharles.Forsyth cksum += (a>>8)&0xff;
17774a4d8c2SCharles.Forsyth cksum += (a>>16)&0xff;
178*ce8e0d60Sforsyth Bprint(&bout, "%.2lX\n", (~cksum)&0xff);
17974a4d8c2SCharles.Forsyth }
18074a4d8c2SCharles.Forsyth
18174a4d8c2SCharles.Forsyth void
usage(void)18274a4d8c2SCharles.Forsyth usage(void)
18374a4d8c2SCharles.Forsyth {
18474a4d8c2SCharles.Forsyth fprint(2, "usage: ms2 [-dsb] [-T address] [-R pagesize] [-S startaddress] ?.out\n");
18574a4d8c2SCharles.Forsyth exits("usage");
18674a4d8c2SCharles.Forsyth }
187