swapgeneric.c revision 4851:5e98cf4c2164
122347Spst/* 222347Spst * CDDL HEADER START 329964Sache * 429964Sache * The contents of this file are subject to the terms of the 522347Spst * Common Development and Distribution License (the "License"). 622347Spst * You may not use this file except in compliance with the License. 722347Spst * 822347Spst * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 922347Spst * or http://www.opensolaris.org/os/licensing. 1022347Spst * See the License for the specific language governing permissions 1129964Sache * and limitations under the License. 1229964Sache * 1329964Sache * When distributing Covered Code, include this CDDL HEADER in each 1422347Spst * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1522347Spst * If applicable, add the following below this CDDL HEADER, with the 1622347Spst * fields enclosed by brackets "[]" replaced with your own identifying 1722347Spst * information: Portions Copyright [yyyy] [name of copyright owner] 1822347Spst * 1922347Spst * CDDL HEADER END 2022347Spst */ 2122347Spst/* ONC_PLUS EXTRACT START */ 2222347Spst/* 2322347Spst * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2422347Spst * Use is subject to license terms. 2522347Spst */ 2629964Sache 2722347Spst#pragma ident "%Z%%M% %I% %E% SMI" 2822347Spst/* ONC_PLUS EXTRACT END */ 2922347Spst 3022347Spst/* 3122347Spst * Configure root, swap and dump devices. 3222347Spst */ 3322347Spst 3422347Spst#include <sys/types.h> 3522347Spst#include <sys/param.h> 3622347Spst#include <sys/sysmacros.h> 3722347Spst#include <sys/signal.h> 3829964Sache#include <sys/cred.h> 3922347Spst#include <sys/proc.h> 4022347Spst#include <sys/user.h> 4122347Spst#include <sys/conf.h> 4222347Spst#include <sys/buf.h> 4322347Spst#include <sys/systm.h> 4422347Spst#include <sys/vm.h> 4522347Spst#include <sys/reboot.h> 4622347Spst#include <sys/file.h> 4722347Spst#include <sys/vfs.h> 4822347Spst#include <sys/vnode.h> 4922347Spst#include <sys/errno.h> 5022347Spst#include <sys/kmem.h> 5122347Spst#include <sys/uio.h> 5222347Spst#include <sys/open.h> 5322347Spst#include <sys/mount.h> 5422347Spst#include <sys/kobj.h> 5522347Spst#include <sys/bootconf.h> 5622347Spst#include <sys/sysconf.h> 5722347Spst#include <sys/modctl.h> 5822347Spst#include <sys/autoconf.h> 5922347Spst#include <sys/debug.h> 6022347Spst#include <sys/fs/snode.h> 6122347Spst#include <fs/fs_subr.h> 6222347Spst#include <sys/socket.h> 6322347Spst#include <net/if.h> 6422347Spst 6522347Spst#include <sys/mkdev.h> 6622347Spst#include <sys/cmn_err.h> 6722347Spst#include <sys/console.h> 6822347Spst 6922347Spst#include <sys/conf.h> 7022347Spst#include <sys/ddi.h> 7122347Spst#include <sys/sunddi.h> 7222347Spst#include <sys/hwconf.h> 7322347Spst#include <sys/dc_ki.h> 7422347Spst#include <sys/promif.h> 7522347Spst 7622347Spst 7722347Spst/* 7822347Spst * Local routines 7922347Spst */ 8022347Spststatic int preload_module(struct sysparam *, void *); 8122347Spststatic struct vfssw *getfstype(char *, char *, size_t); 8222347Spststatic int getphysdev(char *, char *, size_t); 8322347Spststatic int load_bootpath_drivers(char *bootpath); 8422347Spststatic int load_boot_driver(char *drv); 8522347Spststatic int load_boot_platform_modules(char *drv); 8622347Spststatic dev_info_t *path_to_devinfo(char *path); 8722347Spststatic boolean_t netboot_over_ib(char *bootpath); 8822347Spst 8922347Spst 9022347Spst/* 9122347Spst * Module linkage information for the kernel. 9222347Spst */ 9322347Spststatic struct modlmisc modlmisc = { 9422347Spst &mod_miscops, "root and swap configuration %I%" 9522347Spst}; 9622347Spst 9722347Spststatic struct modlinkage modlinkage = { 9822347Spst MODREV_1, (void *)&modlmisc, NULL 9922347Spst}; 10022347Spst 10122347Spstint 10222347Spst_init(void) 10322347Spst{ 10422347Spst return (mod_install(&modlinkage)); 10522347Spst} 10622347Spst 10722347Spstint 10822347Spst_fini(void) 10922347Spst{ 11022347Spst return (mod_remove(&modlinkage)); 11122347Spst} 11222347Spst 11322347Spstint 11422347Spst_info(struct modinfo *modinfop) 11522347Spst{ 11622347Spst return (mod_info(&modlinkage, modinfop)); 11722347Spst} 11822347Spst 11922347Spst/* 12022347Spst * Configure root file system. 12122347Spst */ 12222347Spstint 12322347Spstrootconf(void) 12422347Spst{ 12529964Sache int error; 12622347Spst struct vfssw *vsw; 12722347Spst extern void pm_init(void); 12822347Spst 12929964Sache BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); 13022347Spst BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); 13122347Spst BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); 13222347Spst BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); 13322347Spst 13422347Spst /* 13522347Spst * Install cluster modules that were only loaded during 13622347Spst * loadrootmodules(). 13729964Sache */ 13822347Spst if (error = clboot_rootconf()) 13922347Spst return (error); 14022347Spst 14122347Spst if (root_is_svm) { 14222347Spst (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); 14322347Spst 14422347Spst BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); 14522347Spst BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); 14622347Spst } 14722347Spst 14822347Spst /* 14922347Spst * Run _init on the root filesystem (we already loaded it 15022347Spst * but we've been waiting until now to _init it) which will 15122347Spst * have the side-effect of running vsw_init() on this vfs. 15222347Spst * Because all the nfs filesystems are lumped into one 15322347Spst * module we need to special case it. 15422347Spst */ 15522347Spst if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 15622347Spst if (modload("fs", "nfs") == -1) { 15722347Spst cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 15822347Spst rootfs.bo_fstype); 15922347Spst return (ENXIO); 16022347Spst } 16122347Spst } else { 16222347Spst if (modload("fs", rootfs.bo_fstype) == -1) { 16322347Spst cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 16422347Spst rootfs.bo_fstype); 16522347Spst return (ENXIO); 16622347Spst } 16722347Spst } 16822347Spst RLOCK_VFSSW(); 16922347Spst vsw = vfs_getvfsswbyname(rootfs.bo_fstype); 17022347Spst RUNLOCK_VFSSW(); 17122347Spst VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); 17222347Spst VFS_HOLD(rootvfs); 17322347Spst 17422347Spst if (root_is_svm) { 17522347Spst rootvfs->vfs_flag |= VFS_RDONLY; 17622347Spst } 17722347Spst 17822347Spst /* 17929964Sache * This pm-releated call has to occur before root is mounted since we 18022347Spst * need to power up all devices. It is placed after VFS_INIT() such 18122347Spst * that opening a device via ddi_lyr_ interface just before root has 18222347Spst * been mounted would work. 18322347Spst */ 18422347Spst pm_init(); 18522347Spst 18622347Spst if (netboot) { 18722347Spst if ((error = strplumb()) != 0) { 18822347Spst cmn_err(CE_CONT, "Cannot plumb network device\n"); 18922347Spst return (error); 19022347Spst } 19122347Spst } 19222347Spst 19322347Spst /* 19422347Spst * ufs_mountroot() ends up calling getrootdev() 19522347Spst * (below) which actually triggers the _init, identify, 19622347Spst * probe and attach of the drivers that make up root device 19722347Spst * bush; these are also quietly waiting in memory. 19822347Spst */ 19922347Spst BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); 20022347Spst 20122347Spst error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); 20222347Spst vfs_unrefvfssw(vsw); 20322347Spst rootdev = rootvfs->vfs_dev; 20422347Spst 20522347Spst if (error) 20622347Spst cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", 20722347Spst rootfs.bo_name, rootfs.bo_fstype); 20822347Spst else 20922347Spst cmn_err(CE_CONT, "?root on %s fstype %s\n", 21022347Spst rootfs.bo_name, rootfs.bo_fstype); 21122347Spst return (error); 21222347Spst} 21322347Spst 21422347Spst/* 21522347Spst * Remount root on an SVM mirror root device 216 * Only supported on UFS filesystems at present 217 */ 218int 219svm_rootconf(void) 220{ 221 int error; 222 extern int ufs_remountroot(struct vfs *vfsp); 223 224 ASSERT(root_is_svm == 1); 225 226 if (strcmp(rootfs.bo_fstype, "ufs") != 0) { 227 cmn_err(CE_CONT, "Mounting root on %s with filesystem " 228 "type %s is not supported\n", 229 rootfs.bo_name, rootfs.bo_fstype); 230 return (EINVAL); 231 } 232 233 (void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME); 234 235 BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name)); 236 237 error = ufs_remountroot(rootvfs); 238 239 if (error) { 240 cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n", 241 rootfs.bo_name, rootfs.bo_fstype); 242 } else { 243 cmn_err(CE_CONT, "?root remounted on %s fstype %s\n", 244 rootfs.bo_name, rootfs.bo_fstype); 245 } 246 return (error); 247} 248 249/* 250 * Under the assumption that our root file system is on a 251 * disk partition, get the dev_t of the partition in question. 252 * 253 * By now, boot has faithfully loaded all our modules into memory, and 254 * we've taken over resource management. Before we go any further, we 255 * have to fire up the device drivers and stuff we need to mount the 256 * root filesystem. That's what we do here. Fingers crossed. 257 */ 258dev_t 259getrootdev(void) 260{ 261 dev_t d; 262 263 if ((d = ddi_pathname_to_dev_t(rootfs.bo_name)) == NODEV) 264 cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n", 265 rootfs.bo_name); 266 return (d); 267} 268 269/* 270 * If booted with ASKNAME, prompt on the console for a filesystem 271 * name and return it. 272 */ 273void 274getfsname(char *askfor, char *name, size_t namelen) 275{ 276 if (boothowto & RB_ASKNAME) { 277 printf("%s name: ", askfor); 278 console_gets(name, namelen); 279 } 280} 281 282/*ARGSUSED1*/ 283static int 284preload_module(struct sysparam *sysp, void *p) 285{ 286 static char *wmesg = "forceload of %s failed"; 287 char *name; 288 289 name = sysp->sys_ptr; 290 BMDPRINTF(("preload_module: %s\n", name)); 291 if (modloadonly(NULL, name) < 0) 292 cmn_err(CE_WARN, wmesg, name); 293 return (0); 294} 295 296/* ONC_PLUS EXTRACT START */ 297/* 298 * We want to load all the modules needed to mount the root filesystem, 299 * so that when we start the ball rolling in 'getrootdev', every module 300 * should already be in memory, just waiting to be init-ed. 301 */ 302 303int 304loadrootmodules(void) 305{ 306 struct vfssw *vsw; 307 char *this; 308 char *name; 309 int err; 310/* ONC_PLUS EXTRACT END */ 311 int i, proplen, dhcacklen; 312 extern char *impl_module_list[]; 313 extern char *platform_module_list[]; 314 315 /* Make sure that the PROM's devinfo tree has been created */ 316 ASSERT(ddi_root_node()); 317 318 BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype)); 319 BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name)); 320 BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags)); 321 322 /* 323 * zzz We need to honor what's in rootfs if it's not null. 324 * non-null means use what's there. This way we can 325 * change rootfs with /etc/system AND with tunetool. 326 */ 327 if (root_is_svm) { 328 /* user replaced rootdev, record obp_bootpath */ 329 obp_bootpath[0] = '\0'; 330 (void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME); 331 BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 332 } else { 333 /* 334 * Get the root fstype and root device path from boot. 335 */ 336 rootfs.bo_fstype[0] = '\0'; 337 rootfs.bo_name[0] = '\0'; 338 } 339 340 /* 341 * This lookup will result in modloadonly-ing the root 342 * filesystem module - it gets _init-ed in rootconf() 343 */ 344 if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL) 345 return (ENXIO); /* in case we have no file system types */ 346 347 (void) strcpy(rootfs.bo_fstype, vsw->vsw_name); 348 349 vfs_unrefvfssw(vsw); 350 351 /* 352 * Load the favored drivers of the implementation. 353 * e.g. 'sbus' and possibly 'zs' (even). 354 * 355 * Called whilst boot is still loaded (because boot does 356 * the i/o for us), and DDI services are unavailable. 357 */ 358 BMDPRINTF(("loadrootmodules: impl_module_list\n")); 359 for (i = 0; (this = impl_module_list[i]) != NULL; i++) { 360 if ((err = load_boot_driver(this)) != 0) { 361 cmn_err(CE_WARN, "Cannot load drv/%s", this); 362 return (err); 363 /* NOTREACHED */ 364 } 365 } 366 /* 367 * Now load the platform modules (if any) 368 */ 369 BMDPRINTF(("loadrootmodules: platform_module_list\n")); 370 for (i = 0; (this = platform_module_list[i]) != NULL; i++) { 371 if ((err = load_boot_platform_modules(this)) != 0) { 372 cmn_err(CE_WARN, "Cannot load drv/%s", this); 373 return (err); 374 /* NOTREACHED */ 375 } 376 } 377 378loop: 379 (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME); 380 381 /* 382 * Given a physical pathname, load the correct set of driver 383 * modules into memory, including all possible parents. 384 * 385 * NB: The code sets the variable 'name' for error reporting. 386 */ 387 err = 0; 388 BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 389 if (root_is_svm == 0) { 390 BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 391 name = rootfs.bo_name; 392 err = load_bootpath_drivers(rootfs.bo_name); 393 } 394 395 /* 396 * Load driver modules in obp_bootpath, this is always 397 * required for mountroot to succeed. obp_bootpath is 398 * is set if rootdev is set via /etc/system, which is 399 * the case if booting of a SVM/VxVM mirror. 400 */ 401 if ((err == 0) && obp_bootpath[0] != '\0') { 402 BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 403 name = obp_bootpath; 404 err = load_bootpath_drivers(obp_bootpath); 405 } 406 407 if (err != 0) { 408 cmn_err(CE_CONT, "Cannot load drivers for %s\n", name); 409 goto out; 410 /* NOTREACHED */ 411 } 412 413 /* 414 * Check to see if the booter performed DHCP configuration 415 * ("bootp-response" boot property exists). If so, then before 416 * bootops disappears we need to save the value of this property 417 * such that the userland dhcpagent can adopt the DHCP management 418 * of our primary network interface. We leave room at the beginning of 419 * saved property to cache the interface name we used to boot the 420 * client. This context is necessary for the user land dhcpagent 421 * to do its job properly on a multi-homed system. 422 */ 423 proplen = BOP_GETPROPLEN(bootops, "bootp-response"); 424 if (proplen > 0) { 425 dhcacklen = proplen + IFNAMSIZ; 426 dhcack = kmem_zalloc(dhcacklen, KM_SLEEP); 427 if (BOP_GETPROP(bootops, "bootp-response", 428 (uchar_t *)&dhcack[IFNAMSIZ]) == -1) { 429 cmn_err(CE_WARN, "BOP_GETPROP of " 430 "\"bootp-response\" failed\n"); 431 kmem_free(dhcack, dhcacklen); 432 dhcack = NULL; 433 goto out; 434 } 435 436 /* 437 * Fetch the "netdev-path" boot property (if it exists), and 438 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...). 439 */ 440 proplen = BOP_GETPROPLEN(bootops, "netdev-path"); 441 if (proplen > 0) { 442 netdev_path = kmem_zalloc(proplen, KM_SLEEP); 443 if (BOP_GETPROP(bootops, "netdev-path", 444 (uchar_t *)netdev_path) == -1) { 445 cmn_err(CE_WARN, "BOP_GETPROP of " 446 "\"netdev-path\" failed\n"); 447 kmem_free(netdev_path, proplen); 448 goto out; 449 } 450 } 451 } 452 453 /* 454 * Preload (load-only, no init) all modules which 455 * were added to the /etc/system file with the 456 * FORCELOAD keyword. 457 */ 458 BMDPRINTF(("loadrootmodules: preload_module\n")); 459 (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL); 460 461/* ONC_PLUS EXTRACT START */ 462 /* 463 * If we booted otw then load in the plumbing 464 * routine now while we still can. If we didn't 465 * boot otw then we will load strplumb in main(). 466 * 467 * NFS is actually a set of modules, the core routines, 468 * a diskless helper module, rpcmod, and the tli interface. Load 469 * them now while we still can. 470 * 471 * Because we glomb all versions of nfs into a single module 472 * we check based on the initial string "nfs". 473 * 474 * XXX: A better test for this is to see if device_type 475 * XXX: from the PROM is "network". 476 */ 477 478 if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 479 ++netboot; 480 481 if ((err = modload("misc", "tlimod")) < 0) { 482 cmn_err(CE_CONT, "Cannot load misc/tlimod\n"); 483 goto out; 484 /* NOTREACHED */ 485 } 486 if ((err = modload("strmod", "rpcmod")) < 0) { 487 cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n"); 488 goto out; 489 /* NOTREACHED */ 490 } 491 if ((err = modload("misc", "nfs_dlboot")) < 0) { 492 cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n"); 493 goto out; 494 /* NOTREACHED */ 495 } 496 if ((err = modload("mac", "mac_ether")) < 0) { 497 cmn_err(CE_CONT, "Cannot load mac/mac_ether\n"); 498 goto out; 499 /* NOTREACHED */ 500 } 501 if ((err = modload("misc", "strplumb")) < 0) { 502 cmn_err(CE_CONT, "Cannot load misc/strplumb\n"); 503 goto out; 504 /* NOTREACHED */ 505 } 506 if ((err = strplumb_load()) < 0) { 507 goto out; 508 /* NOTREACHED */ 509 } 510 } 511 512 /* 513 * Preload modules needed for booting as a cluster. 514 */ 515 err = clboot_loadrootmodules(); 516 517out: 518 if (err != 0 && (boothowto & RB_ASKNAME)) 519 goto loop; 520 521 return (err); 522} 523/* ONC_PLUS EXTRACT END */ 524 525/* 526 * Get the name of the root or swap filesystem type, and return 527 * the corresponding entry in the vfs switch. 528 * 529 * If we're not asking the user, and we're trying to find the 530 * root filesystem type, we ask boot for the filesystem 531 * type that it came from and use that. Similarly, if we're 532 * trying to find the swap filesystem, we try and derive it from 533 * the root filesystem type. 534 * 535 * If we are booting via NFS we currently have these options: 536 * nfs - dynamically choose NFS V2. V3, or V4 (default) 537 * nfs2 - force NFS V2 538 * nfs3 - force NFS V3 539 * nfs4 - force NFS V4 540 * Because we need to maintain backward compatibility with the naming 541 * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c) 542 * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic 543 * nfs module will map the type back to either "nfs", "nfs3", or "nfs4". 544 * This is only for root filesystems, all other uses such as cachefs 545 * will expect that "nfs" == NFS V2. 546 * 547 * If the filesystem isn't already loaded, vfs_getvfssw() will load 548 * it for us, but if (at the time we call it) modrootloaded is 549 * still not set, it won't run the filesystems _init routine (and 550 * implicitly it won't run the filesystems vsw_init() entry either). 551 * We do that explicitly in rootconf(). 552 */ 553static struct vfssw * 554getfstype(char *askfor, char *fsname, size_t fsnamelen) 555{ 556 struct vfssw *vsw; 557 static char defaultfs[BO_MAXFSNAME]; 558 int root = 0; 559 560 if (strcmp(askfor, "root") == 0) { 561 (void) BOP_GETPROP(bootops, "fstype", defaultfs); 562 root++; 563 } else { 564 (void) strcpy(defaultfs, "swapfs"); 565 } 566 567 if (boothowto & RB_ASKNAME) { 568 for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') { 569 printf("%s filesystem type [%s]: ", askfor, defaultfs); 570 console_gets(fsname, fsnamelen); 571 if (*fsname == '\0') 572 (void) strcpy(fsname, defaultfs); 573 if (root) { 574 if (strcmp(fsname, "nfs2") == 0) 575 (void) strcpy(fsname, "nfs"); 576 else if (strcmp(fsname, "nfs") == 0) 577 (void) strcpy(fsname, "nfsdyn"); 578 } 579 if ((vsw = vfs_getvfssw(fsname)) != NULL) 580 return (vsw); 581 printf("Unknown filesystem type '%s'\n", fsname); 582 } 583 } else if (*fsname == '\0') { 584 fsname = defaultfs; 585 } 586 if (*fsname == '\0') { 587 return (NULL); 588 } 589 590 if (root) { 591 if (strcmp(fsname, "nfs2") == 0) 592 (void) strcpy(fsname, "nfs"); 593 else if (strcmp(fsname, "nfs") == 0) 594 (void) strcpy(fsname, "nfsdyn"); 595 } 596 597 return (vfs_getvfssw(fsname)); 598} 599 600 601/* 602 * Get a physical device name, and maybe load and attach 603 * the driver. 604 * 605 * XXX Need better checking of whether or not a device 606 * actually exists if the user typed in a pathname. 607 * 608 * XXX Are we sure we want to expose users to this sort 609 * of physical namespace gobbledygook (now there's 610 * a word to conjure with..) 611 * 612 * XXX Note that on an OBP machine, we can easily ask the 613 * prom and pretty-print some plausible set of bootable 614 * devices. We can also user the prom to verify any 615 * such device. Later tim.. later. 616 */ 617static int 618getphysdev(char *askfor, char *name, size_t namelen) 619{ 620 static char fmt[] = "Enter physical name of %s device\n[%s]: "; 621 dev_t dev; 622 static char defaultpath[BO_MAXOBJNAME]; 623 624 /* 625 * Establish 'default' values - we get the root device from 626 * boot, and we infer the swap device is the same but with 627 * a 'b' on the end instead of an 'a'. A first stab at 628 * ease-of-use .. 629 */ 630 if (strcmp(askfor, "root") == 0) { 631 /* 632 * Look for the 1275 compliant name 'bootpath' first, 633 * but make certain it has a non-NULL value as well. 634 */ 635 if ((BOP_GETPROP(bootops, "bootpath", defaultpath) == -1) || 636 strlen(defaultpath) == 0) { 637 if (BOP_GETPROP(bootops, 638 "boot-path", defaultpath) == -1) 639 boothowto |= RB_ASKNAME | RB_VERBOSE; 640 } 641 } else { 642 (void) strcpy(defaultpath, rootfs.bo_name); 643 defaultpath[strlen(defaultpath) - 1] = 'b'; 644 } 645 646retry: 647 if (boothowto & RB_ASKNAME) { 648 printf(fmt, askfor, defaultpath); 649 console_gets(name, namelen); 650 } 651 if (*name == '\0') 652 (void) strcpy(name, defaultpath); 653 654 if (strcmp(askfor, "swap") == 0) { 655 656 /* 657 * Try to load and install the swap device driver. 658 */ 659 dev = ddi_pathname_to_dev_t(name); 660 661 if (dev == (dev_t)-1) { 662 printf("Not a supported device for swap.\n"); 663 boothowto |= RB_ASKNAME | RB_VERBOSE; 664 goto retry; 665 } 666 667 /* 668 * Ensure that we're not trying to swap on the floppy. 669 */ 670 if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) { 671 printf("Too dangerous to swap on the floppy\n"); 672 if (boothowto & RB_ASKNAME) 673 goto retry; 674 return (-1); 675 } 676 } 677 678 return (0); 679} 680 681 682/* 683 * Load a driver needed to boot. 684 */ 685static int 686load_boot_driver(char *drv) 687{ 688 char *drvname; 689 major_t major; 690#ifdef sparc 691 struct devnames *dnp; 692 ddi_prop_t *propp; 693 char *module; 694 char *dir, *mf; 695 int plen; 696 int mlen; 697#endif /* sparc */ 698 699 if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 700 cmn_err(CE_CONT, "%s: no major number\n", drv); 701 return (-1); 702 } 703 /* 704 * resolve aliases 705 */ 706 drvname = ddi_major_to_name(major); 707 708#ifdef DEBUG 709 if (strcmp(drv, drvname) == 0) { 710 BMDPRINTF(("load_boot_driver: %s\n", drv)); 711 } else { 712 BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname)); 713 } 714#endif /* DEBUG */ 715 716 if (modloadonly("drv", drvname) == -1) { 717 cmn_err(CE_CONT, "%s: cannot load driver\n", drvname); 718 return (-1); 719 } 720 721#ifdef sparc 722 /* 723 * NOTE: this can be removed when newboot-sparc is delivered. 724 * 725 * Check to see if the driver had a 'ddi-forceload' global driver.conf 726 * property to identify additional modules that need to be loaded. 727 * The driver still needs to use ddi_modopen() to open these modules, 728 * but the 'ddi-forceload' property allows the modules to be loaded 729 * into memory prior to lights-out, so that driver ddi_modopen() 730 * calls during lights-out (when mounting root) will work correctly. 731 * Use of 'ddi-forceload' is only required for drivers involved in 732 * getting root mounted. 733 */ 734 dnp = &devnamesp[major]; 735 if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list && 736 ((propp = i_ddi_prop_search(DDI_DEV_T_ANY, 737 "ddi-forceload", DDI_PROP_TYPE_STRING, 738 &dnp->dn_global_prop_ptr->prop_list)) != NULL)) { 739 740 module = (char *)propp->prop_val; 741 plen = propp->prop_len; 742 while (plen > 0) { 743 mlen = strlen(module); 744 mf = strrchr(module, '/'); 745 if (mf) { 746 dir = module; 747 *mf++ = '\0'; /* '/' -> '\0' */ 748 } else { 749 dir = "misc"; 750 mf = module; 751 } 752 if (modloadonly(dir, mf) == -1) 753 cmn_err(CE_CONT, 754 "misc/%s: can't load module\n", mf); 755 if (mf != module) 756 *(mf - 1) = '/'; /* '\0' -> '/' */ 757 758 module += mlen + 1; 759 plen -= mlen + 1; 760 } 761 } 762#endif /* sparc */ 763 764 return (0); 765} 766 767 768/* 769 * For a given instance, load that driver and its parents 770 */ 771static int 772load_parent_drivers(dev_info_t *dip, char *path) 773{ 774 int rval = 0; 775 major_t major = (major_t)-1; 776 char *drv; 777 char *p; 778 779 while (dip) { 780 /* check for path-oriented alias */ 781 if (path) 782 major = ddi_name_to_major(path); 783 else 784 major = (major_t)-1; 785 786 if (major != (major_t)-1) 787 drv = ddi_major_to_name(major); 788 else 789 drv = ddi_binding_name(dip); 790 791 if (load_boot_driver(drv) != 0) 792 rval = -1; 793 794 dip = ddi_get_parent(dip); 795 if (path) { 796 p = strrchr(path, '/'); 797 if (p) 798 *p = 0; 799 } 800 } 801 802 return (rval); 803} 804 805 806/* 807 * For a given path to a boot device, 808 * load that driver and all its parents. 809 */ 810static int 811load_bootpath_drivers(char *bootpath) 812{ 813 dev_info_t *dip; 814 char *pathcopy; 815 int pathcopy_len; 816 int rval; 817 char *p; 818 819 if (bootpath == NULL || *bootpath == 0) 820 return (-1); 821 822 BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath)); 823 824 pathcopy = i_ddi_strdup(bootpath, KM_SLEEP); 825 pathcopy_len = strlen(pathcopy) + 1; 826 827 dip = path_to_devinfo(pathcopy); 828 829#if defined(__i386) || defined(__amd64) 830 /* 831 * i386 does not provide stub nodes for all boot devices, 832 * but we should be able to find the node for the parent, 833 * and the leaf of the boot path should be the driver name, 834 * which we go ahead and load here. 835 */ 836 if (dip == NULL) { 837 char *leaf; 838 839 /* 840 * Find last slash to build the full path to the 841 * parent of the leaf boot device 842 */ 843 p = strrchr(pathcopy, '/'); 844 *p++ = 0; 845 846 /* 847 * Now isolate the driver name of the leaf device 848 */ 849 leaf = p; 850 p = strchr(leaf, '@'); 851 *p = 0; 852 853 BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n", 854 bootpath, leaf)); 855 856 dip = path_to_devinfo(pathcopy); 857 if (leaf) { 858 rval = load_boot_driver(leaf, NULL); 859 if (rval == -1) { 860 kmem_free(pathcopy, pathcopy_len); 861 return (NULL); 862 } 863 } 864 } 865#endif 866 867 if (dip == NULL) { 868 cmn_err(CE_WARN, "can't bind driver for boot path <%s>", 869 bootpath); 870 kmem_free(pathcopy, pathcopy_len); 871 return (NULL); 872 } 873 874 /* 875 * Load IP over IB driver when netbooting over IB. 876 * As per IB 1275 binding, IP over IB is represented as 877 * service on the top of the HCA node. So, there is no 878 * PROM node and generic framework cannot pre-load 879 * IP over IB driver based on the bootpath. The following 880 * code preloads IP over IB driver when doing netboot over 881 * InfiniBand. 882 */ 883 if (netboot_over_ib(bootpath) && 884 modloadonly("drv", "ibd") == -1) { 885 cmn_err(CE_CONT, "ibd: cannot load platform driver\n"); 886 kmem_free(pathcopy, pathcopy_len); 887 return (NULL); 888 } 889 890 /* get rid of minor node at end of copy (if not already done above) */ 891 p = strrchr(pathcopy, '/'); 892 if (p) { 893 p = strchr(p, ':'); 894 if (p) 895 *p = 0; 896 } 897 898 rval = load_parent_drivers(dip, pathcopy); 899 kmem_free(pathcopy, pathcopy_len); 900 return (rval); 901} 902 903 904 905 906/* 907 * Load drivers required for a platform 908 * Since all hardware nodes should be available in the device 909 * tree, walk the per-driver list and load the parents of 910 * each node found. If not a hardware node, try to load it. 911 * Pseudo nexus is already loaded. 912 */ 913static int 914load_boot_platform_modules(char *drv) 915{ 916 major_t major; 917 dev_info_t *dip; 918 char *drvname; 919 int rval = 0; 920 921 if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 922 cmn_err(CE_CONT, "%s: no major number\n", drv); 923 return (-1); 924 } 925 926 /* 927 * resolve aliases 928 */ 929 drvname = ddi_major_to_name(major); 930 if ((major = ddi_name_to_major(drvname)) == (major_t)-1) 931 return (-1); 932 933#ifdef DEBUG 934 if (strcmp(drv, drvname) == 0) { 935 BMDPRINTF(("load_boot_platform_modules: %s\n", drv)); 936 } else { 937 BMDPRINTF(("load_boot_platform_modules: %s -> %s\n", 938 drv, drvname)); 939 } 940#endif /* DEBUG */ 941 942 dip = devnamesp[major].dn_head; 943 if (dip == NULL) { 944 /* pseudo node, not-enumerated, needs to be loaded */ 945 if (modloadonly("drv", drvname) == -1) { 946 cmn_err(CE_CONT, "%s: cannot load platform driver\n", 947 drvname); 948 rval = -1; 949 } 950 } else { 951 while (dip) { 952 if (load_parent_drivers(dip, NULL) != 0) 953 rval = -1; 954 dip = ddi_get_next(dip); 955 } 956 } 957 958 return (rval); 959} 960 961 962/* 963 * i_find_node: Internal routine used by path_to_devinfo 964 * to locate a given nodeid in the device tree. 965 */ 966struct i_path_findnode { 967 pnode_t nodeid; 968 dev_info_t *dip; 969}; 970 971static int 972i_path_find_node(dev_info_t *dev, void *arg) 973{ 974 struct i_path_findnode *f = (struct i_path_findnode *)arg; 975 976 977 if (ddi_get_nodeid(dev) == (int)f->nodeid) { 978 f->dip = dev; 979 return (DDI_WALK_TERMINATE); 980 } 981 return (DDI_WALK_CONTINUE); 982} 983 984/* 985 * Return the devinfo node to a boot device 986 */ 987static dev_info_t * 988path_to_devinfo(char *path) 989{ 990 struct i_path_findnode fn; 991 extern dev_info_t *top_devinfo; 992 993 /* 994 * Get the nodeid of the given pathname, if such a mapping exists. 995 */ 996 fn.dip = NULL; 997 fn.nodeid = prom_finddevice(path); 998 if (fn.nodeid != OBP_BADNODE) { 999 /* 1000 * Find the nodeid in our copy of the device tree and return 1001 * whatever name we used to bind this node to a driver. 1002 */ 1003 ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn)); 1004 } 1005 1006#ifdef DEBUG 1007 /* 1008 * If we're bound to something other than the nodename, 1009 * note that in the message buffer and system log. 1010 */ 1011 if (fn.dip) { 1012 char *p, *q; 1013 1014 p = ddi_binding_name(fn.dip); 1015 q = ddi_node_name(fn.dip); 1016 if (p && q && (strcmp(p, q) != 0)) { 1017 BMDPRINTF(("path_to_devinfo: %s bound to %s\n", 1018 path, p)); 1019 } 1020 } 1021#endif /* DEBUG */ 1022 1023 return (fn.dip); 1024} 1025 1026/* 1027 * This routine returns B_TRUE if the bootpath corresponds to 1028 * IP over IB driver. 1029 * 1030 * The format of the bootpath for the IP over IB looks like 1031 * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip 1032 * 1033 * The minor node portion "port=1,pkey=8001,protocol=ip" represents 1034 * IP over IB driver. 1035 */ 1036static boolean_t 1037netboot_over_ib(char *bootpath) 1038{ 1039 1040 char *temp; 1041 boolean_t ret = B_FALSE; 1042 pnode_t node = prom_finddevice(bootpath); 1043 int len; 1044 char devicetype[OBP_MAXDRVNAME]; 1045 1046 /* Is this IB node ? */ 1047 len = prom_getproplen(node, OBP_DEVICETYPE); 1048 if (len <= 1 || len >= OBP_MAXDRVNAME) 1049 return (B_FALSE); 1050 1051 (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype); 1052 1053 if (strncmp("ib", devicetype, 2) == 0) { 1054 /* Check for proper IP over IB string */ 1055 if ((temp = strstr(bootpath, ":port=")) != NULL) { 1056 if ((temp = strstr(temp, ",pkey=")) != NULL) 1057 if ((temp = strstr(temp, 1058 ",protocol=ip")) != NULL) { 1059 ret = B_TRUE; 1060 } 1061 } 1062 } 1063 return (ret); 1064} 1065