xref: /csrg-svn/sys/pmax/stand/mkboottape.c (revision 57876)
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*57876Sralph  *	@(#)mkboottape.c	7.6 (Berkeley) 02/04/93
1153090Sbostic  */
1253090Sbostic 
1353090Sbostic #include <sys/param.h>
1453091Sbostic #include <sys/stat.h>
1553090Sbostic #include <sys/exec.h>
1656526Sbostic 
1753091Sbostic #include <errno.h>
1853091Sbostic #include <stdio.h>
1953091Sbostic #include <stdlib.h>
2053091Sbostic #include <unistd.h>
2153091Sbostic #include <fcntl.h>
2253091Sbostic #include <string.h>
2353090Sbostic 
2456526Sbostic #include <pmax/stand/dec_boot.h>
25*57876Sralph #include <pmax/stand/dec_exec.h>
2653206Sralph 
2753091Sbostic void err __P((const char *, ...));
2853091Sbostic void usage __P((void));
2953090Sbostic 
3053206Sralph struct	Dec_DiskBoot decBootInfo;
31*57876Sralph struct	coff_exec dec_exec;
3253206Sralph 
3353090Sbostic /*
3453090Sbostic  * This program takes a kernel and the name of the special device file that
3553090Sbostic  * has the mini-root file system stored on it and creates a boot tape.
3653090Sbostic  * The -b option makes a bootfile that can load the kernel and mini-root
3753090Sbostic  * over the network using the 'boot 6/tftp/filename -m' PROM command.
3853090Sbostic  *
3953090Sbostic  * usage: mkboottape [-b] tapedev vmunix minirootdev size
4053090Sbostic  */
4153091Sbostic int
4253090Sbostic main(argc, argv)
4353090Sbostic 	int argc;
4453090Sbostic 	char *argv[];
4553090Sbostic {
4653090Sbostic 	register int i, n;
4753090Sbostic 	ProcSectionHeader shdr;
4853090Sbostic 	struct exec aout;
4953090Sbostic 	long loadAddr;
5053090Sbostic 	long execAddr;
5153090Sbostic 	long textoff;
5253090Sbostic 	long length;
5353090Sbostic 	long rootsize;
5453091Sbostic 	int ifd, ofd, rfd;
5553091Sbostic 	int makebootfile;
5653091Sbostic 	int nsectors;
5753091Sbostic 	char block[DEV_BSIZE];
5853090Sbostic 
5953091Sbostic 	makebootfile = 0;
6053091Sbostic 	while ((i = getopt(argc, argv, "b")) != EOF)
6153091Sbostic 		switch(i) {
6253091Sbostic 		case 'b':
6353091Sbostic 			makebootfile = 1;
6453091Sbostic 			break;
6553091Sbostic 		case '?':
6653091Sbostic 		default:
6753091Sbostic 			usage();
6853091Sbostic 		}
6953091Sbostic 	argc -= optind;
7053091Sbostic 	argv += optind;
7153091Sbostic 
7253092Sbostic 	if (argc != 4)
7353090Sbostic 		usage();
7453091Sbostic 
7553090Sbostic 	if (makebootfile)
7653206Sralph 		ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE);
7753090Sbostic 	else
7853206Sralph 		ofd = open(argv[0], O_RDWR, 0);
7953091Sbostic 	if (ofd < 0)
8053206Sralph deverr:		err("%s: %s", argv[0], strerror(errno));
8153090Sbostic 
8253206Sralph 	if ((ifd = open(argv[1], O_RDONLY, 0)) < 0)
8353206Sralph bootferr:	err("%s: %s", argv[1], strerror(errno));
8453091Sbostic 
8553206Sralph 	if ((rfd = open(argv[2], O_RDONLY, 0)) < 0)
8653206Sralph rooterr:	err("%s: %s", argv[2], strerror(errno));
8753091Sbostic 
8853206Sralph 	rootsize = atoi(argv[3]);
8953091Sbostic 
9053090Sbostic 	/*
9153090Sbostic 	 * Check for exec header and skip to code segment.
9253090Sbostic 	 */
9353091Sbostic 	if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) ||
94*57876Sralph 	    aout.a_magic != OMAGIC)
95*57876Sralph 		err("%s: need impure text format (OMAGIC) file", argv[1]);
9653091Sbostic 
97*57876Sralph 	loadAddr = aout.a_entry;
9853090Sbostic 	execAddr = aout.a_entry;
9953090Sbostic 	length = aout.a_text + aout.a_data;
10053090Sbostic 	textoff = N_TXTOFF(aout);
101*57876Sralph 	(void)printf("Input file is a.out format\n");
10253091Sbostic 	(void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length);
10353090Sbostic 
10453090Sbostic 	/*
10553090Sbostic 	 * Compute size of boot program rounded to page size + mini-root size.
10653090Sbostic 	 */
10753090Sbostic 	nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >>
10853206Sralph 		DEV_BSHIFT) + rootsize;
10953090Sbostic 
11053090Sbostic 	if (makebootfile) {
11153090Sbostic 		/*
112*57876Sralph 		 * Write the ECOFF header.
11353090Sbostic 		 */
114*57876Sralph 		dec_exec.magic = COFF_MAGIC;
115*57876Sralph 		dec_exec.numSections = 1;
116*57876Sralph 		dec_exec.optHeader = 56;
117*57876Sralph 		dec_exec.flags = 7;
118*57876Sralph 		dec_exec.aout_magic = OMAGIC;
119*57876Sralph 		dec_exec.verStamp = 512;
120*57876Sralph 		dec_exec.codeSize = nsectors << DEV_BSHIFT;
121*57876Sralph 		dec_exec.entry = execAddr;
122*57876Sralph 		dec_exec.codeStart = loadAddr;
123*57876Sralph 		dec_exec.heapStart = dec_exec.bssStart =
124*57876Sralph 			dec_exec.codeStart + aout.a_text;
125*57876Sralph 		if (write(ofd, (char *)&dec_exec, sizeof(dec_exec)) !=
126*57876Sralph 		    sizeof(dec_exec))
12753090Sbostic 			goto deverr;
12853090Sbostic 		strncpy(shdr.name, ".text", sizeof(shdr.name));
12953090Sbostic 		shdr.physAddr = shdr.virtAddr = loadAddr;
130*57876Sralph 		shdr.size = dec_exec.codeSize;
131*57876Sralph 		shdr.sectionPtr = n =
132*57876Sralph 			(sizeof(dec_exec) + sizeof(shdr) + 15) & ~15;
13353090Sbostic 		shdr.relocPtr = 0;
13453090Sbostic 		shdr.lnnoPtr = 0;
13553090Sbostic 		shdr.numReloc = 0;
13653090Sbostic 		shdr.numLnno = 0;
13753090Sbostic 		shdr.flags = 0x20;
13853090Sbostic 		if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr))
13953090Sbostic 			goto deverr;
140*57876Sralph 		n -= sizeof(dec_exec) + sizeof(shdr);
14153090Sbostic 		if (write(ofd, block, n) != n)
14253090Sbostic 			goto deverr;
14353090Sbostic 	} else {
14453090Sbostic 		/*
14553090Sbostic 		 * Write the boot information block.
14653090Sbostic 		 */
14753090Sbostic 		decBootInfo.magic = DEC_BOOT_MAGIC;
14853090Sbostic 		decBootInfo.mode = 0;
14953090Sbostic 		decBootInfo.loadAddr = loadAddr;
15053090Sbostic 		decBootInfo.execAddr = execAddr;
15153090Sbostic 		decBootInfo.map[0].numBlocks = nsectors;
15253090Sbostic 		decBootInfo.map[0].startBlock = 1;
15353090Sbostic 		decBootInfo.map[1].numBlocks = 0;
15453090Sbostic 		if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) !=
15553090Sbostic 		    sizeof(decBootInfo))
15653090Sbostic 			goto deverr;
15753090Sbostic 	}
15853090Sbostic 	/* seek to start of text */
15953091Sbostic 	if (lseek(ifd, textoff, SEEK_SET) < 0)
16053090Sbostic 		goto bootferr;
16153090Sbostic 
16253090Sbostic 	/*
16353090Sbostic 	 * Write the remaining code to the correct place on the tape.
16453090Sbostic 	 */
16553091Sbostic 	for (i = length; i > 0; i -= n) {
16653090Sbostic 		n = DEV_BSIZE;
16753090Sbostic 		if (n > i)
16853090Sbostic 			n = i;
16953090Sbostic 		if (read(ifd, block, n) != n)
17053090Sbostic 			goto bootferr;
17153206Sralph 		if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
17253090Sbostic 			goto deverr;
17353090Sbostic 	}
17453090Sbostic 
17553090Sbostic 	/*
17653090Sbostic 	 * Pad the boot file with zeros to the start of the mini-root.
17753090Sbostic 	 */
17853090Sbostic 	bzero(block, DEV_BSIZE);
17953206Sralph 	i = ((nsectors - rootsize) << DEV_BSHIFT) -
18053206Sralph 		((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1));
18153206Sralph 	n = DEV_BSIZE;
18253206Sralph 	for (; i > 0; i -= n) {
18353090Sbostic 		if (write(ofd, block, n) != n)
18453090Sbostic 			goto deverr;
18553090Sbostic 	}
18653090Sbostic 
18753090Sbostic 	/*
18853090Sbostic 	 * Write the mini-root to tape.
18953090Sbostic 	 */
19053091Sbostic 	for (i = rootsize; i > 0; i--) {
19153091Sbostic 		if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE)
19253091Sbostic 			goto rooterr;
19353090Sbostic 		if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
19453090Sbostic 			goto deverr;
19553090Sbostic 	}
19653090Sbostic 
19753091Sbostic 	(void)printf("mkboottape: wrote %d sectors\n", nsectors);
19853090Sbostic 	exit(0);
19953090Sbostic }
20053090Sbostic 
20153091Sbostic void
20253090Sbostic usage()
20353090Sbostic {
20453091Sbostic 	(void)fprintf(stderr,
20553091Sbostic 	    "usage: mkboottape [-b] tapedev vmunix minirootdev size\n");
20653090Sbostic 	exit(1);
20753090Sbostic }
20853091Sbostic 
20953091Sbostic #if __STDC__
21053091Sbostic #include <stdarg.h>
21153091Sbostic #else
21253091Sbostic #include <varargs.h>
21353091Sbostic #endif
21453091Sbostic 
21553091Sbostic void
21653091Sbostic #if __STDC__
21753091Sbostic err(const char *fmt, ...)
21853091Sbostic #else
21953091Sbostic err(fmt, va_alist)
22053091Sbostic 	char *fmt;
22153091Sbostic         va_dcl
22253091Sbostic #endif
22353091Sbostic {
22453091Sbostic 	va_list ap;
22553091Sbostic #if __STDC__
22653091Sbostic 	va_start(ap, fmt);
22753091Sbostic #else
22853091Sbostic 	va_start(ap);
22953091Sbostic #endif
23053091Sbostic 	(void)fprintf(stderr, "mkboottape: ");
23153091Sbostic 	(void)vfprintf(stderr, fmt, ap);
23253091Sbostic 	va_end(ap);
23353091Sbostic 	(void)fprintf(stderr, "\n");
23453091Sbostic 	exit(1);
23553091Sbostic 	/* NOTREACHED */
23653091Sbostic }
237