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