1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)autoconf.c 7.1 (Berkeley) 07/13/92 12 * 13 * from: $Header: autoconf.c,v 1.23 92/07/10 22:35:23 torek Exp $ (LBL) 14 */ 15 16 #include "sys/param.h" 17 #include "sys/map.h" 18 #include "sys/buf.h" 19 #include "sys/disklabel.h" 20 #include "sys/device.h" 21 #include "sys/dkstat.h" 22 #include "sys/conf.h" 23 #include "sys/dmap.h" 24 #include "sys/reboot.h" 25 #include "sys/socket.h" 26 #include "sys/systm.h" 27 28 #include "net/if.h" 29 30 #include "machine/autoconf.h" 31 #include "machine/bsd_openprom.h" 32 #include "machine/cpu.h" 33 34 #ifndef FS_NFS /* XXX */ 35 #define FS_NFS 100 /* XXX */ 36 #endif /* XXX */ 37 38 /* 39 * The following several variables are related to 40 * the configuration process, and are used in initializing 41 * the machine. 42 */ 43 int cold; /* if 1, still working on cold-start */ 44 int dkn; /* number of iostat dk numbers assigned so far */ 45 int cpuspeed = 10; /* relative cpu speed */ 46 int fbnode; /* node ID of ROM's console frame buffer */ 47 int optionsnode; /* node ID of ROM's options */ 48 49 extern struct promvec *promvec; 50 51 static int rootnode; 52 int findroot(); 53 static struct bootinfo *findbootdev(); 54 55 static struct bootinfo { 56 char name[16]; /* device name */ 57 int val[3]; /* up to 3 values */ 58 int type; /* FS type */ 59 caddr_t data; /* FS dependant info */ 60 } bootinfo; 61 62 63 /* 64 * Most configuration on the SPARC is done by matching OPENPROM Forth 65 * device names with our internal names. 66 */ 67 int 68 matchbyname(parent, cf, aux) 69 struct device *parent; 70 struct cfdata *cf; 71 void *aux; 72 { 73 74 return (strcmp(cf->cf_driver->cd_name, *(char **)aux) == 0); 75 } 76 77 /* 78 * Convert hex ASCII string to a value. Returns updated pointer. 79 * Depends on ASCII order (this *is* machine-dependent code, you know). 80 */ 81 static char * 82 str2hex(str, vp) 83 register char *str; 84 register int *vp; 85 { 86 register int v, c; 87 88 for (v = 0;; v = v * 16 + c, str++) { 89 c = *(u_char *)str; 90 if (c <= '9') { 91 if ((c -= '0') < 0) 92 break; 93 } else if (c <= 'F') { 94 if ((c -= 'A' - 10) < 10) 95 break; 96 } else if (c <= 'f') { 97 if ((c -= 'a' - 10) < 10) 98 break; 99 } else 100 break; 101 } 102 *vp = v; 103 return (str); 104 } 105 106 /* 107 * locore.s code calls bootstrap() just before calling main(), after double 108 * mapping the kernel to high memory and setting up the trap base register. 109 * We must finish mapping the kernel properly and glean any bootstrap info. 110 */ 111 void 112 bootstrap() 113 { 114 register char *cp, *bp, *ep; 115 register int i; 116 int nmmu, ncontext, node; 117 #ifdef KGDB 118 extern int kgdb_debug_panic; 119 #endif 120 extern char *rindex(const char *, int); 121 122 node = findroot(); 123 nmmu = getpropint(node, "mmu-npmg", 128); 124 ncontext = getpropint(node, "mmu-nctx", 8); 125 pmap_bootstrap(nmmu, ncontext); 126 #ifdef KGDB 127 zs_kgdb_init(); /* XXX */ 128 #endif 129 /* 130 * On SS1s, promvec->pv_v0bootargs->ba_argv[1] contains the flags 131 * that were given after the boot command. On SS2s, pv_v0bootargs 132 * is NULL but *promvec->pv_v2bootargs.v2_bootargs points to 133 * "vmunix -s" or whatever. 134 * ### DO THIS BEFORE pmap_boostrap? 135 */ 136 if (promvec->pv_romvec_vers < 2) { 137 /* Grab boot device name and values. */ 138 cp = (*promvec->pv_v0bootargs)->ba_argv[0]; 139 if (cp != NULL) { 140 bp = bootinfo.name; 141 ep = &bootinfo.name[sizeof(bootinfo.name)]; 142 while (*cp != '(' && *cp != '\0' && bp < ep - 1) 143 *bp++ = *cp++; 144 *bp = '\0'; 145 146 if (*cp == '(' && 147 *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 148 *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 149 (void)str2hex(++cp, &bootinfo.val[2]); 150 } 151 152 /* Setup pointer to boot flags */ 153 cp = (*promvec->pv_v0bootargs)->ba_argv[1]; 154 if (cp == NULL || *cp != '-') 155 return; 156 } else { 157 /* Grab boot device name and values. */ 158 cp = *promvec->pv_v2bootargs.v2_bootpath; 159 if (cp != NULL && (cp = rindex(cp, '/')) != NULL) { 160 ++cp; 161 bp = bootinfo.name; 162 ep = &bootinfo.name[sizeof(bootinfo.name)]; 163 while (*cp != '@' && *cp != '\0' && bp < ep - 1) 164 *bp++ = *cp++; 165 *bp = '\0'; 166 167 if (*cp == '@' && 168 *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 169 *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 170 (void)str2hex(++cp, &bootinfo.val[2]); 171 } 172 173 /* Setup pointer to boot flags */ 174 cp = *promvec->pv_v2bootargs.v2_bootargs; 175 if (cp == NULL) 176 return; 177 while (*cp != '-') 178 if (*cp++ == '\0') 179 return; 180 } 181 for (;;) { 182 switch (*++cp) { 183 184 case '\0': 185 return; 186 187 case 'a': 188 boothowto |= RB_ASKNAME; 189 break; 190 191 case 'b': 192 boothowto |= RB_DFLTROOT; 193 break; 194 195 case 'd': /* kgdb - always on zs XXX */ 196 #ifdef KGDB 197 boothowto |= RB_KDB; /* XXX unused */ 198 kgdb_debug_panic = 1; 199 kgdb_connect(1); 200 #else 201 printf("kernel not compiled with KGDB\n"); 202 #endif 203 break; 204 205 case 's': 206 boothowto |= RB_SINGLE; 207 break; 208 } 209 } 210 } 211 212 /* 213 * Determine mass storage and memory configuration for a machine. 214 * We get the PROM's root device and make sure we understand it, then 215 * attach it as `mainbus0'. We also set up to handle the PROM `sync' 216 * command. 217 */ 218 configure() 219 { 220 register int node; 221 register char *cp; 222 struct romaux ra; 223 void sync_crash(); 224 #ifdef NFS 225 register struct bootinfo *bi; 226 extern int (*mountroot)(), nfs_mountroot(); 227 #endif 228 229 node = findroot(); 230 cp = getpropstring(node, "device_type"); 231 if (strcmp(cp, "cpu") != 0) { 232 printf("PROM root device type = %s\n", cp); 233 panic("need CPU as root"); 234 } 235 *promvec->pv_synchook = sync_crash; 236 ra.ra_node = node; 237 ra.ra_name = cp = "mainbus"; 238 if (!config_rootfound(cp, (void *)&ra)) 239 panic("mainbus not configured"); 240 (void) spl0(); 241 cold = 0; 242 #ifdef NFS 243 if (boothowto & RB_ASKNAME) { 244 char ans[100]; 245 246 printf("nfs root? (y/n) [n] "); 247 gets(ans); 248 if (ans[0] == 'y') 249 mountroot = nfs_mountroot; 250 } else if ((bi = findbootdev()) != NULL && bi->type == FS_NFS) { 251 mountroot = nfs_mountroot; 252 #ifdef LBL 253 lbl_diskless_setup(); 254 #endif /* LBL */ 255 } 256 #endif /* NFS */ 257 #if GENERIC 258 if ((boothowto & RB_ASKNAME) == 0) 259 setroot(); 260 setconf(); 261 #else 262 setroot(); 263 #endif 264 swapconf(); 265 } 266 267 /* 268 * Console `sync' command. SunOS just does a `panic: zero' so I guess 269 * no one really wants anything fancy... 270 */ 271 void 272 sync_crash() 273 { 274 275 panic("PROM sync command"); 276 } 277 278 char * 279 clockfreq(freq) 280 register int freq; 281 { 282 register char *p; 283 static char buf[10]; 284 285 freq /= 1000; 286 sprintf(buf, "%d", freq / 1000); 287 freq %= 1000; 288 if (freq) { 289 freq += 1000; /* now in 1000..1999 */ 290 p = buf + strlen(buf); 291 sprintf(p, "%d", freq); 292 *p = '.'; /* now buf = %d.%3d */ 293 } 294 return (buf); 295 } 296 297 /* ARGSUSED */ 298 static int 299 mbprint(aux, name) 300 void *aux; 301 char *name; 302 { 303 register struct romaux *ra = aux; 304 305 if (name) 306 printf("%s at %s", ra->ra_name, name); 307 if (ra->ra_paddr) 308 printf(" %saddr 0x%x", ra->ra_iospace ? "io" : "", 309 (int)ra->ra_paddr); 310 return (UNCONF); 311 } 312 313 int 314 findroot() 315 { 316 register int node; 317 318 if ((node = rootnode) == 0 && (node = nextsibling(0)) == 0) 319 panic("no PROM root device"); 320 rootnode = node; 321 return (node); 322 } 323 324 /* 325 * Given a `first child' node number, locate the node with the given name. 326 * Return the node number, or 0 if not found. 327 */ 328 int 329 findnode(first, name) 330 int first; 331 register char *name; 332 { 333 register int node; 334 335 for (node = first; node; node = nextsibling(node)) 336 if (strcmp(getpropstring(node, "name"), name) == 0) 337 return (node); 338 return (0); 339 } 340 341 /* 342 * Fill in a romaux. Returns 1 on success, 0 if the register property 343 * was not the right size. 344 */ 345 int 346 romprop(rp, cp, node) 347 register struct romaux *rp; 348 const char *cp; 349 register int node; 350 { 351 register int len; 352 union { char regbuf[64]; int ireg[3]; } u; 353 static const char pl[] = "property length"; 354 355 len = getprop(node, "reg", (void *)u.regbuf, sizeof u.regbuf); 356 if (len < 12) { 357 printf("%s \"reg\" %s = %d (need 12)\n", cp, pl, len); 358 return (0); 359 } 360 if (len > 12) 361 printf("warning: %s \"reg\" %s %d > 12, excess ignored\n", 362 cp, pl, len); 363 rp->ra_node = node; 364 rp->ra_name = cp; 365 rp->ra_iospace = u.ireg[0]; 366 rp->ra_paddr = (caddr_t)u.ireg[1]; 367 rp->ra_len = u.ireg[2]; 368 rp->ra_vaddr = (caddr_t)getpropint(node, "address", 0); 369 len = getprop(node, "intr", (void *)&rp->ra_intr, sizeof rp->ra_intr); 370 if (len == -1) 371 len = 0; 372 if (len & 7) { 373 printf("%s \"intr\" %s = %d (need multiple of 8)\n", 374 cp, pl, len); 375 len = 0; 376 } 377 rp->ra_nintr = len >>= 3; 378 /* SPARCstation interrupts are not hardware-vectored */ 379 while (--len >= 0) { 380 if (rp->ra_intr[len].int_vec) { 381 printf("WARNING: %s interrupt %d has nonzero vector\n", 382 cp, len); 383 break; 384 } 385 } 386 return (1); 387 } 388 389 /* 390 * Attach the mainbus. 391 * 392 * Our main job is to attach the CPU (the root node we got in configure()) 393 * and iterate down the list of `mainbus devices' (children of that node). 394 * We also record the `node id' of the default frame buffer, if any. 395 */ 396 static void 397 mainbus_attach(parent, dev, aux) 398 struct device *parent, *dev; 399 void *aux; 400 { 401 register int node0, node; 402 register const char *cp, *const *ssp, *sp; 403 #define L1A_HACK /* XXX hack to allow L1-A during autoconf */ 404 #ifdef L1A_HACK 405 int nzs = 0, audio = 0; 406 #endif 407 struct romaux ra; 408 static const char *const special[] = { 409 /* find these first (end with empty string) */ 410 "memory-error", "eeprom", "counter-timer", "", 411 412 /* ignore these (end with NULL) */ 413 "options", "packages", "openprom", "memory", "virtual-memory", 414 "interrupt-enable", NULL 415 }; 416 417 printf("\n"); 418 419 /* configure the cpu */ 420 node = ((struct romaux *)aux)->ra_node; 421 ra.ra_node = node; 422 ra.ra_name = cp = "cpu"; 423 ra.ra_paddr = 0; 424 config_found(dev, (void *)&ra, mbprint); 425 426 /* remember which frame buffer, if any, is to be /dev/fb */ 427 fbnode = getpropint(node, "fb", 0); 428 429 /* Find the "options" node */ 430 node0 = firstchild(node); 431 optionsnode = findnode(node0, "options"); 432 if (optionsnode == 0) 433 panic("no options in OPENPROM"); 434 435 /* 436 * Locate and configure the ``early'' devices. These must be 437 * configured before we can do the rest. For instance, the 438 * EEPROM contains the Ethernet address for the LANCE chip. 439 * If the device cannot be located or configured, panic. 440 */ 441 for (ssp = special; *(sp = *ssp) != 0; ssp++) { 442 if ((node = findnode(node0, sp)) == 0) { 443 printf("could not find %s in OPENPROM\n", sp); 444 panic(sp); 445 } 446 if (!romprop(&ra, sp, node) || 447 !config_found(dev, (void *)&ra, mbprint)) 448 panic(sp); 449 } 450 451 /* 452 * Configure the rest of the devices, in PROM order. Skip 453 * PROM entries that are not for devices, or which must be 454 * done before we get here. 455 */ 456 for (node = node0; node; node = nextsibling(node)) { 457 cp = getpropstring(node, "name"); 458 for (ssp = special; (sp = *ssp) != NULL; ssp++) 459 if (strcmp(cp, sp) == 0) 460 break; 461 if (sp == NULL && romprop(&ra, cp, node)) { 462 #ifdef L1A_HACK 463 if (strcmp(cp, "audio") == 0) 464 audio = 1; 465 if (strcmp(cp, "zs") == 0) 466 nzs++; 467 if (audio && nzs >= 2) 468 (void) splx(11 << 8); /* XXX */ 469 #endif 470 (void) config_found(dev, (void *)&ra, mbprint); 471 } 472 } 473 } 474 475 struct cfdriver mainbuscd = 476 { NULL, "mainbus", matchbyname, mainbus_attach, 477 DV_DULL, sizeof(struct device) }; 478 479 /* 480 * findzs() is called from the zs driver (which is, at least in theory, 481 * generic to any machine with a Zilog ZSCC chip). It should return the 482 * address of the corresponding zs channel. It may not fail, and it 483 * may be called before the VM code can be used. Here we count on the 484 * FORTH PROM to map in the required zs chips. 485 */ 486 void * 487 findzs(zs) 488 int zs; 489 { 490 register int node, addr; 491 492 node = firstchild(findroot()); 493 while ((node = findnode(node, "zs")) != 0) { 494 if (getpropint(node, "slave", -1) == zs) { 495 if ((addr = getpropint(node, "address", 0)) == 0) 496 panic("findzs: zs%d not mapped by PROM", zs); 497 return ((void *)addr); 498 } 499 node = nextsibling(node); 500 } 501 panic("findzs: cannot find zs%d", zs); 502 /* NOTREACHED */ 503 } 504 505 int 506 makememarr(ap, max, which) 507 register struct memarr *ap; 508 int max, which; 509 { 510 struct v2rmi { 511 int zero; 512 int addr; 513 int len; 514 } v2rmi[200]; /* version 2 rom meminfo layout */ 515 #define MAXMEMINFO (sizeof(v2rmi) / sizeof(*v2rmi)) 516 register struct v0mlist *mp; 517 register int i, node, len; 518 char *prop; 519 520 switch (i = promvec->pv_romvec_vers) { 521 522 case 0: 523 /* 524 * Version 0 PROMs use a linked list to describe these 525 * guys. 526 */ 527 switch (which) { 528 529 case MEMARR_AVAILPHYS: 530 mp = *promvec->pv_v0mem.v0_physavail; 531 break; 532 533 case MEMARR_TOTALPHYS: 534 mp = *promvec->pv_v0mem.v0_phystot; 535 break; 536 537 default: 538 panic("makememarr"); 539 } 540 for (i = 0; mp != NULL; mp = mp->next, i++) { 541 if (i >= max) 542 goto overflow; 543 ap->addr = (u_int)mp->addr; 544 ap->len = mp->nbytes; 545 ap++; 546 } 547 break; 548 549 default: 550 printf("makememarr: hope version %d PROM is like version 2\n", 551 i); 552 /* FALLTHROUGH */ 553 554 case 2: 555 /* 556 * Version 2 PROMs use a property array to describe them. 557 */ 558 if (max > MAXMEMINFO) { 559 printf("makememarr: limited to %d\n", MAXMEMINFO); 560 max = MAXMEMINFO; 561 } 562 if ((node = findnode(firstchild(findroot()), "memory")) == 0) 563 panic("makememarr: cannot find \"memory\" node"); 564 switch (which) { 565 566 case MEMARR_AVAILPHYS: 567 prop = "available"; 568 break; 569 570 case MEMARR_TOTALPHYS: 571 prop = "reg"; 572 break; 573 574 default: 575 panic("makememarr"); 576 } 577 len = getprop(node, prop, (void *)v2rmi, sizeof v2rmi) / 578 sizeof(struct v2rmi); 579 for (i = 0; i < len; i++) { 580 if (i >= max) 581 goto overflow; 582 ap->addr = v2rmi[i].addr; 583 ap->len = v2rmi[i].len; 584 ap++; 585 } 586 break; 587 } 588 589 /* 590 * Success! (Hooray) 591 */ 592 if (i == 0) 593 panic("makememarr: no memory found"); 594 return (i); 595 596 overflow: 597 /* 598 * Oops, there are more things in the PROM than our caller 599 * provided space for. Truncate any extras. 600 */ 601 printf("makememarr: WARNING: lost some memory\n"); 602 return (i); 603 } 604 605 /* 606 * Internal form of getprop(). Returns the actual length. 607 */ 608 int 609 getprop(node, name, buf, bufsiz) 610 int node; 611 char *name; 612 void *buf; 613 register int bufsiz; 614 { 615 register struct nodeops *no; 616 register int len; 617 618 no = promvec->pv_nodeops; 619 len = no->no_proplen(node, name); 620 if (len > bufsiz) { 621 printf("node %x property %s length %d > %d\n", 622 node, name, len, bufsiz); 623 #ifdef DEBUG 624 panic("getprop"); 625 #else 626 return (0); 627 #endif 628 } 629 no->no_getprop(node, name, buf); 630 return (len); 631 } 632 633 /* 634 * Return a string property. There is a (small) limit on the length; 635 * the string is fetched into a static buffer which is overwritten on 636 * subsequent calls. 637 */ 638 char * 639 getpropstring(node, name) 640 int node; 641 char *name; 642 { 643 register int len; 644 static char stringbuf[32]; 645 646 len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); 647 stringbuf[len] = '\0'; /* usually unnecessary */ 648 return (stringbuf); 649 } 650 651 /* 652 * Fetch an integer (or pointer) property. 653 * The return value is the property, or the default if there was none. 654 */ 655 int 656 getpropint(node, name, deflt) 657 int node; 658 char *name; 659 int deflt; 660 { 661 register int len; 662 char intbuf[16]; 663 664 len = getprop(node, name, (void *)intbuf, sizeof intbuf); 665 if (len != 4) 666 return (deflt); 667 return (*(int *)intbuf); 668 } 669 670 /* 671 * OPENPROM functions. These are here mainly to hide the OPENPROM interface 672 * from the rest of the kernel. 673 */ 674 int 675 firstchild(node) 676 int node; 677 { 678 679 return (promvec->pv_nodeops->no_child(node)); 680 } 681 682 int 683 nextsibling(node) 684 int node; 685 { 686 687 return (promvec->pv_nodeops->no_nextnode(node)); 688 } 689 690 /* Pass a string to the FORTH PROM to be interpreted */ 691 void 692 rominterpret(s) 693 register char *s; 694 { 695 696 if (promvec->pv_romvec_vers < 2) 697 promvec->pv_fortheval.v0_eval(strlen(s), s); 698 else 699 promvec->pv_fortheval.v2_eval(s); 700 } 701 702 volatile void 703 romhalt() 704 { 705 706 promvec->pv_halt(); 707 panic("PROM exit failed"); 708 } 709 710 volatile void 711 romboot(str) 712 char *str; 713 { 714 715 promvec->pv_reboot(str); 716 panic("PROM boot failed"); 717 } 718 719 callrom() 720 { 721 722 #ifdef notdef /* sun4c FORTH PROMs do this for us */ 723 fb_unblank(); 724 #endif 725 promvec->pv_abort(); 726 } 727 728 /* 729 * Configure swap space and related parameters. 730 */ 731 swapconf() 732 { 733 register struct swdevt *swp; 734 register int nblks; 735 736 for (swp = swdevt; swp->sw_dev; swp++) 737 if (bdevsw[major(swp->sw_dev)].d_psize) { 738 nblks = 739 (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 740 if (nblks != -1 && 741 (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 742 swp->sw_nblks = nblks; 743 } 744 dumpconf(); 745 } 746 747 #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ 748 u_long bootdev; /* should be dev_t, but not until 32 bits */ 749 750 static char devname[][2] = { 751 0,0, /* 0 = xx */ 752 }; 753 754 #define PARTITIONMASK 0x7 755 #define PARTITIONSHIFT 3 756 757 /* 758 * Attempt to find the device from which we were booted. 759 * If we can do so, and not instructed not to do so, 760 * change rootdev to correspond to the load device. 761 */ 762 setroot() 763 { 764 #ifdef notyet 765 struct swdevt *swp; 766 767 if (boothowto & RB_DFLTROOT || 768 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 769 return; 770 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 771 if (majdev > sizeof(devname) / sizeof(devname[0])) 772 return; 773 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 774 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 775 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 776 /* 777 * First, find the controller type which support this device. 778 */ 779 for (hd = hp_dinit; hd->hp_driver; hd++) 780 if (hd->hp_driver->d_name[0] == devname[majdev][0] && 781 hd->hp_driver->d_name[1] == devname[majdev][1]) 782 break; 783 if (hd->hp_driver == 0) 784 return; 785 /* 786 * Next, find the controller of that type corresponding to 787 * the adaptor number. 788 */ 789 for (hc = hp_cinit; hc->hp_driver; hc++) 790 if (hc->hp_alive && hc->hp_unit == adaptor && 791 hc->hp_driver == hd->hp_cdriver) 792 break; 793 if (hc->hp_driver == 0) 794 return; 795 /* 796 * Finally, find the device in question attached to that controller. 797 */ 798 for (hd = hp_dinit; hd->hp_driver; hd++) 799 if (hd->hp_alive && hd->hp_slave == unit && 800 hd->hp_cdriver == hc->hp_driver && 801 hd->hp_ctlr == hc->hp_unit) 802 break; 803 if (hd->hp_driver == 0) 804 return; 805 mindev = hd->hp_unit; 806 /* 807 * Form a new rootdev 808 */ 809 mindev = (mindev << PARTITIONSHIFT) + part; 810 orootdev = rootdev; 811 rootdev = makedev(majdev, mindev); 812 /* 813 * If the original rootdev is the same as the one 814 * just calculated, don't need to adjust the swap configuration. 815 */ 816 if (rootdev == orootdev) 817 return; 818 819 printf("Changing root device to %c%c%d%c\n", 820 devname[majdev][0], devname[majdev][1], 821 mindev >> PARTITIONSHIFT, part + 'a'); 822 823 #ifdef DOSWAP 824 mindev &= ~PARTITIONMASK; 825 for (swp = swdevt; swp->sw_dev; swp++) { 826 if (majdev == major(swp->sw_dev) && 827 mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { 828 temp = swdevt[0].sw_dev; 829 swdevt[0].sw_dev = swp->sw_dev; 830 swp->sw_dev = temp; 831 break; 832 } 833 } 834 if (swp->sw_dev == 0) 835 return; 836 837 /* 838 * If argdev and dumpdev were the same as the old primary swap 839 * device, move them to the new primary swap device. 840 */ 841 if (temp == dumpdev) 842 dumpdev = swdevt[0].sw_dev; 843 if (temp == argdev) 844 argdev = swdevt[0].sw_dev; 845 #endif 846 #endif 847 } 848 849 /* 850 * Return pointer to device we booted from. Return NULL if we can't 851 * figure this out. 852 * XXX currently only works for network devices. 853 */ 854 855 static struct bootinfo * 856 findbootdev() 857 { 858 register struct bootinfo *bi; 859 register char *bp; 860 register int unit, controller; 861 register struct ifnet *ifp; 862 863 bi = &bootinfo; 864 bp = bi->name; 865 printf("findbootdev: (v%d rom) trying \"%s(%x,%x,%x)\"... ", 866 promvec->pv_romvec_vers, bp, bi->val[0], bi->val[1], bi->val[2]); 867 868 /* Try network devices first */ 869 unit = bi->val[0]; 870 for (ifp = ifnet; ifp; ifp = ifp->if_next) 871 if (unit == ifp->if_unit && strcmp(bp, ifp->if_name) == 0) { 872 printf("found \"%s%d\"\n", ifp->if_name, ifp->if_unit); 873 bi->type = FS_NFS; 874 bi->data = (caddr_t)ifp; 875 return (bi); 876 } 877 printf("not found\n"); 878 return (NULL); 879 } 880 881 gets(cp) 882 register char *cp; 883 { 884 register char *lp; 885 register int c; 886 887 lp = cp; 888 for (;;) { 889 c = cngetc(); 890 switch (c) { 891 case '\n': 892 case '\r': 893 printf("\n"); 894 *lp++ = '\0'; 895 return; 896 case '\b': 897 case '\177': 898 case '#': 899 if (lp > cp) { 900 lp--; 901 printf(" \b "); 902 } 903 continue; 904 case '@': 905 case 'u'&037: 906 lp = cp; 907 cnputc('\n'); 908 continue; 909 default: 910 if (c < ' ') 911 continue; 912 cnputc(c); 913 *lp++ = c; 914 } 915 } 916 } 917