1 /*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 * $Id: boot.c,v 1.1 94/10/20 16:45:28 root Exp $
36 */
37
38 #include "sys/param.h"
39 #include "sys/reboot.h"
40 #include <a.out.h>
41 #include "saio.h"
42 #include "disklabel.h"
43 #include "ufs_dinode.h"
44
45 /*
46 * Boot program, loaded by boot block from remaing 7.5K of boot area.
47 * Sifts through disklabel and attempts to load an program image of
48 * a standalone program off the disk. If keyboard is hit during load,
49 * or if an error is encounter, try alternate files.
50 */
51
52 char *dfiles[] = { ".askname", ".single", ".dfltroot",".kdb",
53 /* ".diagnostic", ".debug", */ 0};
54 int dflags[] = {RB_ASKNAME, RB_SINGLE, RB_DFLTROOT, RB_KDB};
55
56 char *files[] = { "386bsd", "386bsd.alt", "386bsd.old", "boot" , 0};
57 int retry = 0;
58 extern struct disklabel disklabel;
59 extern int bootdev, cyloffset;
60 static unsigned char *biosparams = (char *) 0x9ff00; /* XXX */
61
62 /*
63 * Boot program... loads /boot out of filesystem indicated by arguements.
64 * We assume an autoboot unless we detect a misconfiguration.
65 */
66
main(dev,unit,off)67 main(dev, unit, off)
68 {
69 register struct disklabel *lp;
70 register int io;
71 register char **bootfile;
72 int howto = 0;
73 extern int scsisn; /* XXX */
74
75
76 /* are we a disk, if so look at disklabel and do things */
77 lp = &disklabel;
78
79 #if DEBUG > 0
80 printf("cyl %x %x hd %x sect %x ",
81 biosparams[0], biosparams[1], biosparams[2], biosparams[0xe]);
82 printf("dev %x unit %x off %d\n", dev, unit, off);
83 #endif
84
85 if (lp->d_magic == DISKMAGIC) {
86 /*
87 * Synthesize bootdev from dev, unit, type and partition
88 * information from the block 0 bootstrap.
89 * It's dirty work, but someone's got to do it.
90 * This will be used by the filesystem primatives, and
91 * drivers. Ultimately, opendev will be created corresponding
92 * to which drive to pass to top level bootstrap.
93 */
94 for (io = 0; io < lp->d_npartitions; io++) {
95 int sn;
96
97 if (lp->d_partitions[io].p_size == 0)
98 continue;
99 if (lp->d_type == DTYPE_SCSI)
100 sn = off;
101 else
102 sn = off * lp->d_secpercyl;
103 if (lp->d_partitions[io].p_offset == sn)
104 break;
105 }
106
107 if (io == lp->d_npartitions) goto screwed;
108 cyloffset = off;
109 } else {
110 screwed:
111 /* probably a bad or non-existant disklabel */
112 io = 0 ;
113 howto |= RB_SINGLE|RB_ASKNAME ;
114 }
115
116 /* construct bootdev */
117 /* currently, PC has no way of booting off alternate controllers */
118 bootdev = MAKEBOOTDEV(/*i_dev*/ dev, /*i_adapt*/0, /*i_ctlr*/0,
119 unit, /*i_part*/io, /*i_fs*/ 1);
120
121 /* first, probe for files associated with special flags quietly */
122 bootfile = dfiles;
123 for (;;) {
124 io = namei(*bootfile);
125 if (io > 2) {
126 howto |= dflags[bootfile - dfiles];
127 #if DEBUG > 0
128 printf("howto %x ", howto);
129 #endif
130 }
131
132 if(*++bootfile == 0)
133 break;
134 }
135
136 bootfile = files;
137 for (;;) {
138 io = namei(*bootfile);
139 if (io > 2)
140 copyunix(io, howto, off);
141 else
142 printf("File not found");
143
144 printf(" - didn't load %s, ", *bootfile);
145 if (*++bootfile == 0)
146 bootfile = files;
147 printf("will try %s\n", *bootfile);
148
149 wait(1<<((retry++) + 10));
150 }
151 }
152
153 /*ARGSUSED*/
copyunix(io,howto,cyloff)154 copyunix(io, howto, cyloff)
155 register io;
156 {
157 struct exec x;
158 int i;
159 char *addr;
160 struct dinode fil;
161 int off, baseamt, extamt;
162
163 fetchi(io, &fil);
164 #if DEBUG > 1
165 printf("mode %o ", fil.di_mode);
166 #endif
167 i = iread(&fil, 0, (char *)&x, sizeof x);
168 off = sizeof x;
169 if (i != sizeof x || x.a_magic != 0413) {
170 printf("File is not an executable format");
171 return;
172 }
173
174 /* check if image loaded will be larger than main memory */
175 /* if (roundup(x.a_text, 4096) + x.a_data + x.a_bss > ???) {
176 printf("Program larger than memory");
177 return;
178 } */
179 addr = 0;
180 off = 4096;
181
182 /* check if program instruction contents larger than "low" RAM" */
183 if ((unsigned)addr <= 0x90000 && (unsigned)addr + x.a_text > 0x90000) {
184 #if DEBUG > 1
185 printf("File text split in two");
186 #endif
187 baseamt = 0x90000 - (unsigned)addr;
188 } else
189 baseamt = x.a_text;
190
191 #if DEBUG > 1
192 printf("o %x a %x s %x ", off, addr, baseamt);
193 #endif
194 if (iread(&fil, off, addr, baseamt) != baseamt)
195 goto shread;
196 off += baseamt;
197 addr += baseamt;
198
199 if (baseamt != x.a_text) {
200 addr = (char *)0x100000;
201 extamt = x.a_text - baseamt;
202 #if DEBUG > 1
203 printf("o %x a %x s %x ", off, addr, extamt);
204 #endif
205 if (iread(&fil, off, addr, extamt) != extamt)
206 goto shread;
207 off += extamt;
208 addr += extamt;
209 }
210
211 addr = (char *)x.a_text;
212 while ((int)addr & (NBPG-1))
213 *addr++ = 0;
214
215 /* check if program data contents larger than "low" RAM" */
216 if ((unsigned)addr <= 0x90000 && (unsigned)addr + x.a_data > 0x90000) {
217 #if DEBUG > 1
218 printf("File data split in two");
219 #endif
220 baseamt = 0x90000 - (int)addr;
221 } else
222 baseamt = x.a_data;
223
224 #if DEBUG > 1
225 printf("o %x a %x s %x ", off, addr, baseamt);
226 #endif
227 if (iread(&fil, off, addr, baseamt) != baseamt)
228 goto shread;
229 off += baseamt;
230 addr += baseamt;
231
232 if (baseamt != x.a_data) {
233 addr = (char *)0x100000;
234 extamt = x.a_data - baseamt;
235 #if DEBUG > 1
236 printf("o %x a %x s %x ", off, addr, extamt);
237 #endif
238 if (iread(&fil, off, addr, extamt) != extamt)
239 goto shread;
240 off += extamt;
241 addr += extamt;
242 }
243
244 #if DEBUG > 1
245 printf("o %x a %x bss %x ", off, addr, x.a_bss);
246 #endif
247 if ((unsigned)addr <= 0x90000 && (unsigned)addr + x.a_bss > 0x90000) {
248 #if DEBUG > 1
249 printf("File BSS split in two");
250 #endif
251 baseamt = 0x90000 - (int)addr;
252 bzero(addr, baseamt);
253 addr = (char *)0x100000;
254 extamt = x.a_bss - baseamt;
255 bzero(addr, extamt);
256 addr += extamt;
257 } else {
258 bzero(addr, x.a_bss);
259 addr += x.a_bss;
260 }
261 /* XXX: read syms and strings */
262 {
263 io = namei(".config");
264 if (io > 2) {
265 printf("cfg ");
266 /*addr += 4096; (int)addr &= ~(4096-1);*/
267 fetchi(io, &fil);
268 (void)iread(&fil, 0, addr, 4096);
269 }
270 }
271
272 /* mask high order bits corresponding to relocated system base */
273 x.a_entry &= ~0xfff00000;
274
275 /*if (scankbd()) {
276 printf("Operator abort");
277 kbdreset();
278 return;
279 }*/
280
281 #if DEBUG > 0
282 printf("entry %x [%x]\n", x.a_entry, *(int *) x.a_entry);
283 #endif
284 bcopy(0x9ff00, 0x300, 0x20); /* XXX */
285 i = (*((int (*)()) x.a_entry))(howto, bootdev, 0x90000);
286
287 if (i)
288 printf("Program exits with %d", i) ;
289 return;
290 shread:
291 printf("Read of program is incomplete");
292 return;
293 }
294