xref: /inferno-os/utils/ms2/ms2.c (revision 556f8a312ed1b20f8ff25c104928646828e8b05c)
1  #include <lib9.h>
2  #include <bio.h>
3  #include <mach.h>
4  
5  void	record(uchar*, int);
6  void	usage(void);
7  void	dosegment(long, int);
8  void trailer(ulong);
9  void header(void);
10  
11  enum
12  {
13  	Recordsize = 32
14  };
15  
16  int	dsegonly;
17  int	supressend;
18  int	binary;
19  ulong	addr;
20  ulong 	psize = 4096;
21  ulong	startaddr = 0x030000;
22  Biobuf 	bout;
23  Biobuf	bio;
24  
25  void
26  main(int argc, char **argv)
27  {
28  	Dir *dir;
29  	Fhdr f;
30  	int fd;
31  
32  	ARGBEGIN{
33  	case 'd':
34  		dsegonly++;
35  		break;
36  	case 's':
37  		supressend++;
38  		break;
39  	case 'a':
40  	case 'T':
41  		addr = strtoul(ARGF(), 0, 0);
42  		break;
43  	case 'p':
44  	case 'R':
45  		psize = strtoul(ARGF(), 0, 0);
46  		break;
47  	case 'b':
48  		binary++;
49  		break;
50  	case 'S':
51  		startaddr = strtoul(ARGF(), 0, 0);
52  		break;
53  	default:
54  		usage();
55  	}ARGEND
56  
57  	if(argc != 1)
58  		usage();
59  
60  	Binit(&bout, 1, OWRITE);
61  
62  	fd = open(argv[0], OREAD);
63  	if(fd < 0) {
64  		fprint(2, "ms2: open %s: %r\n", argv[0]);
65  		exits("open");
66  	}
67  
68  	if(binary) {
69  		if((dir = dirfstat(fd)) == nil) {
70  			fprint(2, "ms2: stat failed %r");
71  			exits("dirfstat");
72  		}
73  		Binit(&bio, fd, OREAD);
74  		header();
75  		dosegment(0, dir->length);
76  		if(supressend == 0)
77  			trailer(startaddr);
78  		Bterm(&bout);
79  		Bterm(&bio);
80  		free(dir);
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  	header();
93  	if(dsegonly)
94  		dosegment(f.datoff, f.datsz);
95  	else {
96  		dosegment(f.txtoff, f.txtsz);
97  		addr = (addr+(psize-1))&~(psize-1);
98  		dosegment(f.datoff, f.datsz);
99  	}
100  
101  	if(supressend == 0)
102  		trailer(startaddr);
103  
104  	Bterm(&bout);
105  	Bterm(&bio);
106  	exits(0);
107  }
108  
109  void
110  dosegment(long foff, int len)
111  {
112  	int l, n;
113  	uchar buf[2*Recordsize];
114  
115  	Bseek(&bio, foff, 0);
116  	for(;;) {
117  		l = len;
118  		if(l > Recordsize)
119  			l = Recordsize;
120  		n = Bread(&bio, buf, l);
121  		if(n == 0)
122  			break;
123  		if(n < 0) {
124  			fprint(2, "ms2: read error: %r\n");
125  			exits("read");
126  		}
127  		record(buf, l);
128  		len -= l;
129  	}
130  }
131  
132  void
133  record(uchar *s, int l)
134  {
135  	int i;
136  	ulong cksum;
137  
138  	if(addr & (0xFF<<24)){
139  		Bprint(&bout, "S3%.2X%.8X", l+5, addr);
140  		cksum = l+5;
141  		cksum += (addr>>24)&0xff;
142  	}else{
143  		Bprint(&bout, "S2%.2X%.6X", l+4, addr);
144  		cksum = l+4;
145  	}
146  	cksum += addr&0xff;
147  	cksum += (addr>>8)&0xff;
148  	cksum += (addr>>16)&0xff;
149  
150  	for(i = 0; i < l; i++) {
151  		cksum += *s;
152  		Bprint(&bout, "%.2X", *s++);
153  	}
154  	Bprint(&bout, "%.2X\n", (~cksum)&0xff);
155  	addr += l;
156  }
157  
158  void
159  header(void)
160  {
161  	Bprint(&bout, "S0030000FC\n");
162  }
163  
164  void
165  trailer(ulong a)
166  {
167  	ulong cksum;
168  
169  	cksum = 0;
170  	if(a & (0xFF<<24)){
171  		Bprint(&bout, "S7%.8X", a);
172  		cksum += (a>>24)&0xff;
173  	}else
174  		Bprint(&bout, "S9%.6X", a);
175  	cksum += a&0xff;
176  	cksum += (a>>8)&0xff;
177  	cksum += (a>>16)&0xff;
178  	Bprint(&bout, "%.2X\n", (~cksum)&0xff);
179  }
180  
181  void
182  usage(void)
183  {
184  	fprint(2, "usage: ms2 [-dsb] [-T address] [-R pagesize] [-S startaddress] ?.out\n");
185  	exits("usage");
186  }
187