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