xref: /csrg-svn/sys/hp300/stand/mkboot.c (revision 57299)
141488Smckusick /*
241488Smckusick  * Copyright (c) 1990 The Regents of the University of California.
341488Smckusick  * All rights reserved.
441488Smckusick  *
541488Smckusick  * %sccs.include.redist.c%
641488Smckusick  *
7*57299Shibler  *	@(#)mkboot.c	7.5 (Berkeley) 12/26/92
841488Smckusick  */
941488Smckusick 
1041488Smckusick #ifndef lint
1141488Smckusick char copyright[] =
1241488Smckusick "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
1341488Smckusick  All rights reserved.\n";
1441488Smckusick #endif /* not lint */
1541488Smckusick 
1641488Smckusick #ifndef lint
1745790Sbostic static char sccsid[] = "@(#)mkboot.c	7.2 (Berkeley) 12/16/90";
1841488Smckusick #endif /* not lint */
1941488Smckusick 
2056510Sbostic #include <sys/param.h>
2156510Sbostic #include <sys/exec.h>
2256510Sbostic #include <sys/file.h>
2354073Shibler 
2456510Sbostic #include <hp300/stand/volhdr.h>
2556510Sbostic 
2641488Smckusick #include <stdio.h>
2741488Smckusick #include <ctype.h>
2841488Smckusick 
29*57299Shibler #define LIF_NUMDIR	8
30*57299Shibler 
31*57299Shibler #define LIF_VOLSTART	0
32*57299Shibler #define LIF_VOLSIZE	sizeof(struct lifvol)
33*57299Shibler #define LIF_DIRSTART	512
34*57299Shibler #define LIF_DIRSIZE	(LIF_NUMDIR * sizeof(struct lifdir))
35*57299Shibler #define LIF_FILESTART	8192
36*57299Shibler 
37*57299Shibler #define btolifs(b)	(((b) + (SECTSIZE - 1)) / SECTSIZE)
38*57299Shibler #define lifstob(s)	((s) * SECTSIZE)
39*57299Shibler 
4041488Smckusick int lpflag;
4141488Smckusick int loadpoint;
4241488Smckusick struct load ld;
4341488Smckusick struct lifvol lifv;
44*57299Shibler struct lifdir lifd[LIF_NUMDIR];
4541488Smckusick struct exec ex;
4641488Smckusick char buf[10240];
4741488Smckusick 
48*57299Shibler /*
49*57299Shibler  * Old Format:
50*57299Shibler  *	sector 0:	LIF volume header (40 bytes)
51*57299Shibler  *	sector 1:	<unused>
52*57299Shibler  *	sector 2:	LIF directory (8 x 32 == 256 bytes)
53*57299Shibler  *	sector 3-:	LIF file 0, LIF file 1, etc.
54*57299Shibler  * where sectors are 256 bytes.
55*57299Shibler  *
56*57299Shibler  * New Format:
57*57299Shibler  *	sector 0:	LIF volume header (40 bytes)
58*57299Shibler  *	sector 1:	<unused>
59*57299Shibler  *	sector 2:	LIF directory (8 x 32 == 256 bytes)
60*57299Shibler  *	sector 3:	<unused>
61*57299Shibler  *	sector 4-31:	disklabel (~300 bytes right now)
62*57299Shibler  *	sector 32-:	LIF file 0, LIF file 1, etc.
63*57299Shibler  */
6441488Smckusick main(argc, argv)
6541488Smckusick 	char **argv;
6641488Smckusick {
6741488Smckusick 	int ac;
6841488Smckusick 	char **av;
6941488Smckusick 	int from1, from2, to;
7041488Smckusick 	register int n;
7141488Smckusick 	char *n1, *n2, *lifname();
7241488Smckusick 
7341488Smckusick 	ac = --argc;
7441488Smckusick 	av = ++argv;
7541488Smckusick 	if (ac == 0)
7641488Smckusick 		usage();
7741488Smckusick 	if (!strcmp(av[0], "-l")) {
7841488Smckusick 		av++;
7941488Smckusick 		ac--;
8041488Smckusick 		if (ac == 0)
8141488Smckusick 			usage();
8241488Smckusick 		sscanf(av[0], "0x%x", &loadpoint);
8341488Smckusick 		lpflag++;
8441488Smckusick 		av++;
8541488Smckusick 		ac--;
8641488Smckusick 	}
8741488Smckusick 	if (ac == 0)
8841488Smckusick 		usage();
8941488Smckusick 	from1 = open(av[0], O_RDONLY, 0);
9041488Smckusick 	if (from1 < 0) {
9141488Smckusick 		perror("open");
9241488Smckusick 		exit(1);
9341488Smckusick 	}
9441488Smckusick 	n1 = av[0];
9541488Smckusick 	av++;
9641488Smckusick 	ac--;
9741488Smckusick 	if (ac == 0)
9841488Smckusick 		usage();
9941488Smckusick 	if (ac == 2) {
10041488Smckusick 		from2 = open(av[0], O_RDONLY, 0);
10141488Smckusick 		if (from2 < 0) {
10241488Smckusick 			perror("open");
10341488Smckusick 			exit(1);
10441488Smckusick 		}
10541488Smckusick 		n2 = av[0];
10641488Smckusick 		av++;
10741488Smckusick 		ac--;
10841488Smckusick 	} else
10941488Smckusick 		from2 = -1;
11041488Smckusick 	to = open(av[0], O_WRONLY | O_TRUNC | O_CREAT, 0644);
11141488Smckusick 	if (to < 0) {
11241488Smckusick 		perror("open");
11341488Smckusick 		exit(1);
11441488Smckusick 	}
11541488Smckusick 	/* clear possibly unused directory entries */
11641488Smckusick 	strncpy(lifd[1].dir_name, "          ", 10);
11741488Smckusick 	lifd[1].dir_type = -1;
11841488Smckusick 	lifd[1].dir_addr = 0;
11941488Smckusick 	lifd[1].dir_length = 0;
12041488Smckusick 	lifd[1].dir_flag = 0xFF;
12141488Smckusick 	lifd[1].dir_exec = 0;
12241488Smckusick 	lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
12341488Smckusick 	/* record volume info */
12441488Smckusick 	lifv.vol_id = VOL_ID;
12541488Smckusick 	strncpy(lifv.vol_label, "BOOT43", 6);
126*57299Shibler 	lifv.vol_addr = btolifs(LIF_DIRSTART);
12741488Smckusick 	lifv.vol_oct = VOL_OCT;
128*57299Shibler 	lifv.vol_dirsize = btolifs(LIF_DIRSIZE);
12941488Smckusick 	lifv.vol_version = 1;
13041488Smckusick 	/* output bootfile one */
131*57299Shibler 	lseek(to, LIF_FILESTART, 0);
13241488Smckusick 	putfile(from1, to);
133*57299Shibler 	n = btolifs(ld.count + sizeof(ld));
13441488Smckusick 	strcpy(lifd[0].dir_name, lifname(n1));
13541488Smckusick 	lifd[0].dir_type = DIR_TYPE;
136*57299Shibler 	lifd[0].dir_addr = btolifs(LIF_FILESTART);
13741488Smckusick 	lifd[0].dir_length = n;
13854073Shibler 	bcddate(from1, lifd[0].dir_toc);
13941488Smckusick 	lifd[0].dir_flag = DIR_FLAG;
14041488Smckusick 	lifd[0].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
14141488Smckusick 	lifv.vol_length = lifd[0].dir_addr + lifd[0].dir_length;
14241488Smckusick 	/* if there is an optional second boot program, output it */
14341488Smckusick 	if (from2 >= 0) {
144*57299Shibler 		lseek(to, LIF_FILESTART+lifstob(n), 0);
14541488Smckusick 		putfile(from2, to);
146*57299Shibler 		n = btolifs(ld.count + sizeof(ld));
14741488Smckusick 		strcpy(lifd[1].dir_name, lifname(n2));
14841488Smckusick 		lifd[1].dir_type = DIR_TYPE;
149*57299Shibler 		lifd[1].dir_addr = lifv.vol_length;
15041488Smckusick 		lifd[1].dir_length = n;
15154073Shibler 		bcddate(from2, lifd[1].dir_toc);
15241488Smckusick 		lifd[1].dir_flag = DIR_FLAG;
15341488Smckusick 		lifd[1].dir_exec = lpflag? loadpoint + ex.a_entry : ex.a_entry;
15441488Smckusick 		lifv.vol_length = lifd[1].dir_addr + lifd[1].dir_length;
15541488Smckusick 	}
15641488Smckusick 	/* output volume/directory header info */
157*57299Shibler 	lseek(to, LIF_VOLSTART, 0);
158*57299Shibler 	write(to, &lifv, LIF_VOLSIZE);
159*57299Shibler 	lseek(to, LIF_DIRSTART, 0);
160*57299Shibler 	write(to, lifd, LIF_DIRSIZE);
16141488Smckusick 	exit(0);
16241488Smckusick }
16341488Smckusick 
16441488Smckusick putfile(from, to)
16541488Smckusick {
16641488Smckusick 	register int n, tcnt, dcnt;
16741488Smckusick 
16841488Smckusick 	n = read(from, &ex, sizeof(ex));
16941488Smckusick 	if (n != sizeof(ex)) {
17041488Smckusick 		fprintf(stderr, "error reading file header\n");
17141488Smckusick 		exit(1);
17241488Smckusick 	}
17341488Smckusick 	if (ex.a_magic == OMAGIC) {
17441488Smckusick 		tcnt = ex.a_text;
17541488Smckusick 		dcnt = ex.a_data;
17641488Smckusick 	}
17741488Smckusick 	else if (ex.a_magic == NMAGIC) {
17841488Smckusick 		tcnt = (ex.a_text + PGOFSET) & ~PGOFSET;
17941488Smckusick 		dcnt = ex.a_data;
18041488Smckusick 	}
18141488Smckusick 	else {
18241488Smckusick 		fprintf(stderr, "bad magic number\n");
18341488Smckusick 		exit(1);
18441488Smckusick 	}
18541488Smckusick 	ld.address = lpflag ? loadpoint : ex.a_entry;
18641488Smckusick 	ld.count = tcnt + dcnt;
18741488Smckusick 	write(to, &ld, sizeof(ld));
18841488Smckusick 	while (tcnt) {
18941488Smckusick 		n = sizeof(buf);
19041488Smckusick 		if (n > tcnt)
19141488Smckusick 			n = tcnt;
19241488Smckusick 		n = read(from, buf, n);
19341488Smckusick 		if (n < 0) {
19441488Smckusick 			perror("read");
19541488Smckusick 			exit(1);
19641488Smckusick 		}
19741488Smckusick 		if (n == 0) {
19841488Smckusick 			fprintf(stderr, "short read\n");
19941488Smckusick 			exit(1);
20041488Smckusick 		}
20141488Smckusick 		if (write(to, buf, n) < 0) {
20241488Smckusick 			perror("write");
20341488Smckusick 			exit(1);
20441488Smckusick 		}
20541488Smckusick 		tcnt -= n;
20641488Smckusick 	}
20741488Smckusick 	while (dcnt) {
20841488Smckusick 		n = sizeof(buf);
20941488Smckusick 		if (n > dcnt)
21041488Smckusick 			n = dcnt;
21141488Smckusick 		n = read(from, buf, n);
21241488Smckusick 		if (n < 0) {
21341488Smckusick 			perror("read");
21441488Smckusick 			exit(1);
21541488Smckusick 		}
21641488Smckusick 		if (n == 0) {
21741488Smckusick 			fprintf(stderr, "short read\n");
21841488Smckusick 			exit(1);
21941488Smckusick 		}
22041488Smckusick 		if (write(to, buf, n) < 0) {
22141488Smckusick 			perror("write");
22241488Smckusick 			exit(1);
22341488Smckusick 		}
22441488Smckusick 		dcnt -= n;
22541488Smckusick 	}
22641488Smckusick }
22741488Smckusick 
22841488Smckusick usage()
22941488Smckusick {
23041488Smckusick 	fprintf(stderr,
23141488Smckusick 		"usage:  mkboot [-l loadpoint] prog1 [ prog2 ] outfile\n");
23241488Smckusick 	exit(1);
23341488Smckusick }
23441488Smckusick 
23541488Smckusick char *
23641488Smckusick lifname(str)
23741488Smckusick  char *str;
23841488Smckusick {
23941488Smckusick 	static char lname[10] = "SYS_XXXXX";
24041488Smckusick 	register int i;
24141488Smckusick 
24241488Smckusick 	for (i = 4; i < 9; i++) {
24341488Smckusick 		if (islower(*str))
24441488Smckusick 			lname[i] = toupper(*str);
24541488Smckusick 		else if (isalnum(*str) || *str == '_')
24641488Smckusick 			lname[i] = *str;
24741488Smckusick 		else
24841488Smckusick 			break;
24941488Smckusick 		str++;
25041488Smckusick 	}
25141488Smckusick 	for ( ; i < 10; i++)
25241488Smckusick 		lname[i] = '\0';
25341488Smckusick 	return(lname);
25441488Smckusick }
25554073Shibler 
25656510Sbostic #include <sys/stat.h>
25756510Sbostic #include <time.h>	/* XXX */
25854073Shibler 
25954073Shibler bcddate(fd, toc)
26054073Shibler 	int fd;
26154073Shibler 	char *toc;
26254073Shibler {
26354073Shibler 	struct stat statb;
26454073Shibler 	struct tm *tm;
26554073Shibler 
26654073Shibler 	fstat(fd, &statb);
26754073Shibler 	tm = localtime(&statb.st_ctime);
26854073Shibler 	*toc = ((tm->tm_mon+1) / 10) << 4;
26954073Shibler 	*toc++ |= (tm->tm_mon+1) % 10;
27054073Shibler 	*toc = (tm->tm_mday / 10) << 4;
27154073Shibler 	*toc++ |= tm->tm_mday % 10;
27254073Shibler 	*toc = (tm->tm_year / 10) << 4;
27354073Shibler 	*toc++ |= tm->tm_year % 10;
27454073Shibler 	*toc = (tm->tm_hour / 10) << 4;
27554073Shibler 	*toc++ |= tm->tm_hour % 10;
27654073Shibler 	*toc = (tm->tm_min / 10) << 4;
27754073Shibler 	*toc++ |= tm->tm_min % 10;
27854073Shibler 	*toc = (tm->tm_sec / 10) << 4;
27954073Shibler 	*toc |= tm->tm_sec % 10;
28054073Shibler }
281