xref: /csrg-svn/sys/pmax/stand/mkboottape.c (revision 53091)
153090Sbostic /*-
253090Sbostic  * Copyright (c) 1992 The Regents of the University of California.
353090Sbostic  * All rights reserved.
453090Sbostic  *
553090Sbostic  * This code is derived from software contributed to Berkeley by
653090Sbostic  * Ralph Campbell.
753090Sbostic  *
853090Sbostic  * %sccs.include.redist.c%
953090Sbostic  *
10*53091Sbostic  *	@(#)mkboottape.c	7.2 (Berkeley) 03/30/92
1153090Sbostic  */
1253090Sbostic 
1353090Sbostic #include <sys/param.h>
14*53091Sbostic #include <sys/stat.h>
1553090Sbostic #include <sys/exec.h>
16*53091Sbostic #include <errno.h>
17*53091Sbostic #include <stdio.h>
18*53091Sbostic #include <stdlib.h>
19*53091Sbostic #include <unistd.h>
20*53091Sbostic #include <fcntl.h>
21*53091Sbostic #include <string.h>
2253090Sbostic #include "../dev/devDiskLabel.h"
2353090Sbostic 
24*53091Sbostic void err __P((const char *, ...));
25*53091Sbostic void usage __P((void));
2653090Sbostic 
2753090Sbostic /*
2853090Sbostic  * This program takes a kernel and the name of the special device file that
2953090Sbostic  * has the mini-root file system stored on it and creates a boot tape.
3053090Sbostic  * The -b option makes a bootfile that can load the kernel and mini-root
3153090Sbostic  * over the network using the 'boot 6/tftp/filename -m' PROM command.
3253090Sbostic  *
3353090Sbostic  * usage: mkboottape [-b] tapedev vmunix minirootdev size
3453090Sbostic  */
35*53091Sbostic int
3653090Sbostic main(argc, argv)
3753090Sbostic 	int argc;
3853090Sbostic 	char *argv[];
3953090Sbostic {
4053090Sbostic 	register int i, n;
4153090Sbostic 	Dec_DiskBoot decBootInfo;
4253090Sbostic 	ProcSectionHeader shdr;
4353090Sbostic 	struct exec aout;
4453090Sbostic 	long loadAddr;
4553090Sbostic 	long execAddr;
4653090Sbostic 	long textoff;
4753090Sbostic 	long length;
4853090Sbostic 	long rootsize;
49*53091Sbostic 	int ifd, ofd, rfd;
50*53091Sbostic 	int makebootfile;
51*53091Sbostic 	int nsectors;
52*53091Sbostic 	char block[DEV_BSIZE];
5353090Sbostic 
54*53091Sbostic 	makebootfile = 0;
55*53091Sbostic 	while ((i = getopt(argc, argv, "b")) != EOF)
56*53091Sbostic 		switch(i) {
57*53091Sbostic 		case 'b':
58*53091Sbostic 			makebootfile = 1;
59*53091Sbostic 			break;
60*53091Sbostic 		case '?':
61*53091Sbostic 		default:
62*53091Sbostic 			usage();
63*53091Sbostic 		}
64*53091Sbostic 	argc -= optind;
65*53091Sbostic 	argv += optind;
66*53091Sbostic 
6753090Sbostic 	if (argc != 5)
6853090Sbostic 		usage();
6953090Sbostic 	rootsize = atoi(argv[4]);
70*53091Sbostic 
7153090Sbostic 	if (makebootfile)
72*53091Sbostic 		ofd = open(argv[1], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE);
7353090Sbostic 	else
74*53091Sbostic 		ofd = open(argv[1], O_RDWR, 0);
75*53091Sbostic 	if (ofd < 0)
76*53091Sbostic deverr:		err("%s: %s", argv[1], strerror(errno));
7753090Sbostic 
78*53091Sbostic 	if ((ifd = open(argv[2], O_RDONLY, 0)) < 0)
79*53091Sbostic bootferr:	err("%s: %s", argv[2], strerror(errno));
80*53091Sbostic 
81*53091Sbostic 	if ((rfd = open(argv[3], 0, 0)) < 0)
82*53091Sbostic rooterr:	err("%s: %s", argv[3], strerror(errno));
83*53091Sbostic 
84*53091Sbostic 
8553090Sbostic 	/*
8653090Sbostic 	 * Check for exec header and skip to code segment.
8753090Sbostic 	 */
88*53091Sbostic 	if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) ||
89*53091Sbostic 	    aout.ex_fhdr.magic != COFF_MAGIC || aout.a_magic != OMAGIC)
90*53091Sbostic 		err("need impure text format (OMAGIC) file");
91*53091Sbostic 
9253090Sbostic 	loadAddr = aout.ex_aout.codeStart;
9353090Sbostic 	execAddr = aout.a_entry;
9453090Sbostic 	length = aout.a_text + aout.a_data;
9553090Sbostic 	textoff = N_TXTOFF(aout);
96*53091Sbostic 	(void)printf("Input file is COFF format\n");
97*53091Sbostic 	(void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length);
9853090Sbostic 
9953090Sbostic 	/*
10053090Sbostic 	 * Compute size of boot program rounded to page size + mini-root size.
10153090Sbostic 	 */
10253090Sbostic 	nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >>
103*53091Sbostic 	    DEV_BSHIFT) + rootsize;
10453090Sbostic 
10553090Sbostic 	if (makebootfile) {
10653090Sbostic 		/*
10753090Sbostic 		 * Write modified ECOFF header.
10853090Sbostic 		 */
10953090Sbostic 		aout.ex_fhdr.numSections = 1;
11053090Sbostic 		aout.ex_fhdr.numSyms = 0;
11153090Sbostic 		aout.ex_fhdr.symPtr = 0;
11253090Sbostic 		aout.a_text = nsectors << DEV_BSHIFT;
11353090Sbostic 		aout.a_data = 0;
11453090Sbostic 		aout.a_bss = 0;
11553090Sbostic 		aout.ex_aout.heapStart = aout.ex_aout.bssStart =
11653090Sbostic 			aout.ex_aout.codeStart + aout.a_text;
11753090Sbostic 		if (write(ofd, (char *)&aout, sizeof(aout)) != sizeof(aout))
11853090Sbostic 			goto deverr;
11953090Sbostic 		strncpy(shdr.name, ".text", sizeof(shdr.name));
12053090Sbostic 		shdr.physAddr = shdr.virtAddr = loadAddr;
12153090Sbostic 		shdr.size = aout.a_text;
12253090Sbostic 		shdr.sectionPtr = n = (sizeof(aout) + sizeof(shdr) + 15) & ~15;
12353090Sbostic 		shdr.relocPtr = 0;
12453090Sbostic 		shdr.lnnoPtr = 0;
12553090Sbostic 		shdr.numReloc = 0;
12653090Sbostic 		shdr.numLnno = 0;
12753090Sbostic 		shdr.flags = 0x20;
12853090Sbostic 		if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr))
12953090Sbostic 			goto deverr;
13053090Sbostic 		n -= sizeof(aout) + sizeof(shdr);
13153090Sbostic 		if (write(ofd, block, n) != n)
13253090Sbostic 			goto deverr;
13353090Sbostic 	} else {
13453090Sbostic 		/*
13553090Sbostic 		 * Write the boot information block.
13653090Sbostic 		 */
13753090Sbostic 		decBootInfo.magic = DEC_BOOT_MAGIC;
13853090Sbostic 		decBootInfo.mode = 0;
13953090Sbostic 		decBootInfo.loadAddr = loadAddr;
14053090Sbostic 		decBootInfo.execAddr = execAddr;
14153090Sbostic 		decBootInfo.map[0].numBlocks = nsectors;
14253090Sbostic 		decBootInfo.map[0].startBlock = 1;
14353090Sbostic 		decBootInfo.map[1].numBlocks = 0;
14453090Sbostic 		if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) !=
14553090Sbostic 		    sizeof(decBootInfo))
14653090Sbostic 			goto deverr;
14753090Sbostic 	}
14853090Sbostic 	/* seek to start of text */
149*53091Sbostic 	if (lseek(ifd, textoff, SEEK_SET) < 0)
15053090Sbostic 		goto bootferr;
15153090Sbostic 
15253090Sbostic 	/*
15353090Sbostic 	 * Write the remaining code to the correct place on the tape.
15453090Sbostic 	 */
155*53091Sbostic 	for (i = length; i > 0; i -= n) {
15653090Sbostic 		n = DEV_BSIZE;
15753090Sbostic 		if (n > i)
15853090Sbostic 			n = i;
15953090Sbostic 		if (read(ifd, block, n) != n)
16053090Sbostic 			goto bootferr;
16153090Sbostic 		if (write(ofd, block, n) != n)
16253090Sbostic 			goto deverr;
16353090Sbostic 	}
16453090Sbostic 
16553090Sbostic 	/*
16653090Sbostic 	 * Pad the boot file with zeros to the start of the mini-root.
16753090Sbostic 	 */
16853090Sbostic 	bzero(block, DEV_BSIZE);
169*53091Sbostic 	for (i = ((nsectors - rootsize) << DEV_BSHIFT) - length;
170*53091Sbostic 	    i > 0; i -= n) {
17153090Sbostic 		n = DEV_BSIZE;
17253090Sbostic 		if (n > i)
17353090Sbostic 			n = i;
17453090Sbostic 		if (write(ofd, block, n) != n)
17553090Sbostic 			goto deverr;
17653090Sbostic 	}
17753090Sbostic 
17853090Sbostic 	/*
17953090Sbostic 	 * Write the mini-root to tape.
18053090Sbostic 	 */
181*53091Sbostic 	for (i = rootsize; i > 0; i--) {
182*53091Sbostic 		if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE)
183*53091Sbostic 			goto rooterr;
18453090Sbostic 		if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
18553090Sbostic 			goto deverr;
18653090Sbostic 	}
18753090Sbostic 
188*53091Sbostic 	(void)printf("mkboottape: wrote %d sectors\n", nsectors);
18953090Sbostic 	exit(0);
19053090Sbostic }
19153090Sbostic 
192*53091Sbostic void
19353090Sbostic usage()
19453090Sbostic {
195*53091Sbostic 	(void)fprintf(stderr,
196*53091Sbostic 	    "usage: mkboottape [-b] tapedev vmunix minirootdev size\n");
19753090Sbostic 	exit(1);
19853090Sbostic }
199*53091Sbostic 
200*53091Sbostic #if __STDC__
201*53091Sbostic #include <stdarg.h>
202*53091Sbostic #else
203*53091Sbostic #include <varargs.h>
204*53091Sbostic #endif
205*53091Sbostic 
206*53091Sbostic void
207*53091Sbostic #if __STDC__
208*53091Sbostic err(const char *fmt, ...)
209*53091Sbostic #else
210*53091Sbostic err(fmt, va_alist)
211*53091Sbostic 	char *fmt;
212*53091Sbostic         va_dcl
213*53091Sbostic #endif
214*53091Sbostic {
215*53091Sbostic 	va_list ap;
216*53091Sbostic #if __STDC__
217*53091Sbostic 	va_start(ap, fmt);
218*53091Sbostic #else
219*53091Sbostic 	va_start(ap);
220*53091Sbostic #endif
221*53091Sbostic 	(void)fprintf(stderr, "mkboottape: ");
222*53091Sbostic 	(void)vfprintf(stderr, fmt, ap);
223*53091Sbostic 	va_end(ap);
224*53091Sbostic 	(void)fprintf(stderr, "\n");
225*53091Sbostic 	exit(1);
226*53091Sbostic 	/* NOTREACHED */
227*53091Sbostic }
228