153090Sbostic /*-
2*63226Sbostic * Copyright (c) 1992, 1993
3*63226Sbostic * The Regents of the University of California. 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*63226Sbostic * @(#)mkboottape.c 8.1 (Berkeley) 06/10/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>
2358573Sralph #include <err.h>
2453090Sbostic
2556526Sbostic #include <pmax/stand/dec_boot.h>
2657876Sralph #include <pmax/stand/dec_exec.h>
2753206Sralph
2853091Sbostic void usage __P((void));
2953090Sbostic
3053206Sralph struct Dec_DiskBoot decBootInfo;
3157876Sralph struct coff_exec dec_exec;
3258573Sralph extern char *__progname; /* Program name, from crt0. */
3353206Sralph
3453090Sbostic /*
3553090Sbostic * This program takes a kernel and the name of the special device file that
3653090Sbostic * has the mini-root file system stored on it and creates a boot tape.
3753090Sbostic * The -b option makes a bootfile that can load the kernel and mini-root
3853090Sbostic * over the network using the 'boot 6/tftp/filename -m' PROM command.
3953090Sbostic *
4053090Sbostic * usage: mkboottape [-b] tapedev vmunix minirootdev size
4153090Sbostic */
4253091Sbostic int
main(argc,argv)4353090Sbostic main(argc, argv)
4453090Sbostic int argc;
4553090Sbostic char *argv[];
4653090Sbostic {
4753090Sbostic register int i, n;
4853090Sbostic ProcSectionHeader shdr;
4953090Sbostic struct exec aout;
5053090Sbostic long loadAddr;
5153090Sbostic long execAddr;
5258573Sralph off_t textoff;
5353090Sbostic long length;
5453090Sbostic long rootsize;
5553091Sbostic int ifd, ofd, rfd;
5653091Sbostic int makebootfile;
5753091Sbostic int nsectors;
5853091Sbostic char block[DEV_BSIZE];
5953090Sbostic
6053091Sbostic makebootfile = 0;
6153091Sbostic while ((i = getopt(argc, argv, "b")) != EOF)
6253091Sbostic switch(i) {
6353091Sbostic case 'b':
6453091Sbostic makebootfile = 1;
6553091Sbostic break;
6653091Sbostic case '?':
6753091Sbostic default:
6853091Sbostic usage();
6953091Sbostic }
7053091Sbostic argc -= optind;
7153091Sbostic argv += optind;
7253091Sbostic
7353092Sbostic if (argc != 4)
7453090Sbostic usage();
7553091Sbostic
7653090Sbostic if (makebootfile)
7753206Sralph ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE);
7853090Sbostic else
7953206Sralph ofd = open(argv[0], O_RDWR, 0);
8053091Sbostic if (ofd < 0)
8158573Sralph deverr: err(1, "%s", argv[0]);
8253090Sbostic
8353206Sralph if ((ifd = open(argv[1], O_RDONLY, 0)) < 0)
8458573Sralph bootferr: err(1, "%s", argv[1]);
8553091Sbostic
8653206Sralph if ((rfd = open(argv[2], O_RDONLY, 0)) < 0)
8758573Sralph rooterr: err(1, "%s", argv[2]);
8853091Sbostic
8953206Sralph rootsize = atoi(argv[3]);
9053091Sbostic
9153090Sbostic /*
9253090Sbostic * Check for exec header and skip to code segment.
9353090Sbostic */
9453091Sbostic if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) ||
9558573Sralph aout.a_magic != OMAGIC) {
9658573Sralph fprintf(stderr, "%s: %s: need old text format (OMAGIC) file\n",
9758573Sralph __progname, argv[1]);
9858573Sralph exit(1);
9958573Sralph }
10053091Sbostic
10157876Sralph loadAddr = aout.a_entry;
10253090Sbostic execAddr = aout.a_entry;
10353090Sbostic length = aout.a_text + aout.a_data;
10453090Sbostic textoff = N_TXTOFF(aout);
10557876Sralph (void)printf("Input file is a.out format\n");
10653091Sbostic (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length);
10753090Sbostic
10853090Sbostic /*
10953090Sbostic * Compute size of boot program rounded to page size + mini-root size.
11053090Sbostic */
11153090Sbostic nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >>
11253206Sralph DEV_BSHIFT) + rootsize;
11353090Sbostic
11453090Sbostic if (makebootfile) {
11553090Sbostic /*
11657876Sralph * Write the ECOFF header.
11753090Sbostic */
11857876Sralph dec_exec.magic = COFF_MAGIC;
11957876Sralph dec_exec.numSections = 1;
12057876Sralph dec_exec.optHeader = 56;
12157876Sralph dec_exec.flags = 7;
12257876Sralph dec_exec.aout_magic = OMAGIC;
12357876Sralph dec_exec.verStamp = 512;
12457876Sralph dec_exec.codeSize = nsectors << DEV_BSHIFT;
12557876Sralph dec_exec.entry = execAddr;
12657876Sralph dec_exec.codeStart = loadAddr;
12757876Sralph dec_exec.heapStart = dec_exec.bssStart =
12857876Sralph dec_exec.codeStart + aout.a_text;
12957876Sralph if (write(ofd, (char *)&dec_exec, sizeof(dec_exec)) !=
13057876Sralph sizeof(dec_exec))
13153090Sbostic goto deverr;
13253090Sbostic strncpy(shdr.name, ".text", sizeof(shdr.name));
13353090Sbostic shdr.physAddr = shdr.virtAddr = loadAddr;
13457876Sralph shdr.size = dec_exec.codeSize;
13557876Sralph shdr.sectionPtr = n =
13657876Sralph (sizeof(dec_exec) + sizeof(shdr) + 15) & ~15;
13753090Sbostic shdr.relocPtr = 0;
13853090Sbostic shdr.lnnoPtr = 0;
13953090Sbostic shdr.numReloc = 0;
14053090Sbostic shdr.numLnno = 0;
14153090Sbostic shdr.flags = 0x20;
14253090Sbostic if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr))
14353090Sbostic goto deverr;
14457876Sralph n -= sizeof(dec_exec) + sizeof(shdr);
14553090Sbostic if (write(ofd, block, n) != n)
14653090Sbostic goto deverr;
14753090Sbostic } else {
14853090Sbostic /*
14953090Sbostic * Write the boot information block.
15053090Sbostic */
15153090Sbostic decBootInfo.magic = DEC_BOOT_MAGIC;
15253090Sbostic decBootInfo.mode = 0;
15353090Sbostic decBootInfo.loadAddr = loadAddr;
15453090Sbostic decBootInfo.execAddr = execAddr;
15553090Sbostic decBootInfo.map[0].numBlocks = nsectors;
15653090Sbostic decBootInfo.map[0].startBlock = 1;
15753090Sbostic decBootInfo.map[1].numBlocks = 0;
15853090Sbostic if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) !=
15953090Sbostic sizeof(decBootInfo))
16053090Sbostic goto deverr;
16153090Sbostic }
16253090Sbostic /* seek to start of text */
16353091Sbostic if (lseek(ifd, textoff, SEEK_SET) < 0)
16453090Sbostic goto bootferr;
16553090Sbostic
16653090Sbostic /*
16753090Sbostic * Write the remaining code to the correct place on the tape.
16853090Sbostic */
16953091Sbostic for (i = length; i > 0; i -= n) {
17053090Sbostic n = DEV_BSIZE;
17153090Sbostic if (n > i)
17253090Sbostic n = i;
17353090Sbostic if (read(ifd, block, n) != n)
17453090Sbostic goto bootferr;
17553206Sralph if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
17653090Sbostic goto deverr;
17753090Sbostic }
17853090Sbostic
17953090Sbostic /*
18053090Sbostic * Pad the boot file with zeros to the start of the mini-root.
18153090Sbostic */
18253090Sbostic bzero(block, DEV_BSIZE);
18353206Sralph i = ((nsectors - rootsize) << DEV_BSHIFT) -
18453206Sralph ((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1));
18553206Sralph n = DEV_BSIZE;
18653206Sralph for (; i > 0; i -= n) {
18753090Sbostic if (write(ofd, block, n) != n)
18853090Sbostic goto deverr;
18953090Sbostic }
19053090Sbostic
19153090Sbostic /*
19253090Sbostic * Write the mini-root to tape.
19353090Sbostic */
19453091Sbostic for (i = rootsize; i > 0; i--) {
19553091Sbostic if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE)
19653091Sbostic goto rooterr;
19753090Sbostic if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
19853090Sbostic goto deverr;
19953090Sbostic }
20053090Sbostic
20158573Sralph (void)printf("%s: wrote %d sectors\n", __progname, nsectors);
20253090Sbostic exit(0);
20353090Sbostic }
20453090Sbostic
20553091Sbostic void
usage()20653090Sbostic usage()
20753090Sbostic {
20853091Sbostic (void)fprintf(stderr,
20958573Sralph "usage: %s [-b] tapedev vmunix minirootdev size\n", __progname);
21053090Sbostic exit(1);
21153090Sbostic }
212