xref: /inferno-os/utils/ms2/ms2.c (revision ce8e0d607a2bec33fcaac7237d0b5535e5b152a1)
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