xref: /386bsd/usr/src/bootstrap/boot/boot.c (revision a2142627)
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