1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 23*7c478bd9Sstevel@tonic-gate /* 24*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * Configure root, swap and dump devices. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/vm.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/open.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/sysconf.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h> 62*7c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 64*7c478bd9Sstevel@tonic-gate #include <net/if.h> 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/console.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 74*7c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * Local routines 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate static int preload_module(struct sysparam *, void *); 82*7c478bd9Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t); 83*7c478bd9Sstevel@tonic-gate static int getphysdev(char *, char *, size_t); 84*7c478bd9Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath); 85*7c478bd9Sstevel@tonic-gate static int load_boot_driver(char *drv); 86*7c478bd9Sstevel@tonic-gate static int load_boot_platform_modules(char *drv); 87*7c478bd9Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path); 88*7c478bd9Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate /* 92*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 93*7c478bd9Sstevel@tonic-gate */ 94*7c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 95*7c478bd9Sstevel@tonic-gate &mod_miscops, "root and swap configuration %I%" 96*7c478bd9Sstevel@tonic-gate }; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 99*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 100*7c478bd9Sstevel@tonic-gate }; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate int 103*7c478bd9Sstevel@tonic-gate _init(void) 104*7c478bd9Sstevel@tonic-gate { 105*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate int 109*7c478bd9Sstevel@tonic-gate _fini(void) 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate int 115*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 116*7c478bd9Sstevel@tonic-gate { 117*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Configure root file system. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate int 124*7c478bd9Sstevel@tonic-gate rootconf(void) 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate int error; 127*7c478bd9Sstevel@tonic-gate struct vfssw *vsw; 128*7c478bd9Sstevel@tonic-gate extern void pm_init(void); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); 131*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); 132*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); 133*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * Install cluster modules that were only loaded during 137*7c478bd9Sstevel@tonic-gate * loadrootmodules(). 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate if (error = clboot_rootconf()) 140*7c478bd9Sstevel@tonic-gate return (error); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (root_is_svm) { 143*7c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); 146*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * Run _init on the root filesystem (we already loaded it 151*7c478bd9Sstevel@tonic-gate * but we've been waiting until now to _init it) which will 152*7c478bd9Sstevel@tonic-gate * have the side-effect of running vsw_init() on this vfs. 153*7c478bd9Sstevel@tonic-gate * Because all the nfs filesystems are lumped into one 154*7c478bd9Sstevel@tonic-gate * module we need to special case it. 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 157*7c478bd9Sstevel@tonic-gate if (modload("fs", "nfs") == -1) { 158*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 159*7c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 160*7c478bd9Sstevel@tonic-gate return (ENXIO); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate } else { 163*7c478bd9Sstevel@tonic-gate if (modload("fs", rootfs.bo_fstype) == -1) { 164*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 165*7c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 166*7c478bd9Sstevel@tonic-gate return (ENXIO); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate RLOCK_VFSSW(); 170*7c478bd9Sstevel@tonic-gate vsw = vfs_getvfsswbyname(rootfs.bo_fstype); 171*7c478bd9Sstevel@tonic-gate RUNLOCK_VFSSW(); 172*7c478bd9Sstevel@tonic-gate VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); 173*7c478bd9Sstevel@tonic-gate VFS_HOLD(rootvfs); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate if (root_is_svm) { 176*7c478bd9Sstevel@tonic-gate rootvfs->vfs_flag |= VFS_RDONLY; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * This pm-releated call has to occur before root is mounted since we 181*7c478bd9Sstevel@tonic-gate * need to power up all devices. It is placed after VFS_INIT() such 182*7c478bd9Sstevel@tonic-gate * that opening a device via ddi_lyr_ interface just before root has 183*7c478bd9Sstevel@tonic-gate * been mounted would work. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate pm_init(); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate if (netboot) { 188*7c478bd9Sstevel@tonic-gate if ((error = strplumb()) != 0) { 189*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot plumb network device\n"); 190*7c478bd9Sstevel@tonic-gate return (error); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * ufs_mountroot() ends up calling getrootdev() 196*7c478bd9Sstevel@tonic-gate * (below) which actually triggers the _init, identify, 197*7c478bd9Sstevel@tonic-gate * probe and attach of the drivers that make up root device 198*7c478bd9Sstevel@tonic-gate * bush; these are also quietly waiting in memory. 199*7c478bd9Sstevel@tonic-gate */ 200*7c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); 203*7c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 204*7c478bd9Sstevel@tonic-gate rootdev = rootvfs->vfs_dev; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (error) 207*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", 208*7c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root on %s fstype %s\n", 211*7c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 212*7c478bd9Sstevel@tonic-gate return (error); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Remount root on an SVM mirror root device 217*7c478bd9Sstevel@tonic-gate * Only supported on UFS filesystems at present 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate int 220*7c478bd9Sstevel@tonic-gate svm_rootconf(void) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate int error; 223*7c478bd9Sstevel@tonic-gate extern int ufs_remountroot(struct vfs *vfsp); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate ASSERT(root_is_svm == 1); 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if (strcmp(rootfs.bo_fstype, "ufs") != 0) { 228*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Mounting root on %s with filesystem " 229*7c478bd9Sstevel@tonic-gate "type %s is not supported\n", 230*7c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 231*7c478bd9Sstevel@tonic-gate return (EINVAL); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name)); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate error = ufs_remountroot(rootvfs); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate if (error) { 241*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n", 242*7c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 243*7c478bd9Sstevel@tonic-gate } else { 244*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root remounted on %s fstype %s\n", 245*7c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate return (error); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * Under the assumption that our root file system is on a 252*7c478bd9Sstevel@tonic-gate * disk partition, get the dev_t of the partition in question. 253*7c478bd9Sstevel@tonic-gate * 254*7c478bd9Sstevel@tonic-gate * By now, boot has faithfully loaded all our modules into memory, and 255*7c478bd9Sstevel@tonic-gate * we've taken over resource management. Before we go any further, we 256*7c478bd9Sstevel@tonic-gate * have to fire up the device drivers and stuff we need to mount the 257*7c478bd9Sstevel@tonic-gate * root filesystem. That's what we do here. Fingers crossed. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate dev_t 260*7c478bd9Sstevel@tonic-gate getrootdev(void) 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate dev_t d; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if ((d = ddi_pathname_to_dev_t(rootfs.bo_name)) == NODEV) 265*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n", 266*7c478bd9Sstevel@tonic-gate rootfs.bo_name); 267*7c478bd9Sstevel@tonic-gate return (d); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* 271*7c478bd9Sstevel@tonic-gate * If booted with ASKNAME, prompt on the console for a filesystem 272*7c478bd9Sstevel@tonic-gate * name and return it. 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate void 275*7c478bd9Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen) 276*7c478bd9Sstevel@tonic-gate { 277*7c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 278*7c478bd9Sstevel@tonic-gate printf("%s name: ", askfor); 279*7c478bd9Sstevel@tonic-gate console_gets(name, namelen); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 284*7c478bd9Sstevel@tonic-gate static int 285*7c478bd9Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p) 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate static char *wmesg = "forceload of %s failed"; 288*7c478bd9Sstevel@tonic-gate char *name; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate name = sysp->sys_ptr; 291*7c478bd9Sstevel@tonic-gate BMDPRINTF(("preload_module: %s\n", name)); 292*7c478bd9Sstevel@tonic-gate if (modloadonly(NULL, name) < 0) 293*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, wmesg, name); 294*7c478bd9Sstevel@tonic-gate return (0); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * We want to load all the modules needed to mount the root filesystem, 300*7c478bd9Sstevel@tonic-gate * so that when we start the ball rolling in 'getrootdev', every module 301*7c478bd9Sstevel@tonic-gate * should already be in memory, just waiting to be init-ed. 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate int 305*7c478bd9Sstevel@tonic-gate loadrootmodules(void) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate struct vfssw *vsw; 308*7c478bd9Sstevel@tonic-gate char *this; 309*7c478bd9Sstevel@tonic-gate char *name; 310*7c478bd9Sstevel@tonic-gate int err; 311*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 312*7c478bd9Sstevel@tonic-gate int i, proplen, dhcacklen; 313*7c478bd9Sstevel@tonic-gate extern char *impl_module_list[]; 314*7c478bd9Sstevel@tonic-gate extern char *platform_module_list[]; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* Make sure that the PROM's devinfo tree has been created */ 317*7c478bd9Sstevel@tonic-gate ASSERT(ddi_root_node()); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype)); 320*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name)); 321*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags)); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * zzz We need to honor what's in rootfs if it's not null. 325*7c478bd9Sstevel@tonic-gate * non-null means use what's there. This way we can 326*7c478bd9Sstevel@tonic-gate * change rootfs with /etc/system AND with tunetool. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate if (root_is_svm) { 329*7c478bd9Sstevel@tonic-gate /* user replaced rootdev, record obp_bootpath */ 330*7c478bd9Sstevel@tonic-gate obp_bootpath[0] = '\0'; 331*7c478bd9Sstevel@tonic-gate (void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME); 332*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 333*7c478bd9Sstevel@tonic-gate } else { 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * Get the root fstype and root device path from boot. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate rootfs.bo_fstype[0] = '\0'; 338*7c478bd9Sstevel@tonic-gate rootfs.bo_name[0] = '\0'; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * This lookup will result in modloadonly-ing the root 343*7c478bd9Sstevel@tonic-gate * filesystem module - it gets _init-ed in rootconf() 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL) 346*7c478bd9Sstevel@tonic-gate return (ENXIO); /* in case we have no file system types */ 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate (void) strcpy(rootfs.bo_fstype, vsw->vsw_name); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Load the favored drivers of the implementation. 354*7c478bd9Sstevel@tonic-gate * e.g. 'sbus' and possibly 'zs' (even). 355*7c478bd9Sstevel@tonic-gate * 356*7c478bd9Sstevel@tonic-gate * Called whilst boot is still loaded (because boot does 357*7c478bd9Sstevel@tonic-gate * the i/o for us), and DDI services are unavailable. 358*7c478bd9Sstevel@tonic-gate */ 359*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: impl_module_list\n")); 360*7c478bd9Sstevel@tonic-gate for (i = 0; (this = impl_module_list[i]) != NULL; i++) { 361*7c478bd9Sstevel@tonic-gate if ((err = load_boot_driver(this)) != 0) { 362*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 363*7c478bd9Sstevel@tonic-gate return (err); 364*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * Now load the platform modules (if any) 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: platform_module_list\n")); 371*7c478bd9Sstevel@tonic-gate for (i = 0; (this = platform_module_list[i]) != NULL; i++) { 372*7c478bd9Sstevel@tonic-gate if ((err = load_boot_platform_modules(this)) != 0) { 373*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 374*7c478bd9Sstevel@tonic-gate return (err); 375*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate loop: 380*7c478bd9Sstevel@tonic-gate (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * Given a physical pathname, load the correct set of driver 384*7c478bd9Sstevel@tonic-gate * modules into memory, including all possible parents. 385*7c478bd9Sstevel@tonic-gate * 386*7c478bd9Sstevel@tonic-gate * NB: The code sets the variable 'name' for error reporting. 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate err = 0; 389*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 390*7c478bd9Sstevel@tonic-gate if (root_is_svm == 0) { 391*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 392*7c478bd9Sstevel@tonic-gate name = rootfs.bo_name; 393*7c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(rootfs.bo_name); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* 397*7c478bd9Sstevel@tonic-gate * Load driver modules in obp_bootpath, this is always 398*7c478bd9Sstevel@tonic-gate * required for mountroot to succeed. obp_bootpath is 399*7c478bd9Sstevel@tonic-gate * is set if rootdev is set via /etc/system, which is 400*7c478bd9Sstevel@tonic-gate * the case if booting of a SVM/VxVM mirror. 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate if ((err == 0) && obp_bootpath[0] != '\0') { 403*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 404*7c478bd9Sstevel@tonic-gate name = obp_bootpath; 405*7c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(obp_bootpath); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate if (err != 0) { 409*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load drivers for %s\n", name); 410*7c478bd9Sstevel@tonic-gate goto out; 411*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * Check to see if the booter performed DHCP configuration 416*7c478bd9Sstevel@tonic-gate * ("bootp-response" boot property exists). If so, then before 417*7c478bd9Sstevel@tonic-gate * bootops disappears we need to save the value of this property 418*7c478bd9Sstevel@tonic-gate * such that the userland dhcpagent can adopt the DHCP management 419*7c478bd9Sstevel@tonic-gate * of our primary network interface. We leave room at the beginning of 420*7c478bd9Sstevel@tonic-gate * saved property to cache the interface name we used to boot the 421*7c478bd9Sstevel@tonic-gate * client. This context is necessary for the user land dhcpagent 422*7c478bd9Sstevel@tonic-gate * to do its job properly on a multi-homed system. 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "bootp-response"); 425*7c478bd9Sstevel@tonic-gate if (proplen > 0) { 426*7c478bd9Sstevel@tonic-gate dhcacklen = proplen + IFNAMSIZ; 427*7c478bd9Sstevel@tonic-gate dhcack = kmem_zalloc(dhcacklen, KM_SLEEP); 428*7c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "bootp-response", 429*7c478bd9Sstevel@tonic-gate (uchar_t *)&dhcack[IFNAMSIZ]) == -1) { 430*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 431*7c478bd9Sstevel@tonic-gate "\"bootp-response\" failed\n"); 432*7c478bd9Sstevel@tonic-gate kmem_free(dhcack, dhcacklen); 433*7c478bd9Sstevel@tonic-gate dhcack = NULL; 434*7c478bd9Sstevel@tonic-gate goto out; 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * Fetch the "netdev-path" boot property (if it exists), and 439*7c478bd9Sstevel@tonic-gate * stash it for later use by sysinfo(SI_DHCP_CACHE, ...). 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "netdev-path"); 442*7c478bd9Sstevel@tonic-gate if (proplen > 0) { 443*7c478bd9Sstevel@tonic-gate netdev_path = kmem_zalloc(proplen, KM_SLEEP); 444*7c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "netdev-path", 445*7c478bd9Sstevel@tonic-gate (uchar_t *)netdev_path) == -1) { 446*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 447*7c478bd9Sstevel@tonic-gate "\"netdev-path\" failed\n"); 448*7c478bd9Sstevel@tonic-gate kmem_free(netdev_path, proplen); 449*7c478bd9Sstevel@tonic-gate goto out; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * Preload (load-only, no init) all modules which 456*7c478bd9Sstevel@tonic-gate * were added to the /etc/system file with the 457*7c478bd9Sstevel@tonic-gate * FORCELOAD keyword. 458*7c478bd9Sstevel@tonic-gate */ 459*7c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: preload_module\n")); 460*7c478bd9Sstevel@tonic-gate (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * If we booted otw then load in the plumbing 465*7c478bd9Sstevel@tonic-gate * routine now while we still can. If we didn't 466*7c478bd9Sstevel@tonic-gate * boot otw then we will load strplumb in main(). 467*7c478bd9Sstevel@tonic-gate * 468*7c478bd9Sstevel@tonic-gate * NFS is actually a set of modules, the core routines, 469*7c478bd9Sstevel@tonic-gate * a diskless helper module, rpcmod, and the tli interface. Load 470*7c478bd9Sstevel@tonic-gate * them now while we still can. 471*7c478bd9Sstevel@tonic-gate * 472*7c478bd9Sstevel@tonic-gate * Because we glomb all versions of nfs into a single module 473*7c478bd9Sstevel@tonic-gate * we check based on the initial string "nfs". 474*7c478bd9Sstevel@tonic-gate * 475*7c478bd9Sstevel@tonic-gate * XXX: A better test for this is to see if device_type 476*7c478bd9Sstevel@tonic-gate * XXX: from the PROM is "network". 477*7c478bd9Sstevel@tonic-gate */ 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 480*7c478bd9Sstevel@tonic-gate ++netboot; 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if ((err = modload("misc", "tlimod")) < 0) { 483*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/tlimod\n"); 484*7c478bd9Sstevel@tonic-gate goto out; 485*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate if ((err = modload("strmod", "rpcmod")) < 0) { 488*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n"); 489*7c478bd9Sstevel@tonic-gate goto out; 490*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate if ((err = modload("misc", "nfs_dlboot")) < 0) { 493*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n"); 494*7c478bd9Sstevel@tonic-gate goto out; 495*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate if ((err = modload("misc", "strplumb")) < 0) { 498*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/strplumb\n"); 499*7c478bd9Sstevel@tonic-gate goto out; 500*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate if ((err = strplumb_load()) < 0) { 503*7c478bd9Sstevel@tonic-gate goto out; 504*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * Preload modules needed for booting as a cluster. 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate err = clboot_loadrootmodules(); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate out: 514*7c478bd9Sstevel@tonic-gate if (err != 0 && (boothowto & RB_ASKNAME)) 515*7c478bd9Sstevel@tonic-gate goto loop; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate return (err); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * Get the name of the root or swap filesystem type, and return 523*7c478bd9Sstevel@tonic-gate * the corresponding entry in the vfs switch. 524*7c478bd9Sstevel@tonic-gate * 525*7c478bd9Sstevel@tonic-gate * If we're not asking the user, and we're trying to find the 526*7c478bd9Sstevel@tonic-gate * root filesystem type, we ask boot for the filesystem 527*7c478bd9Sstevel@tonic-gate * type that it came from and use that. Similarly, if we're 528*7c478bd9Sstevel@tonic-gate * trying to find the swap filesystem, we try and derive it from 529*7c478bd9Sstevel@tonic-gate * the root filesystem type. 530*7c478bd9Sstevel@tonic-gate * 531*7c478bd9Sstevel@tonic-gate * If we are booting via NFS we currently have these options: 532*7c478bd9Sstevel@tonic-gate * nfs - dynamically choose NFS V2. V3, or V4 (default) 533*7c478bd9Sstevel@tonic-gate * nfs2 - force NFS V2 534*7c478bd9Sstevel@tonic-gate * nfs3 - force NFS V3 535*7c478bd9Sstevel@tonic-gate * nfs4 - force NFS V4 536*7c478bd9Sstevel@tonic-gate * Because we need to maintain backward compatibility with the naming 537*7c478bd9Sstevel@tonic-gate * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c) 538*7c478bd9Sstevel@tonic-gate * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic 539*7c478bd9Sstevel@tonic-gate * nfs module will map the type back to either "nfs", "nfs3", or "nfs4". 540*7c478bd9Sstevel@tonic-gate * This is only for root filesystems, all other uses such as cachefs 541*7c478bd9Sstevel@tonic-gate * will expect that "nfs" == NFS V2. 542*7c478bd9Sstevel@tonic-gate * 543*7c478bd9Sstevel@tonic-gate * If the filesystem isn't already loaded, vfs_getvfssw() will load 544*7c478bd9Sstevel@tonic-gate * it for us, but if (at the time we call it) modrootloaded is 545*7c478bd9Sstevel@tonic-gate * still not set, it won't run the filesystems _init routine (and 546*7c478bd9Sstevel@tonic-gate * implicitly it won't run the filesystems vsw_init() entry either). 547*7c478bd9Sstevel@tonic-gate * We do that explicitly in rootconf(). 548*7c478bd9Sstevel@tonic-gate */ 549*7c478bd9Sstevel@tonic-gate static struct vfssw * 550*7c478bd9Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen) 551*7c478bd9Sstevel@tonic-gate { 552*7c478bd9Sstevel@tonic-gate struct vfssw *vsw; 553*7c478bd9Sstevel@tonic-gate static char defaultfs[BO_MAXFSNAME]; 554*7c478bd9Sstevel@tonic-gate int root = 0; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 557*7c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "fstype", defaultfs); 558*7c478bd9Sstevel@tonic-gate root++; 559*7c478bd9Sstevel@tonic-gate } else { 560*7c478bd9Sstevel@tonic-gate (void) strcpy(defaultfs, "swapfs"); 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 564*7c478bd9Sstevel@tonic-gate for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') { 565*7c478bd9Sstevel@tonic-gate printf("%s filesystem type [%s]: ", askfor, defaultfs); 566*7c478bd9Sstevel@tonic-gate console_gets(fsname, fsnamelen); 567*7c478bd9Sstevel@tonic-gate if (*fsname == '\0') 568*7c478bd9Sstevel@tonic-gate (void) strcpy(fsname, defaultfs); 569*7c478bd9Sstevel@tonic-gate if (root) { 570*7c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 571*7c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 572*7c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 573*7c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate if ((vsw = vfs_getvfssw(fsname)) != NULL) 576*7c478bd9Sstevel@tonic-gate return (vsw); 577*7c478bd9Sstevel@tonic-gate printf("Unknown filesystem type '%s'\n", fsname); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate } else if (*fsname == '\0') { 580*7c478bd9Sstevel@tonic-gate fsname = defaultfs; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate if (*fsname == '\0') { 583*7c478bd9Sstevel@tonic-gate return (NULL); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (root) { 587*7c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 588*7c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 589*7c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 590*7c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate return (vfs_getvfssw(fsname)); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* 598*7c478bd9Sstevel@tonic-gate * Get a physical device name, and maybe load and attach 599*7c478bd9Sstevel@tonic-gate * the driver. 600*7c478bd9Sstevel@tonic-gate * 601*7c478bd9Sstevel@tonic-gate * XXX Need better checking of whether or not a device 602*7c478bd9Sstevel@tonic-gate * actually exists if the user typed in a pathname. 603*7c478bd9Sstevel@tonic-gate * 604*7c478bd9Sstevel@tonic-gate * XXX Are we sure we want to expose users to this sort 605*7c478bd9Sstevel@tonic-gate * of physical namespace gobbledygook (now there's 606*7c478bd9Sstevel@tonic-gate * a word to conjure with..) 607*7c478bd9Sstevel@tonic-gate * 608*7c478bd9Sstevel@tonic-gate * XXX Note that on an OBP machine, we can easily ask the 609*7c478bd9Sstevel@tonic-gate * prom and pretty-print some plausible set of bootable 610*7c478bd9Sstevel@tonic-gate * devices. We can also user the prom to verify any 611*7c478bd9Sstevel@tonic-gate * such device. Later tim.. later. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate static int 614*7c478bd9Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen) 615*7c478bd9Sstevel@tonic-gate { 616*7c478bd9Sstevel@tonic-gate static char fmt[] = "Enter physical name of %s device\n[%s]: "; 617*7c478bd9Sstevel@tonic-gate dev_t dev; 618*7c478bd9Sstevel@tonic-gate static char defaultpath[BO_MAXOBJNAME]; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * Establish 'default' values - we get the root device from 622*7c478bd9Sstevel@tonic-gate * boot, and we infer the swap device is the same but with 623*7c478bd9Sstevel@tonic-gate * a 'b' on the end instead of an 'a'. A first stab at 624*7c478bd9Sstevel@tonic-gate * ease-of-use .. 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 627*7c478bd9Sstevel@tonic-gate /* 628*7c478bd9Sstevel@tonic-gate * Look for the 1275 compliant name 'bootpath' first, 629*7c478bd9Sstevel@tonic-gate * but make certain it has a non-NULL value as well. 630*7c478bd9Sstevel@tonic-gate */ 631*7c478bd9Sstevel@tonic-gate if ((BOP_GETPROP(bootops, "bootpath", defaultpath) == -1) || 632*7c478bd9Sstevel@tonic-gate strlen(defaultpath) == 0) { 633*7c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, 634*7c478bd9Sstevel@tonic-gate "boot-path", defaultpath) == -1) 635*7c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate } else { 638*7c478bd9Sstevel@tonic-gate (void) strcpy(defaultpath, rootfs.bo_name); 639*7c478bd9Sstevel@tonic-gate defaultpath[strlen(defaultpath) - 1] = 'b'; 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate retry: 643*7c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 644*7c478bd9Sstevel@tonic-gate printf(fmt, askfor, defaultpath); 645*7c478bd9Sstevel@tonic-gate console_gets(name, namelen); 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate if (*name == '\0') 648*7c478bd9Sstevel@tonic-gate (void) strcpy(name, defaultpath); 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate if (strcmp(askfor, "swap") == 0) { 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate /* 653*7c478bd9Sstevel@tonic-gate * Try to load and install the swap device driver. 654*7c478bd9Sstevel@tonic-gate */ 655*7c478bd9Sstevel@tonic-gate dev = ddi_pathname_to_dev_t(name); 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate if (dev == (dev_t)-1) { 658*7c478bd9Sstevel@tonic-gate printf("Not a supported device for swap.\n"); 659*7c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 660*7c478bd9Sstevel@tonic-gate goto retry; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * Ensure that we're not trying to swap on the floppy. 665*7c478bd9Sstevel@tonic-gate */ 666*7c478bd9Sstevel@tonic-gate if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) { 667*7c478bd9Sstevel@tonic-gate printf("Too dangerous to swap on the floppy\n"); 668*7c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) 669*7c478bd9Sstevel@tonic-gate goto retry; 670*7c478bd9Sstevel@tonic-gate return (-1); 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate return (0); 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * Load a driver needed to boot. 680*7c478bd9Sstevel@tonic-gate */ 681*7c478bd9Sstevel@tonic-gate static int 682*7c478bd9Sstevel@tonic-gate load_boot_driver(char *drv) 683*7c478bd9Sstevel@tonic-gate { 684*7c478bd9Sstevel@tonic-gate char *drvname; 685*7c478bd9Sstevel@tonic-gate major_t major; 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 688*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 689*7c478bd9Sstevel@tonic-gate return (-1); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate /* 692*7c478bd9Sstevel@tonic-gate * resolve aliases 693*7c478bd9Sstevel@tonic-gate */ 694*7c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 697*7c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 698*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s\n", drv)); 699*7c478bd9Sstevel@tonic-gate } else { 700*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname)); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 705*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load driver\n", drvname); 706*7c478bd9Sstevel@tonic-gate return (-1); 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate return (0); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * For a given instance, load that driver and its parents 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate static int 717*7c478bd9Sstevel@tonic-gate load_parent_drivers(dev_info_t *dip) 718*7c478bd9Sstevel@tonic-gate { 719*7c478bd9Sstevel@tonic-gate int rval = 0; 720*7c478bd9Sstevel@tonic-gate char *drv; 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate while (dip) { 723*7c478bd9Sstevel@tonic-gate drv = ddi_get_name(dip); 724*7c478bd9Sstevel@tonic-gate if (load_boot_driver(drv) != 0) 725*7c478bd9Sstevel@tonic-gate rval = -1; 726*7c478bd9Sstevel@tonic-gate dip = ddi_get_parent(dip); 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate return (rval); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /* 734*7c478bd9Sstevel@tonic-gate * For a given path to a boot device, 735*7c478bd9Sstevel@tonic-gate * load that driver and all its parents. 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate static int 738*7c478bd9Sstevel@tonic-gate load_bootpath_drivers(char *bootpath) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (bootpath == NULL || *bootpath == 0) 743*7c478bd9Sstevel@tonic-gate return (-1); 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath)); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate dip = path_to_devinfo(bootpath); 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 750*7c478bd9Sstevel@tonic-gate /* 751*7c478bd9Sstevel@tonic-gate * i386 does not provide stub nodes for all boot devices, 752*7c478bd9Sstevel@tonic-gate * but we should be able to find the node for the parent, 753*7c478bd9Sstevel@tonic-gate * and the leaf of the boot path should be the driver name, 754*7c478bd9Sstevel@tonic-gate * which we go ahead and load here. 755*7c478bd9Sstevel@tonic-gate */ 756*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 757*7c478bd9Sstevel@tonic-gate char *pathcopy, *leaf, *p; 758*7c478bd9Sstevel@tonic-gate int len, rval; 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate len = strlen(bootpath) + 1; 761*7c478bd9Sstevel@tonic-gate pathcopy = kmem_zalloc(len, KM_SLEEP); 762*7c478bd9Sstevel@tonic-gate (void) strcpy(pathcopy, bootpath); 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate * Work backward to the last slash to build the 766*7c478bd9Sstevel@tonic-gate * full path of the parent of the boot device 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate for (p = pathcopy + len - 2; *p != '/'; p--) 769*7c478bd9Sstevel@tonic-gate ; 770*7c478bd9Sstevel@tonic-gate *p++ = 0; 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /* 773*7c478bd9Sstevel@tonic-gate * Now isolate the driver name of the leaf device 774*7c478bd9Sstevel@tonic-gate */ 775*7c478bd9Sstevel@tonic-gate for (leaf = p; *p && *p != '@'; p++) 776*7c478bd9Sstevel@tonic-gate ; 777*7c478bd9Sstevel@tonic-gate *p = 0; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n", 780*7c478bd9Sstevel@tonic-gate pathcopy, leaf)); 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate dip = path_to_devinfo(pathcopy); 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate rval = load_boot_driver(leaf); 785*7c478bd9Sstevel@tonic-gate kmem_free(pathcopy, len); 786*7c478bd9Sstevel@tonic-gate if (rval == -1) 787*7c478bd9Sstevel@tonic-gate return (NULL); 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate #endif 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 793*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "can't bind driver for boot path <%s>", 794*7c478bd9Sstevel@tonic-gate bootpath); 795*7c478bd9Sstevel@tonic-gate return (NULL); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate /* 799*7c478bd9Sstevel@tonic-gate * Load IP over IB driver when netbooting over IB. 800*7c478bd9Sstevel@tonic-gate * As per IB 1275 binding, IP over IB is represented as 801*7c478bd9Sstevel@tonic-gate * service on the top of the HCA node. So, there is no 802*7c478bd9Sstevel@tonic-gate * PROM node and generic framework cannot pre-load 803*7c478bd9Sstevel@tonic-gate * IP over IB driver based on the bootpath. The following 804*7c478bd9Sstevel@tonic-gate * code preloads IP over IB driver when doing netboot over 805*7c478bd9Sstevel@tonic-gate * InfiniBand. 806*7c478bd9Sstevel@tonic-gate */ 807*7c478bd9Sstevel@tonic-gate if (netboot_over_ib(bootpath) && 808*7c478bd9Sstevel@tonic-gate modloadonly("drv", "ibd") == -1) { 809*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ibd: cannot load platform driver\n"); 810*7c478bd9Sstevel@tonic-gate return (NULL); 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate return (load_parent_drivers(dip)); 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* 820*7c478bd9Sstevel@tonic-gate * Load drivers required for a platform 821*7c478bd9Sstevel@tonic-gate * Since all hardware nodes should be available in the device 822*7c478bd9Sstevel@tonic-gate * tree, walk the per-driver list and load the parents of 823*7c478bd9Sstevel@tonic-gate * each node found. If not a hardware node, try to load it. 824*7c478bd9Sstevel@tonic-gate * Pseudo nexus is already loaded. 825*7c478bd9Sstevel@tonic-gate */ 826*7c478bd9Sstevel@tonic-gate static int 827*7c478bd9Sstevel@tonic-gate load_boot_platform_modules(char *drv) 828*7c478bd9Sstevel@tonic-gate { 829*7c478bd9Sstevel@tonic-gate major_t major; 830*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 831*7c478bd9Sstevel@tonic-gate char *drvname; 832*7c478bd9Sstevel@tonic-gate int rval = 0; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 835*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 836*7c478bd9Sstevel@tonic-gate return (-1); 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* 840*7c478bd9Sstevel@tonic-gate * resolve aliases 841*7c478bd9Sstevel@tonic-gate */ 842*7c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 843*7c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drvname)) == (major_t)-1) 844*7c478bd9Sstevel@tonic-gate return (-1); 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 847*7c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 848*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s\n", drv)); 849*7c478bd9Sstevel@tonic-gate } else { 850*7c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s -> %s\n", 851*7c478bd9Sstevel@tonic-gate drv, drvname)); 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate dip = devnamesp[major].dn_head; 856*7c478bd9Sstevel@tonic-gate if (dip == NULL) { 857*7c478bd9Sstevel@tonic-gate /* pseudo node, not-enumerated, needs to be loaded */ 858*7c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 859*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load platform driver\n", 860*7c478bd9Sstevel@tonic-gate drvname); 861*7c478bd9Sstevel@tonic-gate rval = -1; 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate } else { 864*7c478bd9Sstevel@tonic-gate while (dip) { 865*7c478bd9Sstevel@tonic-gate if (load_parent_drivers(dip) != 0) 866*7c478bd9Sstevel@tonic-gate rval = -1; 867*7c478bd9Sstevel@tonic-gate dip = ddi_get_next(dip); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate return (rval); 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * i_find_node: Internal routine used by path_to_devinfo 877*7c478bd9Sstevel@tonic-gate * to locate a given nodeid in the device tree. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate struct i_path_findnode { 880*7c478bd9Sstevel@tonic-gate dnode_t nodeid; 881*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 882*7c478bd9Sstevel@tonic-gate }; 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate static int 885*7c478bd9Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg) 886*7c478bd9Sstevel@tonic-gate { 887*7c478bd9Sstevel@tonic-gate struct i_path_findnode *f = (struct i_path_findnode *)arg; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if (ddi_get_nodeid(dev) == (int)f->nodeid) { 891*7c478bd9Sstevel@tonic-gate f->dip = dev; 892*7c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate /* 898*7c478bd9Sstevel@tonic-gate * Return the devinfo node to a boot device 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate static dev_info_t * 901*7c478bd9Sstevel@tonic-gate path_to_devinfo(char *path) 902*7c478bd9Sstevel@tonic-gate { 903*7c478bd9Sstevel@tonic-gate struct i_path_findnode fn; 904*7c478bd9Sstevel@tonic-gate extern dev_info_t *top_devinfo; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate /* 907*7c478bd9Sstevel@tonic-gate * Get the nodeid of the given pathname, if such a mapping exists. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate fn.dip = NULL; 910*7c478bd9Sstevel@tonic-gate fn.nodeid = prom_finddevice(path); 911*7c478bd9Sstevel@tonic-gate if (fn.nodeid != OBP_BADNODE) { 912*7c478bd9Sstevel@tonic-gate /* 913*7c478bd9Sstevel@tonic-gate * Find the nodeid in our copy of the device tree and return 914*7c478bd9Sstevel@tonic-gate * whatever name we used to bind this node to a driver. 915*7c478bd9Sstevel@tonic-gate */ 916*7c478bd9Sstevel@tonic-gate ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn)); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * If we're bound to something other than the nodename, 922*7c478bd9Sstevel@tonic-gate * note that in the message buffer and system log. 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate if (fn.dip) { 925*7c478bd9Sstevel@tonic-gate char *p, *q; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate p = ddi_binding_name(fn.dip); 928*7c478bd9Sstevel@tonic-gate q = ddi_node_name(fn.dip); 929*7c478bd9Sstevel@tonic-gate if (p && q && (strcmp(p, q) != 0)) { 930*7c478bd9Sstevel@tonic-gate BMDPRINTF(("path_to_devinfo: %s bound to %s\n", 931*7c478bd9Sstevel@tonic-gate path, p)); 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate return (fn.dip); 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate /* 940*7c478bd9Sstevel@tonic-gate * This routine returns B_TRUE if the bootpath corresponds to 941*7c478bd9Sstevel@tonic-gate * IP over IB driver. 942*7c478bd9Sstevel@tonic-gate * 943*7c478bd9Sstevel@tonic-gate * The format of the bootpath for the IP over IB looks like 944*7c478bd9Sstevel@tonic-gate * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip 945*7c478bd9Sstevel@tonic-gate * 946*7c478bd9Sstevel@tonic-gate * The minor node portion "port=1,pkey=8001,protocol=ip" represents 947*7c478bd9Sstevel@tonic-gate * IP over IB driver. 948*7c478bd9Sstevel@tonic-gate */ 949*7c478bd9Sstevel@tonic-gate static boolean_t 950*7c478bd9Sstevel@tonic-gate netboot_over_ib(char *bootpath) 951*7c478bd9Sstevel@tonic-gate { 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate char *temp; 954*7c478bd9Sstevel@tonic-gate boolean_t ret = B_FALSE; 955*7c478bd9Sstevel@tonic-gate dnode_t node = prom_finddevice(bootpath); 956*7c478bd9Sstevel@tonic-gate int len; 957*7c478bd9Sstevel@tonic-gate char devicetype[OBP_MAXDRVNAME]; 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate /* Is this IB node ? */ 960*7c478bd9Sstevel@tonic-gate len = prom_getproplen(node, OBP_DEVICETYPE); 961*7c478bd9Sstevel@tonic-gate if (len <= 1 || len >= OBP_MAXDRVNAME) 962*7c478bd9Sstevel@tonic-gate return (B_FALSE); 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate if (strncmp("ib", devicetype, 2) == 0) { 967*7c478bd9Sstevel@tonic-gate /* Check for proper IP over IB string */ 968*7c478bd9Sstevel@tonic-gate if ((temp = strstr(bootpath, ":port=")) != NULL) { 969*7c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, ",pkey=")) != NULL) 970*7c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, 971*7c478bd9Sstevel@tonic-gate ",protocol=ip")) != NULL) { 972*7c478bd9Sstevel@tonic-gate ret = B_TRUE; 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate return (ret); 977*7c478bd9Sstevel@tonic-gate } 978