make kernel includes standard
[unix-history] / usr / src / sys / pmax / stand / mkboottape.c
CommitLineData
5a9c4166
KB
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ralph Campbell.
7 *
8 * %sccs.include.redist.c%
9 *
5548a02f 10 * @(#)mkboottape.c 7.5 (Berkeley) %G%
5a9c4166
KB
11 */
12
5a9c4166 13#include <sys/param.h>
69c1fa90 14#include <sys/stat.h>
5a9c4166 15#include <sys/exec.h>
5548a02f 16
69c1fa90
KB
17#include <errno.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <string.h>
b8e366da 23
5548a02f 24#include <pmax/stand/dec_boot.h>
5a9c4166 25
69c1fa90
KB
26void err __P((const char *, ...));
27void usage __P((void));
5a9c4166 28
b8e366da
RC
29struct Dec_DiskBoot decBootInfo;
30
5a9c4166
KB
31/*
32 * This program takes a kernel and the name of the special device file that
33 * has the mini-root file system stored on it and creates a boot tape.
34 * The -b option makes a bootfile that can load the kernel and mini-root
35 * over the network using the 'boot 6/tftp/filename -m' PROM command.
36 *
37 * usage: mkboottape [-b] tapedev vmunix minirootdev size
38 */
69c1fa90 39int
5a9c4166
KB
40main(argc, argv)
41 int argc;
42 char *argv[];
43{
44 register int i, n;
5a9c4166
KB
45 ProcSectionHeader shdr;
46 struct exec aout;
5a9c4166
KB
47 long loadAddr;
48 long execAddr;
49 long textoff;
50 long length;
51 long rootsize;
69c1fa90
KB
52 int ifd, ofd, rfd;
53 int makebootfile;
54 int nsectors;
55 char block[DEV_BSIZE];
56
57 makebootfile = 0;
58 while ((i = getopt(argc, argv, "b")) != EOF)
59 switch(i) {
60 case 'b':
61 makebootfile = 1;
62 break;
63 case '?':
64 default:
65 usage();
66 }
67 argc -= optind;
68 argv += optind;
5a9c4166 69
65a02c33 70 if (argc != 4)
5a9c4166 71 usage();
69c1fa90 72
5a9c4166 73 if (makebootfile)
b8e366da 74 ofd = open(argv[0], O_CREAT|O_TRUNC|O_WRONLY, DEFFILEMODE);
5a9c4166 75 else
b8e366da 76 ofd = open(argv[0], O_RDWR, 0);
69c1fa90 77 if (ofd < 0)
b8e366da 78deverr: err("%s: %s", argv[0], strerror(errno));
69c1fa90 79
b8e366da
RC
80 if ((ifd = open(argv[1], O_RDONLY, 0)) < 0)
81bootferr: err("%s: %s", argv[1], strerror(errno));
69c1fa90 82
b8e366da
RC
83 if ((rfd = open(argv[2], O_RDONLY, 0)) < 0)
84rooterr: err("%s: %s", argv[2], strerror(errno));
69c1fa90 85
b8e366da 86 rootsize = atoi(argv[3]);
5a9c4166
KB
87
88 /*
89 * Check for exec header and skip to code segment.
90 */
69c1fa90
KB
91 if (read(ifd, &aout, sizeof(aout)) != sizeof(aout) ||
92 aout.ex_fhdr.magic != COFF_MAGIC || aout.a_magic != OMAGIC)
93 err("need impure text format (OMAGIC) file");
94
5a9c4166
KB
95 loadAddr = aout.ex_aout.codeStart;
96 execAddr = aout.a_entry;
97 length = aout.a_text + aout.a_data;
98 textoff = N_TXTOFF(aout);
69c1fa90
KB
99 (void)printf("Input file is COFF format\n");
100 (void)printf("load %x, start %x, len %d\n", loadAddr, execAddr, length);
5a9c4166
KB
101
102 /*
103 * Compute size of boot program rounded to page size + mini-root size.
104 */
105 nsectors = (((length + aout.a_bss + NBPG - 1) & ~(NBPG - 1)) >>
b8e366da 106 DEV_BSHIFT) + rootsize;
5a9c4166
KB
107
108 if (makebootfile) {
109 /*
110 * Write modified ECOFF header.
111 */
112 aout.ex_fhdr.numSections = 1;
113 aout.ex_fhdr.numSyms = 0;
114 aout.ex_fhdr.symPtr = 0;
115 aout.a_text = nsectors << DEV_BSHIFT;
116 aout.a_data = 0;
117 aout.a_bss = 0;
118 aout.ex_aout.heapStart = aout.ex_aout.bssStart =
119 aout.ex_aout.codeStart + aout.a_text;
120 if (write(ofd, (char *)&aout, sizeof(aout)) != sizeof(aout))
121 goto deverr;
122 strncpy(shdr.name, ".text", sizeof(shdr.name));
123 shdr.physAddr = shdr.virtAddr = loadAddr;
124 shdr.size = aout.a_text;
125 shdr.sectionPtr = n = (sizeof(aout) + sizeof(shdr) + 15) & ~15;
126 shdr.relocPtr = 0;
127 shdr.lnnoPtr = 0;
128 shdr.numReloc = 0;
129 shdr.numLnno = 0;
130 shdr.flags = 0x20;
131 if (write(ofd, (char *)&shdr, sizeof(shdr)) != sizeof(shdr))
132 goto deverr;
133 n -= sizeof(aout) + sizeof(shdr);
134 if (write(ofd, block, n) != n)
135 goto deverr;
136 } else {
137 /*
138 * Write the boot information block.
139 */
140 decBootInfo.magic = DEC_BOOT_MAGIC;
141 decBootInfo.mode = 0;
142 decBootInfo.loadAddr = loadAddr;
143 decBootInfo.execAddr = execAddr;
144 decBootInfo.map[0].numBlocks = nsectors;
145 decBootInfo.map[0].startBlock = 1;
146 decBootInfo.map[1].numBlocks = 0;
147 if (write(ofd, (char *)&decBootInfo, sizeof(decBootInfo)) !=
148 sizeof(decBootInfo))
149 goto deverr;
150 }
151 /* seek to start of text */
69c1fa90 152 if (lseek(ifd, textoff, SEEK_SET) < 0)
5a9c4166
KB
153 goto bootferr;
154
155 /*
156 * Write the remaining code to the correct place on the tape.
157 */
69c1fa90 158 for (i = length; i > 0; i -= n) {
5a9c4166
KB
159 n = DEV_BSIZE;
160 if (n > i)
161 n = i;
162 if (read(ifd, block, n) != n)
163 goto bootferr;
b8e366da 164 if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
5a9c4166 165 goto deverr;
5a9c4166
KB
166 }
167
168 /*
169 * Pad the boot file with zeros to the start of the mini-root.
170 */
171 bzero(block, DEV_BSIZE);
b8e366da
RC
172 i = ((nsectors - rootsize) << DEV_BSHIFT) -
173 ((length + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1));
174 n = DEV_BSIZE;
175 for (; i > 0; i -= n) {
5a9c4166
KB
176 if (write(ofd, block, n) != n)
177 goto deverr;
5a9c4166
KB
178 }
179
180 /*
181 * Write the mini-root to tape.
182 */
69c1fa90
KB
183 for (i = rootsize; i > 0; i--) {
184 if (read(rfd, block, DEV_BSIZE) != DEV_BSIZE)
185 goto rooterr;
5a9c4166
KB
186 if (write(ofd, block, DEV_BSIZE) != DEV_BSIZE)
187 goto deverr;
5a9c4166
KB
188 }
189
69c1fa90 190 (void)printf("mkboottape: wrote %d sectors\n", nsectors);
5a9c4166
KB
191 exit(0);
192}
193
69c1fa90 194void
5a9c4166
KB
195usage()
196{
69c1fa90
KB
197 (void)fprintf(stderr,
198 "usage: mkboottape [-b] tapedev vmunix minirootdev size\n");
199 exit(1);
200}
201
202#if __STDC__
203#include <stdarg.h>
204#else
205#include <varargs.h>
206#endif
207
208void
209#if __STDC__
210err(const char *fmt, ...)
211#else
212err(fmt, va_alist)
213 char *fmt;
214 va_dcl
215#endif
216{
217 va_list ap;
218#if __STDC__
219 va_start(ap, fmt);
220#else
221 va_start(ap);
222#endif
223 (void)fprintf(stderr, "mkboottape: ");
224 (void)vfprintf(stderr, fmt, ap);
225 va_end(ap);
226 (void)fprintf(stderr, "\n");
5a9c4166 227 exit(1);
69c1fa90 228 /* NOTREACHED */
5a9c4166 229}