xref: /original-bsd/sys/hp300/stand/mkboot.c (revision b806d041)
1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)mkboot.c	7.5 (Berkeley) 12/26/92
8  */
9 
10 #ifndef lint
11 char copyright[] =
12 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
13  All rights reserved.\n";
14 #endif /* not lint */
15 
16 #ifndef lint
17 static char sccsid[] = "@(#)mkboot.c	7.2 (Berkeley) 12/16/90";
18 #endif /* not lint */
19 
20 #include <sys/param.h>
21 #include <sys/exec.h>
22 #include <sys/file.h>
23 
24 #include <hp300/stand/volhdr.h>
25 
26 #include <stdio.h>
27 #include <ctype.h>
28 
29 #define LIF_NUMDIR	8
30 
31 #define LIF_VOLSTART	0
32 #define LIF_VOLSIZE	sizeof(struct lifvol)
33 #define LIF_DIRSTART	512
34 #define LIF_DIRSIZE	(LIF_NUMDIR * sizeof(struct lifdir))
35 #define LIF_FILESTART	8192
36 
37 #define btolifs(b)	(((b) + (SECTSIZE - 1)) / SECTSIZE)
38 #define lifstob(s)	((s) * SECTSIZE)
39 
40 int lpflag;
41 int loadpoint;
42 struct load ld;
43 struct lifvol lifv;
44 struct lifdir lifd[LIF_NUMDIR];
45 struct exec ex;
46 char buf[10240];
47 
48 /*
49  * Old Format:
50  *	sector 0:	LIF volume header (40 bytes)
51  *	sector 1:	<unused>
52  *	sector 2:	LIF directory (8 x 32 == 256 bytes)
53  *	sector 3-:	LIF file 0, LIF file 1, etc.
54  * where sectors are 256 bytes.
55  *
56  * New Format:
57  *	sector 0:	LIF volume header (40 bytes)
58  *	sector 1:	<unused>
59  *	sector 2:	LIF directory (8 x 32 == 256 bytes)
60  *	sector 3:	<unused>
61  *	sector 4-31:	disklabel (~300 bytes right now)
62  *	sector 32-:	LIF file 0, LIF file 1, etc.
63  */
64 main(argc, argv)
65 	char **argv;
66 {
67 	int ac;
68 	char **av;
69 	int from1, from2, to;
70 	register int n;
71 	char *n1, *n2, *lifname();
72 
73 	ac = --argc;
74 	av = ++argv;
75 	if (ac == 0)
76 		usage();
77 	if (!strcmp(av[0], "-l")) {
78 		av++;
79 		ac--;
80 		if (ac == 0)
81 			usage();
82 		sscanf(av[0], "0x%x", &loadpoint);
83 		lpflag++;
84 		av++;
85 		ac--;
86 	}
87 	if (ac == 0)
88 		usage();
89 	from1 = open(av[0], O_RDONLY, 0);
90 	if (from1 < 0) {
91 		perror("open");
92 		exit(1);
93 	}
94 	n1 = av[0];
95 	av++;
96 	ac--;
97 	if (ac == 0)
98 		usage();
99 	if (ac == 2) {
100 		from2 = open(av[0], O_RDONLY, 0);
101 		if (from2 < 0) {
102 			perror("open");
103 			exit(1);
104 		}
105 		n2 = av[0];
106 		av++;
107 		ac--;
108 	} else
109 		from2 = -1;
110 	to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644);
111 	if (to < 0) {
112 		perror("open");
113 		exit(1);
114 	}
115 	/* clear possibly unused directory entries */
116 	strncpy(lifd[1].dir_name, "          ", 10);
117 	lifd[1].dir_type = -1;
118 	lifd[1].dir_addr = 0;
119 	lifd[1].dir_length = 0;
120 	lifd[1].dir_flag = 0xFF;
121 	lifd[1].dir_exec = 0;
122 	lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
123 	/* record volume info */
124 	lifv.vol_id = VOL_ID;
125 	strncpy(lifv.vol_label, "BOOT43", 6);
126 	lifv.vol_addr = btolifs(LIF_DIRSTART);
127 	lifv.vol_oct = VOL_OCT;
128 	lifv.vol_dirsize = btolifs(LIF_DIRSIZE);
129 	lifv.vol_version = 1;
130 	/* output bootfile one */
131 	lseek(to, LIF_FILESTART, 0);
132 	putfile(from1, to);
133 	n = btolifs(ld.count + sizeof(ld));
134 	strcpy(lifd[0].dir_name, lifname(n1));
135 	lifd[0].dir_type = DIR_TYPE;
136 	lifd[0].dir_addr = btolifs(LIF_FILESTART);
137 	lifd[0].dir_length = n;
138 	bcddate(from1, lifd[0].dir_toc);
139 	lifd[0].dir_flag = DIR_FLAG;
140 	lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
141 	lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length;
142 	/* if there is an optional second boot program, output it */
143 	if (from2 >= 0) {
144 		lseek(to, LIF_FILESTART+lifstob(n), 0);
145 		putfile(from2, to);
146 		n = btolifs(ld.count + sizeof(ld));
147 		strcpy(lifd[1].dir_name, lifname(n2));
148 		lifd[1].dir_type = DIR_TYPE;
149 		lifd[1].dir_addr = lifv.vol_length;
150 		lifd[1].dir_length = n;
151 		bcddate(from2, lifd[1].dir_toc);
152 		lifd[1].dir_flag = DIR_FLAG;
153 		lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
154 		lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length;
155 	}
156 	/* output volume/directory header info */
157 	lseek(to, LIF_VOLSTART, 0);
158 	write(to, &lifv, LIF_VOLSIZE);
159 	lseek(to, LIF_DIRSTART, 0);
160 	write(to, lifd, LIF_DIRSIZE);
161 	exit(0);
162 }
163 
164 putfile(from, to)
165 {
166 	register int n, tcnt, dcnt;
167 
168 	n = read(from, &ex, sizeof(ex));
169 	if (n != sizeof(ex)) {
170 		fprintf(stderr, "error reading file header\n");
171 		exit(1);
172 	}
173 	if (ex.a_magic == OMAGIC) {
174 		tcnt = ex.a_text;
175 		dcnt = ex.a_data;
176 	}
177 	else if (ex.a_magic == NMAGIC) {
178 		tcnt = (ex.a_text + PGOFSET) & ~PGOFSET;
179 		dcnt = ex.a_data;
180 	}
181 	else {
182 		fprintf(stderr, "bad magic number\n");
183 		exit(1);
184 	}
185 	ld.address = lpflag ? loadpoint : ex.a_entry;
186 	ld.count = tcnt + dcnt;
187 	write(to, &ld, sizeof(ld));
188 	while (tcnt) {
189 		n = sizeof(buf);
190 		if (n > tcnt)
191 			n = tcnt;
192 		n = read(from, buf, n);
193 		if (n < 0) {
194 			perror("read");
195 			exit(1);
196 		}
197 		if (n == 0) {
198 			fprintf(stderr, "short read\n");
199 			exit(1);
200 		}
201 		if (write(to, buf, n) < 0) {
202 			perror("write");
203 			exit(1);
204 		}
205 		tcnt -= n;
206 	}
207 	while (dcnt) {
208 		n = sizeof(buf);
209 		if (n > dcnt)
210 			n = dcnt;
211 		n = read(from, buf, n);
212 		if (n < 0) {
213 			perror("read");
214 			exit(1);
215 		}
216 		if (n == 0) {
217 			fprintf(stderr, "short read\n");
218 			exit(1);
219 		}
220 		if (write(to, buf, n) < 0) {
221 			perror("write");
222 			exit(1);
223 		}
224 		dcnt -= n;
225 	}
226 }
227 
228 usage()
229 {
230 	fprintf(stderr,
231 		"usage:  mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n");
232 	exit(1);
233 }
234 
235 char *
236 lifname(str)
237  char *str;
238 {
239 	static char lname[10] = "SYS_XXXXX";
240 	register int i;
241 
242 	for (i = 4; i < 9; i++) {
243 		if (islower(*str))
244 			lname[i] = toupper(*str);
245 		else if (isalnum(*str) || *str == '_')
246 			lname[i] = *str;
247 		else
248 			break;
249 		str++;
250 	}
251 	for ( ; i < 10; i++)
252 		lname[i] = '\0';
253 	return(lname);
254 }
255 
256 #include <sys/stat.h>
257 #include <time.h>	/* XXX */
258 
259 bcddate(fd, toc)
260 	int fd;
261 	char *toc;
262 {
263 	struct stat statb;
264 	struct tm *tm;
265 
266 	fstat(fd, &statb);
267 	tm = localtime(&statb.st_ctime);
268 	*toc = ((tm->tm_mon+1) / 10) << 4;
269 	*toc++ |= (tm->tm_mon+1) % 10;
270 	*toc = (tm->tm_mday / 10) << 4;
271 	*toc++ |= tm->tm_mday % 10;
272 	*toc = (tm->tm_year / 10) << 4;
273 	*toc++ |= tm->tm_year % 10;
274 	*toc = (tm->tm_hour / 10) << 4;
275 	*toc++ |= tm->tm_hour % 10;
276 	*toc = (tm->tm_min / 10) << 4;
277 	*toc++ |= tm->tm_min % 10;
278 	*toc = (tm->tm_sec / 10) << 4;
279 	*toc |= tm->tm_sec % 10;
280 }
281