xref: /openbsd-src/sys/arch/i386/i386/autoconf.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: autoconf.c,v 1.36 2001/06/25 00:43:11 mickey Exp $	*/
2 /*	$NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * William Jolitz.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	@(#)autoconf.c	7.1 (Berkeley) 5/9/91
40  */
41 
42 /*
43  * Setup the system to run on the current machine.
44  *
45  * cpu_configure() is called at boot time and initializes the vba
46  * device tables and the memory controller monitoring.  Available
47  * devices are determined (from possibilities mentioned in ioconf.c),
48  * and the drivers are initialized.
49  */
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/buf.h>
53 #include <sys/dkstat.h>
54 #include <sys/disklabel.h>
55 #include <sys/conf.h>
56 #include <sys/dmap.h>
57 #include <sys/reboot.h>
58 #include <sys/device.h>
59 
60 #include <machine/pte.h>
61 #include <machine/cpu.h>
62 #include <machine/biosvar.h>
63 
64 #include <dev/cons.h>
65 
66 void rootconf __P((void));
67 void swapconf __P((void));
68 void setroot __P((void));
69 void diskconf __P((void));
70 
71 /*
72  * The following several variables are related to
73  * the configuration process, and are used in initializing
74  * the machine.
75  */
76 dev_t	bootdev = 0;		/* bootdevice, initialized in locore.s */
77 
78 /*
79  * Determine i/o configuration for a machine.
80  */
81 void
82 cpu_configure()
83 {
84 
85 	startrtclock();
86 
87 	if (config_rootfound("mainbus", NULL) == NULL)
88 		panic("cpu_configure: mainbus not configured");
89 
90 	printf("biomask %x netmask %x ttymask %x\n",
91 	    (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET],
92 	    (u_short)imask[IPL_TTY]);
93 
94 	spl0();
95 
96 	/*
97 	 * We can not know which is our root disk, defer
98 	 * until we can checksum blocks to figure it out.
99 	 */
100 	md_diskconf = diskconf;
101 	cold = 0;
102 
103 	/* Set up proc0's TSS and LDT (after the FPU is configured). */
104 	i386_proc0_tss_ldt_init();
105 }
106 
107 /*
108  * Now that we are fully operational, we can checksum the
109  * disks, and using some heuristics, hopefully are able to
110  * always determine the correct root disk.
111  */
112 void
113 diskconf()
114 {
115 	/*
116 	 * Configure root, swap, and dump area.  This is
117 	 * currently done by running the same checksum
118 	 * algorithm over all known disks, as was done in
119 	 * /boot.  Then we basically fixup the *dev vars
120 	 * from the info we gleaned from this.
121 	 */
122 	dkcsumattach();
123 
124 	rootconf();
125 	swapconf();
126 	dumpconf();
127 }
128 
129 /*
130  * Configure swap space and related parameters.
131  */
132 void
133 swapconf()
134 {
135 	register struct swdevt *swp;
136 	register int nblks;
137 
138 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
139 		int maj = major(swp->sw_dev);
140 
141 		if (maj > nblkdev)
142 			break;
143 		if (bdevsw[maj].d_psize) {
144 			nblks = (*bdevsw[maj].d_psize)(swp->sw_dev);
145 			if (nblks != -1 &&
146 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
147 				swp->sw_nblks = nblks;
148 			swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
149 		}
150 	}
151 }
152 
153 #define	DOSWAP			/* change swdevt and dumpdev */
154 
155 static const char *devname[] = {
156 	"wd",		/* 0 = wd */
157 	"sw",		/* 1 = sw */
158 	"fd",		/* 2 = fd */
159 	"wt",		/* 3 = wt */
160 	"sd",		/* 4 = sd */
161 	"",		/* 5 */
162 	"",		/* 6 */
163 	"mcd",		/* 7 = mcd */
164 	"",		/* 8 */
165 	"",		/* 9 */
166 	"",		/* 10 */
167 	"",		/* 11 */
168 	"",		/* 12 */
169 	"",		/* 13 */
170 	"",		/* 14 */
171 	"",		/* 15 */
172 	"",		/* 16 */
173 	"rd",		/* 17 = rd */
174 	"",		/* 18 */
175 	"",		/* 19 */
176 	""		/* 20 */
177 };
178 
179 dev_t	argdev = NODEV;
180 int	nswap;
181 long	dumplo;
182 int	dmmin, dmmax, dmtext;
183 
184 /*
185  * Attempt to find the device from which we were booted.
186  * If we can do so, and not instructed not to do so,
187  * change rootdev to correspond to the load device.
188  */
189 void
190 setroot()
191 {
192 	int  majdev, mindev, unit, part, adaptor;
193 	dev_t orootdev;
194 #ifdef DOSWAP
195 	dev_t temp = 0;
196 #endif
197 	struct swdevt *swp;
198 
199 	if (boothowto & RB_DFLTROOT ||
200 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
201 		return;
202 	majdev = B_TYPE(bootdev);
203 	if (majdev > sizeof(devname)/sizeof(devname[0]) ||
204 	    *devname[majdev] == '\0')
205 		return;
206 	adaptor = B_ADAPTOR(bootdev);
207 	part = B_PARTITION(bootdev);
208 	unit = B_UNIT(bootdev);
209 	mindev = (unit * MAXPARTITIONS) + part;
210 	orootdev = rootdev;
211 	rootdev = makedev(majdev, mindev);
212 	/*
213 	 * If the original rootdev is the same as the one
214 	 * just calculated, don't need to adjust the swap configuration.
215 	 */
216 	if (rootdev == orootdev)
217 		return;
218 	printf("root on %s%d%c\n", devname[majdev], unit, part + 'a');
219 
220 #ifdef DOSWAP
221 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
222 		if (majdev == major(swp->sw_dev) &&
223 		    mindev/MAXPARTITIONS == minor(swp->sw_dev)/MAXPARTITIONS) {
224 			temp = swdevt[0].sw_dev;
225 			swdevt[0].sw_dev = swp->sw_dev;
226 			swp->sw_dev = temp;
227 			break;
228 		}
229 	}
230 	if (swp->sw_dev == NODEV)
231 		return;
232 
233 	/*
234 	 * If dumpdev was the same as the old primary swap device, move
235 	 * it to the new primary swap device.
236 	 */
237 	if (temp == dumpdev)
238 		dumpdev = swdevt[0].sw_dev;
239 #endif
240 }
241 
242 #include "wd.h"
243 #if NWD > 0
244 extern	struct cfdriver wd_cd;
245 #endif
246 #include "sd.h"
247 #if NSD > 0
248 extern	struct cfdriver sd_cd;
249 #endif
250 #include "cd.h"
251 #if NCD > 0
252 extern	struct cfdriver cd_cd;
253 #endif
254 #include "mcd.h"
255 #if NMCD > 0
256 extern	struct cfdriver mcd_cd;
257 #endif
258 #include "fd.h"
259 #if NFD > 0
260 extern	struct cfdriver fd_cd;
261 #endif
262 #include "rd.h"
263 #if NRD > 0
264 extern	struct cfdriver rd_cd;
265 #endif
266 
267 struct	genericconf {
268 	struct cfdriver *gc_driver;
269 	char *gc_name;
270 	dev_t gc_major;
271 } genericconf[] = {
272 #if NWD > 0
273 	{ &wd_cd,  "wd",  0 },
274 #endif
275 #if NFD > 0
276 	{ &fd_cd,  "fd",  2 },
277 #endif
278 #if NSD > 0
279 	{ &sd_cd,  "sd",  4 },
280 #endif
281 #if NCD > 0
282 	{ &cd_cd,  "cd",  6 },
283 #endif
284 #if NMCD > 0
285 	{ &mcd_cd, "mcd", 7 },
286 #endif
287 #if NRD > 0
288 	{ &rd_cd,  "rd",  17 },
289 #endif
290 	{ 0 }
291 };
292 
293 void
294 rootconf()
295 {
296 	register struct genericconf *gc;
297 	int unit, part = 0;
298 	char *num;
299 
300 #ifdef INSTALL
301 	if (B_TYPE(bootdev) == 2) {
302 		printf("\n\nInsert file system floppy...\n");
303 		if (!(boothowto & RB_ASKNAME))
304 			cngetc();
305 	}
306 #endif
307 
308 	if (boothowto & RB_ASKNAME) {
309 		char name[128];
310 retry:
311 		printf("root device? ");
312 		getsn(name, sizeof name);
313 		if (*name == '\0')
314 			goto noask;
315 		for (gc = genericconf; gc->gc_driver; gc++)
316 			if (gc->gc_driver->cd_ndevs &&
317 			    strncmp(gc->gc_name, name,
318 			    strlen(gc->gc_name)) == 0)
319 				break;
320 		if (gc->gc_driver) {
321 			num = &name[strlen(gc->gc_name)];
322 
323 			unit = -2;
324 			do {
325 				if (unit != -2 && *num >= 'a' &&
326 				    *num <= 'a'+MAXPARTITIONS-1 &&
327 				    num[1] == '\0') {
328 					part = *num++ - 'a';
329 					break;
330 				}
331 				if (unit == -2)
332 					unit = 0;
333 				unit = (unit * 10) + *num - '0';
334 				if (*num < '0' || *num > '9')
335 					unit = -1;
336 			} while (unit != -1 && *++num);
337 
338 			if (unit < 0) {
339 				printf("%s: not a unit number\n",
340 				    &name[strlen(gc->gc_name)]);
341 			} else if (unit > gc->gc_driver->cd_ndevs ||
342 			    gc->gc_driver->cd_devs[unit] == NULL) {
343 				printf("%d: no such unit\n", unit);
344 			} else {
345 				printf("root on %s%d%c\n", gc->gc_name, unit,
346 				    'a' + part);
347 				rootdev = makedev(gc->gc_major,
348 				    unit * MAXPARTITIONS + part);
349 				goto doswap;
350 			}
351 		}
352 		printf("use one of: ");
353 		for (gc = genericconf; gc->gc_driver; gc++) {
354 			for (unit=0; unit < gc->gc_driver->cd_ndevs; unit++) {
355 				if (gc->gc_driver->cd_devs[unit])
356 					printf("%s%d[a-%c] ", gc->gc_name,
357 					    unit, 'a'+MAXPARTITIONS-1);
358 			}
359 		}
360 		printf("\n");
361 		goto retry;
362 	}
363 noask:
364 	if (mountroot == NULL) {
365 		/* `swap generic' */
366 		setroot();
367 	} else {
368 		/* preconfigured */
369 		return;
370 	}
371 
372 doswap:
373 #ifndef DISKLESS
374 	mountroot = dk_mountroot;
375 #endif
376 	swdevt[0].sw_dev = argdev = dumpdev =
377 	    makedev(major(rootdev), minor(rootdev) + 1);
378 	/* swap size and dumplo set during autoconfigure */
379 }
380