Home | History | Annotate | Line # | Download | only in mkboot
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