mkboot.c revision 1.1 1 /* $NetBSD: mkboot.c,v 1.1 1997/02/04 03:53:04 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)mkboot.c 8.1 (Berkeley) 7/15/93
36 */
37
38 #ifndef lint
39 static char copyright[] =
40 "@(#) Copyright (c) 1990, 1993\n\
41 The Regents of the University of California. All rights reserved.\n";
42 #endif /* not lint */
43
44 #ifndef lint
45 #ifdef notdef
46 static char sccsid[] = "@(#)mkboot.c 7.2 (Berkeley) 12/16/90";
47 #endif
48 static char rcsid[] = "$NetBSD: mkboot.c,v 1.1 1997/02/04 03:53:04 thorpej Exp $";
49 #endif /* not lint */
50
51 #include <sys/param.h>
52 #include <sys/file.h>
53 #include <a.out.h>
54
55 #include "volhdr.h"
56
57 #include <stdio.h>
58 #include <ctype.h>
59
60 #define LIF_NUMDIR 8
61
62 #define LIF_VOLSTART 0
63 #define LIF_VOLSIZE sizeof(struct lifvol)
64 #define LIF_DIRSTART 512
65 #define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir))
66 #define LIF_FILESTART 8192
67
68 #define btolifs(b) (((b) + (SECTSIZE - 1)) / SECTSIZE)
69 #define lifstob(s) ((s) * SECTSIZE)
70
71 int lpflag;
72 int loadpoint;
73 struct load ld;
74 struct lifvol lifv;
75 struct lifdir lifd[LIF_NUMDIR];
76 struct exec ex;
77 char buf[10240];
78
79 /*
80 * Old Format:
81 * sector 0: LIF volume header (40 bytes)
82 * sector 1: <unused>
83 * sector 2: LIF directory (8 x 32 == 256 bytes)
84 * sector 3-: LIF file 0, LIF file 1, etc.
85 * where sectors are 256 bytes.
86 *
87 * New Format:
88 * sector 0: LIF volume header (40 bytes)
89 * sector 1: <unused>
90 * sector 2: LIF directory (8 x 32 == 256 bytes)
91 * sector 3: <unused>
92 * sector 4-31: disklabel (~300 bytes right now)
93 * sector 32-: LIF file 0, LIF file 1, etc.
94 */
95 main(argc, argv)
96 char **argv;
97 {
98 int ac;
99 char **av;
100 int from1, from2, from3, to;
101 register int n;
102 char *n1, *n2, *n3, *lifname();
103
104 ac = --argc;
105 av = ++argv;
106 if (ac == 0)
107 usage();
108 if (!strcmp(av[0], "-l")) {
109 av++;
110 ac--;
111 if (ac == 0)
112 usage();
113 sscanf(av[0], "0x%x", &loadpoint);
114 lpflag++;
115 av++;
116 ac--;
117 }
118 if (ac == 0)
119 usage();
120 from1 = open(av[0], O_RDONLY, 0);
121 if (from1 < 0) {
122 perror("open");
123 exit(1);
124 }
125 n1 = av[0];
126 av++;
127 ac--;
128 if (ac == 0)
129 usage();
130 if (ac > 1) {
131 from2 = open(av[0], O_RDONLY, 0);
132 if (from2 < 0) {
133 perror("open");
134 exit(1);
135 }
136 n2 = av[0];
137 av++;
138 ac--;
139 if (ac > 1) {
140 from3 = open(av[0], O_RDONLY, 0);
141 if (from3 < 0) {
142 perror("open");
143 exit(1);
144 }
145 n3 = av[0];
146 av++;
147 ac--;
148 } else
149 from3 = -1;
150 } else
151 from2 = from3 = -1;
152 to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644);
153 if (to < 0) {
154 perror("open");
155 exit(1);
156 }
157 /* clear possibly unused directory entries */
158 strncpy(lifd[1].dir_name, " ", 10);
159 lifd[1].dir_type = -1;
160 lifd[1].dir_addr = 0;
161 lifd[1].dir_length = 0;
162 lifd[1].dir_flag = 0xFF;
163 lifd[1].dir_exec = 0;
164 lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
165 /* record volume info */
166 lifv.vol_id = VOL_ID;
167 strncpy(lifv.vol_label, "BOOT43", 6);
168 lifv.vol_addr = btolifs(LIF_DIRSTART);
169 lifv.vol_oct = VOL_OCT;
170 lifv.vol_dirsize = btolifs(LIF_DIRSIZE);
171 lifv.vol_version = 1;
172 /* output bootfile one */
173 lseek(to, LIF_FILESTART, 0);
174 putfile(from1, to);
175 n = btolifs(ld.count + sizeof(ld));
176 strcpy(lifd[0].dir_name, lifname(n1));
177 lifd[0].dir_type = DIR_TYPE;
178 lifd[0].dir_addr = btolifs(LIF_FILESTART);
179 lifd[0].dir_length = n;
180 bcddate(from1, lifd[0].dir_toc);
181 lifd[0].dir_flag = DIR_FLAG;
182 lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
183 lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length;
184 /* if there is an optional second boot program, output it */
185 if (from2 >= 0) {
186 lseek(to, LIF_FILESTART+lifstob(n), 0);
187 putfile(from2, to);
188 n = btolifs(ld.count + sizeof(ld));
189 strcpy(lifd[1].dir_name, lifname(n2));
190 lifd[1].dir_type = DIR_TYPE;
191 lifd[1].dir_addr = lifv.vol_length;
192 lifd[1].dir_length = n;
193 bcddate(from2, lifd[1].dir_toc);
194 lifd[1].dir_flag = DIR_FLAG;
195 lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
196 lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length;
197 }
198 /* ditto for three */
199 if (from3 >= 0) {
200 lseek(to, LIF_FILESTART+lifstob(lifd[0].dir_length+n), 0);
201 putfile(from3, to);
202 n = btolifs(ld.count + sizeof(ld));
203 strcpy(lifd[2].dir_name, lifname(n3));
204 lifd[2].dir_type = DIR_TYPE;
205 lifd[2].dir_addr = lifv.vol_length;
206 lifd[2].dir_length = n;
207 bcddate(from3, lifd[2].dir_toc);
208 lifd[2].dir_flag = DIR_FLAG;
209 lifd[2].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
210 lifv.vol_length = lifd[2].dir_addr + lifd[2].dir_length;
211 }
212 /* output volume/directory header info */
213 lseek(to, LIF_VOLSTART, 0);
214 write(to, &lifv, LIF_VOLSIZE);
215 lseek(to, LIF_DIRSTART, 0);
216 write(to, lifd, LIF_DIRSIZE);
217 exit(0);
218 }
219
220 putfile(from, to)
221 {
222 register int n, tcnt, dcnt;
223
224 n = read(from, &ex, sizeof(ex));
225 if (n != sizeof(ex)) {
226 fprintf(stderr, "error reading file header\n");
227 exit(1);
228 }
229 if (N_GETMAGIC(ex) == OMAGIC) {
230 tcnt = ex.a_text;
231 dcnt = ex.a_data;
232 }
233 else if (N_GETMAGIC(ex) == NMAGIC) {
234 tcnt = (ex.a_text + PGOFSET) & ~PGOFSET;
235 dcnt = ex.a_data;
236 }
237 else {
238 fprintf(stderr, "bad magic number\n");
239 exit(1);
240 }
241 ld.address = lpflag ? loadpoint : ex.a_entry;
242 ld.count = tcnt + dcnt;
243 write(to, &ld, sizeof(ld));
244 while (tcnt) {
245 n = sizeof(buf);
246 if (n > tcnt)
247 n = tcnt;
248 n = read(from, buf, n);
249 if (n < 0) {
250 perror("read");
251 exit(1);
252 }
253 if (n == 0) {
254 fprintf(stderr, "short read\n");
255 exit(1);
256 }
257 if (write(to, buf, n) < 0) {
258 perror("write");
259 exit(1);
260 }
261 tcnt -= n;
262 }
263 while (dcnt) {
264 n = sizeof(buf);
265 if (n > dcnt)
266 n = dcnt;
267 n = read(from, buf, n);
268 if (n < 0) {
269 perror("read");
270 exit(1);
271 }
272 if (n == 0) {
273 fprintf(stderr, "short read\n");
274 exit(1);
275 }
276 if (write(to, buf, n) < 0) {
277 perror("write");
278 exit(1);
279 }
280 dcnt -= n;
281 }
282 }
283
284 usage()
285 {
286 fprintf(stderr,
287 "usage: mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n");
288 exit(1);
289 }
290
291 char *
292 lifname(str)
293 char *str;
294 {
295 static char lname[10] = "SYS_XXXXX";
296 register int i;
297
298 for (i = 4; i < 9; i++) {
299 if (islower(*str))
300 lname[i] = toupper(*str);
301 else if (isalnum(*str) || *str == '_')
302 lname[i] = *str;
303 else
304 break;
305 str++;
306 }
307 for ( ; i < 10; i++)
308 lname[i] = '\0';
309 return(lname);
310 }
311
312 #include <sys/stat.h>
313 #include <time.h> /* XXX */
314
315 bcddate(fd, toc)
316 int fd;
317 char *toc;
318 {
319 struct stat statb;
320 struct tm *tm;
321
322 fstat(fd, &statb);
323 tm = localtime(&statb.st_ctime);
324 *toc = ((tm->tm_mon+1) / 10) << 4;
325 *toc++ |= (tm->tm_mon+1) % 10;
326 *toc = (tm->tm_mday / 10) << 4;
327 *toc++ |= tm->tm_mday % 10;
328 *toc = (tm->tm_year / 10) << 4;
329 *toc++ |= tm->tm_year % 10;
330 *toc = (tm->tm_hour / 10) << 4;
331 *toc++ |= tm->tm_hour % 10;
332 *toc = (tm->tm_min / 10) << 4;
333 *toc++ |= tm->tm_min % 10;
334 *toc = (tm->tm_sec / 10) << 4;
335 *toc |= tm->tm_sec % 10;
336 }
337