xref: /onnv-gate/usr/src/uts/common/os/swapgeneric.c (revision 12163:f0cf0084e756)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52357Sseb  * Common Development and Distribution License (the "License").
62357Sseb  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
220Sstevel@tonic-gate /*
23*12163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 1982, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * Configure root, swap and dump devices.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/param.h>
330Sstevel@tonic-gate #include <sys/sysmacros.h>
340Sstevel@tonic-gate #include <sys/signal.h>
350Sstevel@tonic-gate #include <sys/cred.h>
360Sstevel@tonic-gate #include <sys/proc.h>
370Sstevel@tonic-gate #include <sys/user.h>
380Sstevel@tonic-gate #include <sys/conf.h>
390Sstevel@tonic-gate #include <sys/buf.h>
400Sstevel@tonic-gate #include <sys/systm.h>
410Sstevel@tonic-gate #include <sys/vm.h>
420Sstevel@tonic-gate #include <sys/reboot.h>
430Sstevel@tonic-gate #include <sys/file.h>
440Sstevel@tonic-gate #include <sys/vfs.h>
450Sstevel@tonic-gate #include <sys/vnode.h>
460Sstevel@tonic-gate #include <sys/errno.h>
470Sstevel@tonic-gate #include <sys/kmem.h>
480Sstevel@tonic-gate #include <sys/uio.h>
490Sstevel@tonic-gate #include <sys/open.h>
500Sstevel@tonic-gate #include <sys/mount.h>
510Sstevel@tonic-gate #include <sys/kobj.h>
520Sstevel@tonic-gate #include <sys/bootconf.h>
530Sstevel@tonic-gate #include <sys/sysconf.h>
540Sstevel@tonic-gate #include <sys/modctl.h>
550Sstevel@tonic-gate #include <sys/autoconf.h>
560Sstevel@tonic-gate #include <sys/debug.h>
570Sstevel@tonic-gate #include <sys/fs/snode.h>
580Sstevel@tonic-gate #include <fs/fs_subr.h>
590Sstevel@tonic-gate #include <sys/socket.h>
600Sstevel@tonic-gate #include <net/if.h>
610Sstevel@tonic-gate 
620Sstevel@tonic-gate #include <sys/mkdev.h>
630Sstevel@tonic-gate #include <sys/cmn_err.h>
640Sstevel@tonic-gate #include <sys/console.h>
650Sstevel@tonic-gate 
660Sstevel@tonic-gate #include <sys/conf.h>
670Sstevel@tonic-gate #include <sys/ddi.h>
680Sstevel@tonic-gate #include <sys/sunddi.h>
690Sstevel@tonic-gate #include <sys/hwconf.h>
700Sstevel@tonic-gate #include <sys/dc_ki.h>
710Sstevel@tonic-gate #include <sys/promif.h>
7210822SJack.Meng@Sun.COM #include <sys/bootprops.h>
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate  * Local routines
760Sstevel@tonic-gate  */
770Sstevel@tonic-gate static int preload_module(struct sysparam *, void *);
780Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t);
790Sstevel@tonic-gate static int getphysdev(char *, char *, size_t);
800Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath);
810Sstevel@tonic-gate static int load_boot_driver(char *drv);
820Sstevel@tonic-gate static int load_boot_platform_modules(char *drv);
830Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path);
840Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath);
8510822SJack.Meng@Sun.COM static boolean_t netboot_over_iscsi(void);
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Module linkage information for the kernel.
890Sstevel@tonic-gate  */
900Sstevel@tonic-gate static struct modlmisc modlmisc = {
915648Ssetje 	&mod_miscops, "root and swap configuration"
920Sstevel@tonic-gate };
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static struct modlinkage modlinkage = {
950Sstevel@tonic-gate 	MODREV_1, (void *)&modlmisc, NULL
960Sstevel@tonic-gate };
970Sstevel@tonic-gate 
980Sstevel@tonic-gate int
_init(void)990Sstevel@tonic-gate _init(void)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 	return (mod_install(&modlinkage));
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate int
_fini(void)1050Sstevel@tonic-gate _fini(void)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1110Sstevel@tonic-gate _info(struct modinfo *modinfop)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
11610822SJack.Meng@Sun.COM extern ib_boot_prop_t *iscsiboot_prop;
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate  * Configure root file system.
1190Sstevel@tonic-gate  */
1200Sstevel@tonic-gate int
rootconf(void)1210Sstevel@tonic-gate rootconf(void)
1220Sstevel@tonic-gate {
12310822SJack.Meng@Sun.COM 	int		error;
12410822SJack.Meng@Sun.COM 	struct vfssw	*vsw;
1250Sstevel@tonic-gate 	extern void pm_init(void);
12610822SJack.Meng@Sun.COM 	int ret = -1;
1270Sstevel@tonic-gate 	BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
1280Sstevel@tonic-gate 	BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
1290Sstevel@tonic-gate 	BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
1300Sstevel@tonic-gate 	BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	/*
1330Sstevel@tonic-gate 	 * Install cluster modules that were only loaded during
1340Sstevel@tonic-gate 	 * loadrootmodules().
1350Sstevel@tonic-gate 	 */
1360Sstevel@tonic-gate 	if (error = clboot_rootconf())
1370Sstevel@tonic-gate 		return (error);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (root_is_svm) {
1400Sstevel@tonic-gate 		(void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME);
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 		BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name));
1430Sstevel@tonic-gate 		BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath));
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	/*
1470Sstevel@tonic-gate 	 * Run _init on the root filesystem (we already loaded it
1480Sstevel@tonic-gate 	 * but we've been waiting until now to _init it) which will
1490Sstevel@tonic-gate 	 * have the side-effect of running vsw_init() on this vfs.
1500Sstevel@tonic-gate 	 * Because all the nfs filesystems are lumped into one
1510Sstevel@tonic-gate 	 * module we need to special case it.
1520Sstevel@tonic-gate 	 */
1530Sstevel@tonic-gate 	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
1540Sstevel@tonic-gate 		if (modload("fs", "nfs") == -1) {
1550Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1560Sstevel@tonic-gate 			    rootfs.bo_fstype);
1570Sstevel@tonic-gate 			return (ENXIO);
1580Sstevel@tonic-gate 		}
1590Sstevel@tonic-gate 	} else {
1600Sstevel@tonic-gate 		if (modload("fs", rootfs.bo_fstype) == -1) {
1610Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1620Sstevel@tonic-gate 			    rootfs.bo_fstype);
1630Sstevel@tonic-gate 			return (ENXIO);
1640Sstevel@tonic-gate 		}
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	RLOCK_VFSSW();
1670Sstevel@tonic-gate 	vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
1680Sstevel@tonic-gate 	RUNLOCK_VFSSW();
1697439SPavel.Filipensky@Sun.COM 	if (vsw == NULL) {
1707439SPavel.Filipensky@Sun.COM 		cmn_err(CE_CONT, "Cannot find %s filesystem\n",
1717439SPavel.Filipensky@Sun.COM 		    rootfs.bo_fstype);
1727439SPavel.Filipensky@Sun.COM 		return (ENXIO);
1737439SPavel.Filipensky@Sun.COM 	}
1740Sstevel@tonic-gate 	VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
1750Sstevel@tonic-gate 	VFS_HOLD(rootvfs);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if (root_is_svm) {
1780Sstevel@tonic-gate 		rootvfs->vfs_flag |= VFS_RDONLY;
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/*
1820Sstevel@tonic-gate 	 * This pm-releated call has to occur before root is mounted since we
1830Sstevel@tonic-gate 	 * need to power up all devices.  It is placed after VFS_INIT() such
1840Sstevel@tonic-gate 	 * that opening a device via ddi_lyr_ interface just before root has
1850Sstevel@tonic-gate 	 * been mounted would work.
1860Sstevel@tonic-gate 	 */
1870Sstevel@tonic-gate 	pm_init();
1880Sstevel@tonic-gate 
18910822SJack.Meng@Sun.COM 	if (netboot && iscsiboot_prop) {
19010822SJack.Meng@Sun.COM 		cmn_err(CE_WARN, "NFS boot and iSCSI boot"
19110822SJack.Meng@Sun.COM 		    " shouldn't happen in the same time");
19210822SJack.Meng@Sun.COM 		return (EINVAL);
19310822SJack.Meng@Sun.COM 	}
19410822SJack.Meng@Sun.COM 
19510822SJack.Meng@Sun.COM 	if (netboot || iscsiboot_prop) {
19610822SJack.Meng@Sun.COM 		ret = strplumb();
19710822SJack.Meng@Sun.COM 		if (ret != 0) {
19810822SJack.Meng@Sun.COM 			cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
19910822SJack.Meng@Sun.COM 			return (EFAULT);
20010822SJack.Meng@Sun.COM 		}
20110822SJack.Meng@Sun.COM 	}
20210822SJack.Meng@Sun.COM 
20310822SJack.Meng@Sun.COM 	if ((ret == 0) && iscsiboot_prop) {
20410822SJack.Meng@Sun.COM 		ret = modload("drv", "iscsi");
20510822SJack.Meng@Sun.COM 		/* -1 indicates fail */
20610822SJack.Meng@Sun.COM 		if (ret == -1) {
20710822SJack.Meng@Sun.COM 			cmn_err(CE_WARN, "Failed to load iscsi module");
20810822SJack.Meng@Sun.COM 			iscsi_boot_prop_free();
20910822SJack.Meng@Sun.COM 			return (EINVAL);
21010822SJack.Meng@Sun.COM 		} else {
21110822SJack.Meng@Sun.COM 			if (!i_ddi_attach_pseudo_node("iscsi")) {
21210822SJack.Meng@Sun.COM 				cmn_err(CE_WARN,
21310822SJack.Meng@Sun.COM 				    "Failed to attach iscsi driver");
21410822SJack.Meng@Sun.COM 				iscsi_boot_prop_free();
21510822SJack.Meng@Sun.COM 				return (ENODEV);
21610822SJack.Meng@Sun.COM 			}
2170Sstevel@tonic-gate 		}
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/*
2210Sstevel@tonic-gate 	 * ufs_mountroot() ends up calling getrootdev()
2220Sstevel@tonic-gate 	 * (below) which actually triggers the _init, identify,
2230Sstevel@tonic-gate 	 * probe and attach of the drivers that make up root device
2240Sstevel@tonic-gate 	 * bush; these are also quietly waiting in memory.
2250Sstevel@tonic-gate 	 */
2260Sstevel@tonic-gate 	BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
2290Sstevel@tonic-gate 	vfs_unrefvfssw(vsw);
2300Sstevel@tonic-gate 	rootdev = rootvfs->vfs_dev;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	if (error)
2330Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
2340Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2350Sstevel@tonic-gate 	else
2360Sstevel@tonic-gate 		cmn_err(CE_CONT, "?root on %s fstype %s\n",
2370Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2380Sstevel@tonic-gate 	return (error);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate /*
2420Sstevel@tonic-gate  * Remount root on an SVM mirror root device
2430Sstevel@tonic-gate  * Only supported on UFS filesystems at present
2440Sstevel@tonic-gate  */
2450Sstevel@tonic-gate int
svm_rootconf(void)2460Sstevel@tonic-gate svm_rootconf(void)
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate 	int	error;
2490Sstevel@tonic-gate 	extern int ufs_remountroot(struct vfs *vfsp);
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	ASSERT(root_is_svm == 1);
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	if (strcmp(rootfs.bo_fstype, "ufs") != 0) {
2540Sstevel@tonic-gate 		cmn_err(CE_CONT, "Mounting root on %s with filesystem "
2550Sstevel@tonic-gate 		    "type %s is not supported\n",
2560Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2570Sstevel@tonic-gate 		return (EINVAL);
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	(void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME);
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name));
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	error = ufs_remountroot(rootvfs);
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (error) {
2670Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n",
2684851Scth 		    rootfs.bo_name, rootfs.bo_fstype);
2690Sstevel@tonic-gate 	} else {
2700Sstevel@tonic-gate 		cmn_err(CE_CONT, "?root remounted on %s fstype %s\n",
2714851Scth 		    rootfs.bo_name, rootfs.bo_fstype);
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 	return (error);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate  * Under the assumption that our root file system is on a
2780Sstevel@tonic-gate  * disk partition, get the dev_t of the partition in question.
2790Sstevel@tonic-gate  *
2800Sstevel@tonic-gate  * By now, boot has faithfully loaded all our modules into memory, and
2810Sstevel@tonic-gate  * we've taken over resource management.  Before we go any further, we
2820Sstevel@tonic-gate  * have to fire up the device drivers and stuff we need to mount the
2830Sstevel@tonic-gate  * root filesystem.  That's what we do here.  Fingers crossed.
2840Sstevel@tonic-gate  */
2850Sstevel@tonic-gate dev_t
getrootdev(void)2860Sstevel@tonic-gate getrootdev(void)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	dev_t	d;
2890Sstevel@tonic-gate 
29010822SJack.Meng@Sun.COM 	d = ddi_pathname_to_dev_t(rootfs.bo_name);
29110822SJack.Meng@Sun.COM 	if ((d == NODEV) && (iscsiboot_prop != NULL)) {
29210822SJack.Meng@Sun.COM 		/* Give it another try with the 'disk' path */
29310822SJack.Meng@Sun.COM 		get_iscsi_bootpath_phy(rootfs.bo_name);
29410822SJack.Meng@Sun.COM 		d = ddi_pathname_to_dev_t(rootfs.bo_name);
29510822SJack.Meng@Sun.COM 	}
29610822SJack.Meng@Sun.COM 	if (d == NODEV)
2970Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
2980Sstevel@tonic-gate 		    rootfs.bo_name);
2990Sstevel@tonic-gate 	return (d);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate  * If booted with ASKNAME, prompt on the console for a filesystem
3040Sstevel@tonic-gate  * name and return it.
3050Sstevel@tonic-gate  */
3060Sstevel@tonic-gate void
getfsname(char * askfor,char * name,size_t namelen)3070Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
3100Sstevel@tonic-gate 		printf("%s name: ", askfor);
3110Sstevel@tonic-gate 		console_gets(name, namelen);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate /*ARGSUSED1*/
3160Sstevel@tonic-gate static int
preload_module(struct sysparam * sysp,void * p)3170Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p)
3180Sstevel@tonic-gate {
3190Sstevel@tonic-gate 	static char *wmesg = "forceload of %s failed";
3200Sstevel@tonic-gate 	char *name;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	name = sysp->sys_ptr;
3230Sstevel@tonic-gate 	BMDPRINTF(("preload_module: %s\n", name));
3240Sstevel@tonic-gate 	if (modloadonly(NULL, name) < 0)
3250Sstevel@tonic-gate 		cmn_err(CE_WARN, wmesg, name);
3260Sstevel@tonic-gate 	return (0);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate  * We want to load all the modules needed to mount the root filesystem,
3320Sstevel@tonic-gate  * so that when we start the ball rolling in 'getrootdev', every module
3330Sstevel@tonic-gate  * should already be in memory, just waiting to be init-ed.
3340Sstevel@tonic-gate  */
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate int
loadrootmodules(void)3370Sstevel@tonic-gate loadrootmodules(void)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 	struct vfssw	*vsw;
3400Sstevel@tonic-gate 	char		*this;
3414851Scth 	char		*name;
3420Sstevel@tonic-gate 	int		err;
3430Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
3445648Ssetje 	int		i, proplen;
3450Sstevel@tonic-gate 	extern char	*impl_module_list[];
3460Sstevel@tonic-gate 	extern char	*platform_module_list[];
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	/* Make sure that the PROM's devinfo tree has been created */
3490Sstevel@tonic-gate 	ASSERT(ddi_root_node());
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
3520Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
3530Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	/*
3560Sstevel@tonic-gate 	 * zzz We need to honor what's in rootfs if it's not null.
3570Sstevel@tonic-gate 	 * non-null means use what's there.  This way we can
3580Sstevel@tonic-gate 	 * change rootfs with /etc/system AND with tunetool.
3590Sstevel@tonic-gate 	 */
3600Sstevel@tonic-gate 	if (root_is_svm) {
3610Sstevel@tonic-gate 		/* user replaced rootdev, record obp_bootpath */
3620Sstevel@tonic-gate 		obp_bootpath[0] = '\0';
3630Sstevel@tonic-gate 		(void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME);
3640Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
3650Sstevel@tonic-gate 	} else {
3660Sstevel@tonic-gate 		/*
3670Sstevel@tonic-gate 		 * Get the root fstype and root device path from boot.
3680Sstevel@tonic-gate 		 */
3690Sstevel@tonic-gate 		rootfs.bo_fstype[0] = '\0';
3700Sstevel@tonic-gate 		rootfs.bo_name[0] = '\0';
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	/*
3740Sstevel@tonic-gate 	 * This lookup will result in modloadonly-ing the root
3750Sstevel@tonic-gate 	 * filesystem module - it gets _init-ed in rootconf()
3760Sstevel@tonic-gate 	 */
3770Sstevel@tonic-gate 	if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
3780Sstevel@tonic-gate 		return (ENXIO);	/* in case we have no file system types */
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	(void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	vfs_unrefvfssw(vsw);
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	/*
3850Sstevel@tonic-gate 	 * Load the favored drivers of the implementation.
3860Sstevel@tonic-gate 	 * e.g. 'sbus' and possibly 'zs' (even).
3870Sstevel@tonic-gate 	 *
3880Sstevel@tonic-gate 	 * Called whilst boot is still loaded (because boot does
3890Sstevel@tonic-gate 	 * the i/o for us), and DDI services are unavailable.
3900Sstevel@tonic-gate 	 */
3910Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: impl_module_list\n"));
3920Sstevel@tonic-gate 	for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
3930Sstevel@tonic-gate 		if ((err = load_boot_driver(this)) != 0) {
3940Sstevel@tonic-gate 			cmn_err(CE_WARN, "Cannot load drv/%s", this);
3950Sstevel@tonic-gate 			return (err);
3960Sstevel@tonic-gate 		}
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 	/*
3990Sstevel@tonic-gate 	 * Now load the platform modules (if any)
4000Sstevel@tonic-gate 	 */
4010Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: platform_module_list\n"));
4020Sstevel@tonic-gate 	for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
4030Sstevel@tonic-gate 		if ((err = load_boot_platform_modules(this)) != 0) {
4040Sstevel@tonic-gate 			cmn_err(CE_WARN, "Cannot load drv/%s", this);
4050Sstevel@tonic-gate 			return (err);
4060Sstevel@tonic-gate 		}
4070Sstevel@tonic-gate 	}
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate loop:
4100Sstevel@tonic-gate 	(void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
4110Sstevel@tonic-gate 	/*
4120Sstevel@tonic-gate 	 * Given a physical pathname, load the correct set of driver
4130Sstevel@tonic-gate 	 * modules into memory, including all possible parents.
4140Sstevel@tonic-gate 	 *
4150Sstevel@tonic-gate 	 * NB: The code sets the variable 'name' for error reporting.
4160Sstevel@tonic-gate 	 */
4170Sstevel@tonic-gate 	err = 0;
4180Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
4190Sstevel@tonic-gate 	if (root_is_svm == 0) {
4200Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
4210Sstevel@tonic-gate 		name = rootfs.bo_name;
4220Sstevel@tonic-gate 		err = load_bootpath_drivers(rootfs.bo_name);
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	/*
4260Sstevel@tonic-gate 	 * Load driver modules in obp_bootpath, this is always
4270Sstevel@tonic-gate 	 * required for mountroot to succeed. obp_bootpath is
4280Sstevel@tonic-gate 	 * is set if rootdev is set via /etc/system, which is
4290Sstevel@tonic-gate 	 * the case if booting of a SVM/VxVM mirror.
4300Sstevel@tonic-gate 	 */
4310Sstevel@tonic-gate 	if ((err == 0) && obp_bootpath[0] != '\0') {
4320Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
4330Sstevel@tonic-gate 		name = obp_bootpath;
4340Sstevel@tonic-gate 		err = load_bootpath_drivers(obp_bootpath);
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	if (err != 0) {
4380Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
4390Sstevel@tonic-gate 		goto out;
4400Sstevel@tonic-gate 	}
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/*
4430Sstevel@tonic-gate 	 * Check to see if the booter performed DHCP configuration
4440Sstevel@tonic-gate 	 * ("bootp-response" boot property exists). If so, then before
4450Sstevel@tonic-gate 	 * bootops disappears we need to save the value of this property
4460Sstevel@tonic-gate 	 * such that the userland dhcpagent can adopt the DHCP management
4475648Ssetje 	 * of our primary network interface.
4480Sstevel@tonic-gate 	 */
4490Sstevel@tonic-gate 	proplen = BOP_GETPROPLEN(bootops, "bootp-response");
4500Sstevel@tonic-gate 	if (proplen > 0) {
4515648Ssetje 		dhcack = kmem_zalloc(proplen, KM_SLEEP);
4525648Ssetje 		if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) {
4530Sstevel@tonic-gate 			cmn_err(CE_WARN, "BOP_GETPROP of  "
4540Sstevel@tonic-gate 			    "\"bootp-response\" failed\n");
4550Sstevel@tonic-gate 			kmem_free(dhcack, dhcacklen);
4560Sstevel@tonic-gate 			dhcack = NULL;
4570Sstevel@tonic-gate 			goto out;
4580Sstevel@tonic-gate 		}
4595648Ssetje 		dhcacklen = proplen;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 		/*
4620Sstevel@tonic-gate 		 * Fetch the "netdev-path" boot property (if it exists), and
4630Sstevel@tonic-gate 		 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
4640Sstevel@tonic-gate 		 */
4650Sstevel@tonic-gate 		proplen = BOP_GETPROPLEN(bootops, "netdev-path");
4660Sstevel@tonic-gate 		if (proplen > 0) {
4670Sstevel@tonic-gate 			netdev_path = kmem_zalloc(proplen, KM_SLEEP);
4680Sstevel@tonic-gate 			if (BOP_GETPROP(bootops, "netdev-path",
4690Sstevel@tonic-gate 			    (uchar_t *)netdev_path) == -1) {
4700Sstevel@tonic-gate 				cmn_err(CE_WARN, "BOP_GETPROP of  "
4710Sstevel@tonic-gate 				    "\"netdev-path\" failed\n");
4720Sstevel@tonic-gate 				kmem_free(netdev_path, proplen);
4730Sstevel@tonic-gate 				goto out;
4740Sstevel@tonic-gate 			}
4750Sstevel@tonic-gate 		}
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	/*
4790Sstevel@tonic-gate 	 * Preload (load-only, no init) all modules which
4800Sstevel@tonic-gate 	 * were added to the /etc/system file with the
4810Sstevel@tonic-gate 	 * FORCELOAD keyword.
4820Sstevel@tonic-gate 	 */
4830Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: preload_module\n"));
4840Sstevel@tonic-gate 	(void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
4870Sstevel@tonic-gate 	/*
4880Sstevel@tonic-gate 	 * If we booted otw then load in the plumbing
4890Sstevel@tonic-gate 	 * routine now while we still can. If we didn't
4900Sstevel@tonic-gate 	 * boot otw then we will load strplumb in main().
4910Sstevel@tonic-gate 	 *
4920Sstevel@tonic-gate 	 * NFS is actually a set of modules, the core routines,
4930Sstevel@tonic-gate 	 * a diskless helper module, rpcmod, and the tli interface.  Load
4940Sstevel@tonic-gate 	 * them now while we still can.
4950Sstevel@tonic-gate 	 *
4960Sstevel@tonic-gate 	 * Because we glomb all versions of nfs into a single module
4970Sstevel@tonic-gate 	 * we check based on the initial string "nfs".
4980Sstevel@tonic-gate 	 *
4990Sstevel@tonic-gate 	 * XXX: A better test for this is to see if device_type
5000Sstevel@tonic-gate 	 * XXX: from the PROM is "network".
5010Sstevel@tonic-gate 	 */
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
5040Sstevel@tonic-gate 		++netboot;
5050Sstevel@tonic-gate 
5065895Syz147064 		/*
5075895Syz147064 		 * Preload (load-only, no init) the dacf module. We cannot
5085895Syz147064 		 * init the module because one of its requisite modules is
5095895Syz147064 		 * dld whose _init function will call taskq_create(), which
5105895Syz147064 		 * will panic the system at this point.
5115895Syz147064 		 */
5125895Syz147064 		if ((err = modloadonly("dacf", "net_dacf")) < 0)  {
5135895Syz147064 			cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
5145895Syz147064 			goto out;
5155895Syz147064 		}
5160Sstevel@tonic-gate 		if ((err = modload("misc", "tlimod")) < 0)  {
5170Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
5180Sstevel@tonic-gate 			goto out;
5190Sstevel@tonic-gate 		}
5200Sstevel@tonic-gate 		if ((err = modload("strmod", "rpcmod")) < 0)  {
5210Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
5220Sstevel@tonic-gate 			goto out;
5230Sstevel@tonic-gate 		}
5240Sstevel@tonic-gate 		if ((err = modload("misc", "nfs_dlboot")) < 0)  {
5250Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
5260Sstevel@tonic-gate 			goto out;
5270Sstevel@tonic-gate 		}
5282357Sseb 		if ((err = modload("mac", "mac_ether")) < 0)  {
5292357Sseb 			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
5302357Sseb 			goto out;
5312357Sseb 		}
5320Sstevel@tonic-gate 		if ((err = modload("misc", "strplumb")) < 0)  {
5330Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
5340Sstevel@tonic-gate 			goto out;
5350Sstevel@tonic-gate 		}
5360Sstevel@tonic-gate 		if ((err = strplumb_load()) < 0) {
5370Sstevel@tonic-gate 			goto out;
5380Sstevel@tonic-gate 		}
5390Sstevel@tonic-gate 	}
54010822SJack.Meng@Sun.COM 	if (netboot_over_iscsi() == B_TRUE) {
54110822SJack.Meng@Sun.COM 		/* iscsi boot */
54210822SJack.Meng@Sun.COM 		if ((err = modloadonly("dacf", "net_dacf")) < 0) {
54310822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
54410822SJack.Meng@Sun.COM 			goto out;
54510822SJack.Meng@Sun.COM 		}
54610822SJack.Meng@Sun.COM 		if ((err = modload("misc", "tlimod")) < 0) {
54710822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
54810822SJack.Meng@Sun.COM 			goto out;
54910822SJack.Meng@Sun.COM 		}
55010822SJack.Meng@Sun.COM 		if ((err = modload("mac", "mac_ether")) < 0) {
55110822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
55210822SJack.Meng@Sun.COM 			goto out;
55310822SJack.Meng@Sun.COM 		}
55410822SJack.Meng@Sun.COM 		if ((err = modloadonly("drv", "iscsi")) < 0) {
55510822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load drv/iscsi\n");
55610822SJack.Meng@Sun.COM 			goto out;
55710822SJack.Meng@Sun.COM 		}
55810822SJack.Meng@Sun.COM 		if ((err = modloadonly("drv", "ssd")) < 0) {
55910822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load drv/ssd\n");
56010822SJack.Meng@Sun.COM 			goto out;
56110822SJack.Meng@Sun.COM 		}
56210822SJack.Meng@Sun.COM 		if ((err = modloadonly("drv", "sd")) < 0) {
56310822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load drv/sd\n");
56410822SJack.Meng@Sun.COM 			goto out;
56510822SJack.Meng@Sun.COM 		}
56610822SJack.Meng@Sun.COM 		if ((err = modload("misc", "strplumb")) < 0) {
56710822SJack.Meng@Sun.COM 			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
56810822SJack.Meng@Sun.COM 			goto out;
56910822SJack.Meng@Sun.COM 		}
57010822SJack.Meng@Sun.COM 		if ((err = strplumb_load()) < 0) {
57110822SJack.Meng@Sun.COM 			goto out;
57210822SJack.Meng@Sun.COM 		}
57310822SJack.Meng@Sun.COM 	}
5740Sstevel@tonic-gate 	/*
5750Sstevel@tonic-gate 	 * Preload modules needed for booting as a cluster.
5760Sstevel@tonic-gate 	 */
5770Sstevel@tonic-gate 	err = clboot_loadrootmodules();
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate out:
5800Sstevel@tonic-gate 	if (err != 0 && (boothowto & RB_ASKNAME))
5810Sstevel@tonic-gate 		goto loop;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	return (err);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
5860Sstevel@tonic-gate 
5875648Ssetje static int
get_bootpath_prop(char * bootpath)5885648Ssetje get_bootpath_prop(char *bootpath)
5895648Ssetje {
5905648Ssetje 	if (root_is_ramdisk) {
5915648Ssetje 		if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1)
5925648Ssetje 			return (-1);
5935648Ssetje 		(void) strlcat(bootpath, ":a", BO_MAXOBJNAME);
5945648Ssetje 	} else {
5955648Ssetje 		/*
5965648Ssetje 		 * Look for the 1275 compliant name 'bootpath' first,
5975648Ssetje 		 * but make certain it has a non-NULL value as well.
5985648Ssetje 		 */
5995648Ssetje 		if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) ||
6005648Ssetje 		    strlen(bootpath) == 0) {
6015648Ssetje 			if (BOP_GETPROP(bootops,
6025648Ssetje 			    "boot-path", bootpath) == -1)
6035648Ssetje 				return (-1);
6045648Ssetje 		}
60510822SJack.Meng@Sun.COM 		if (memcmp(bootpath, BP_ISCSI_DISK,
60610822SJack.Meng@Sun.COM 		    strlen(BP_ISCSI_DISK)) == 0) {
60710822SJack.Meng@Sun.COM 			/* iscsi boot */
60810822SJack.Meng@Sun.COM 			get_iscsi_bootpath_vhci(bootpath);
60910822SJack.Meng@Sun.COM 		}
6105648Ssetje 	}
6115648Ssetje 	return (0);
6125648Ssetje }
6135648Ssetje 
6145648Ssetje static int
get_fstype_prop(char * fstype)6155648Ssetje get_fstype_prop(char *fstype)
6165648Ssetje {
6175648Ssetje 	char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype";
6185648Ssetje 
6195648Ssetje 	return (BOP_GETPROP(bootops, prop, fstype));
6205648Ssetje }
6215648Ssetje 
6220Sstevel@tonic-gate /*
6230Sstevel@tonic-gate  * Get the name of the root or swap filesystem type, and return
6240Sstevel@tonic-gate  * the corresponding entry in the vfs switch.
6250Sstevel@tonic-gate  *
6260Sstevel@tonic-gate  * If we're not asking the user, and we're trying to find the
6270Sstevel@tonic-gate  * root filesystem type, we ask boot for the filesystem
6280Sstevel@tonic-gate  * type that it came from and use that.  Similarly, if we're
6290Sstevel@tonic-gate  * trying to find the swap filesystem, we try and derive it from
6300Sstevel@tonic-gate  * the root filesystem type.
6310Sstevel@tonic-gate  *
6320Sstevel@tonic-gate  * If we are booting via NFS we currently have these options:
6330Sstevel@tonic-gate  *	nfs -	dynamically choose NFS V2. V3, or V4 (default)
6340Sstevel@tonic-gate  *	nfs2 -	force NFS V2
6350Sstevel@tonic-gate  *	nfs3 -	force NFS V3
6360Sstevel@tonic-gate  *	nfs4 -	force NFS V4
6370Sstevel@tonic-gate  * Because we need to maintain backward compatibility with the naming
6380Sstevel@tonic-gate  * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
6390Sstevel@tonic-gate  * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs".  The dynamic
6400Sstevel@tonic-gate  * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
6410Sstevel@tonic-gate  * This is only for root filesystems, all other uses such as cachefs
6420Sstevel@tonic-gate  * will expect that "nfs" == NFS V2.
6430Sstevel@tonic-gate  *
6440Sstevel@tonic-gate  * If the filesystem isn't already loaded, vfs_getvfssw() will load
6450Sstevel@tonic-gate  * it for us, but if (at the time we call it) modrootloaded is
6460Sstevel@tonic-gate  * still not set, it won't run the filesystems _init routine (and
6470Sstevel@tonic-gate  * implicitly it won't run the filesystems vsw_init() entry either).
6480Sstevel@tonic-gate  * We do that explicitly in rootconf().
6490Sstevel@tonic-gate  */
6500Sstevel@tonic-gate static struct vfssw *
getfstype(char * askfor,char * fsname,size_t fsnamelen)6510Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen)
6520Sstevel@tonic-gate {
6530Sstevel@tonic-gate 	struct vfssw *vsw;
6540Sstevel@tonic-gate 	static char defaultfs[BO_MAXFSNAME];
6550Sstevel@tonic-gate 	int root = 0;
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	if (strcmp(askfor, "root") == 0) {
6585648Ssetje 		(void) get_fstype_prop(defaultfs);
6590Sstevel@tonic-gate 		root++;
6600Sstevel@tonic-gate 	} else {
6610Sstevel@tonic-gate 		(void) strcpy(defaultfs, "swapfs");
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
6650Sstevel@tonic-gate 		for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') {
6660Sstevel@tonic-gate 			printf("%s filesystem type [%s]: ", askfor, defaultfs);
6670Sstevel@tonic-gate 			console_gets(fsname, fsnamelen);
6680Sstevel@tonic-gate 			if (*fsname == '\0')
6690Sstevel@tonic-gate 				(void) strcpy(fsname, defaultfs);
6700Sstevel@tonic-gate 			if (root) {
6710Sstevel@tonic-gate 				if (strcmp(fsname, "nfs2") == 0)
6720Sstevel@tonic-gate 					(void) strcpy(fsname, "nfs");
6730Sstevel@tonic-gate 				else if (strcmp(fsname, "nfs") == 0)
6740Sstevel@tonic-gate 					(void) strcpy(fsname, "nfsdyn");
6750Sstevel@tonic-gate 			}
6760Sstevel@tonic-gate 			if ((vsw = vfs_getvfssw(fsname)) != NULL)
6770Sstevel@tonic-gate 				return (vsw);
6780Sstevel@tonic-gate 			printf("Unknown filesystem type '%s'\n", fsname);
6790Sstevel@tonic-gate 		}
6800Sstevel@tonic-gate 	} else if (*fsname == '\0') {
6810Sstevel@tonic-gate 		fsname = defaultfs;
6820Sstevel@tonic-gate 	}
6830Sstevel@tonic-gate 	if (*fsname == '\0') {
6840Sstevel@tonic-gate 		return (NULL);
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	if (root) {
6880Sstevel@tonic-gate 		if (strcmp(fsname, "nfs2") == 0)
6890Sstevel@tonic-gate 			(void) strcpy(fsname, "nfs");
6900Sstevel@tonic-gate 		else if (strcmp(fsname, "nfs") == 0)
6910Sstevel@tonic-gate 			(void) strcpy(fsname, "nfsdyn");
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	return (vfs_getvfssw(fsname));
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate /*
6990Sstevel@tonic-gate  * Get a physical device name, and maybe load and attach
7000Sstevel@tonic-gate  * the driver.
7010Sstevel@tonic-gate  *
7020Sstevel@tonic-gate  * XXX	Need better checking of whether or not a device
7030Sstevel@tonic-gate  *	actually exists if the user typed in a pathname.
7040Sstevel@tonic-gate  *
7050Sstevel@tonic-gate  * XXX	Are we sure we want to expose users to this sort
7060Sstevel@tonic-gate  *	of physical namespace gobbledygook (now there's
7070Sstevel@tonic-gate  *	a word to conjure with..)
7080Sstevel@tonic-gate  *
7090Sstevel@tonic-gate  * XXX	Note that on an OBP machine, we can easily ask the
7100Sstevel@tonic-gate  *	prom and pretty-print some plausible set of bootable
7110Sstevel@tonic-gate  *	devices.  We can also user the prom to verify any
7120Sstevel@tonic-gate  *	such device.  Later tim.. later.
7130Sstevel@tonic-gate  */
7140Sstevel@tonic-gate static int
getphysdev(char * askfor,char * name,size_t namelen)7150Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen)
7160Sstevel@tonic-gate {
7170Sstevel@tonic-gate 	static char fmt[] = "Enter physical name of %s device\n[%s]: ";
7180Sstevel@tonic-gate 	dev_t dev;
7190Sstevel@tonic-gate 	static char defaultpath[BO_MAXOBJNAME];
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	/*
7220Sstevel@tonic-gate 	 * Establish 'default' values - we get the root device from
7230Sstevel@tonic-gate 	 * boot, and we infer the swap device is the same but with
7240Sstevel@tonic-gate 	 * a 'b' on the end instead of an 'a'.  A first stab at
7250Sstevel@tonic-gate 	 * ease-of-use ..
7260Sstevel@tonic-gate 	 */
7270Sstevel@tonic-gate 	if (strcmp(askfor, "root") == 0) {
7285648Ssetje 		if (get_bootpath_prop(defaultpath) == -1)
7295648Ssetje 			boothowto |= RB_ASKNAME | RB_VERBOSE;
7300Sstevel@tonic-gate 	} else {
7310Sstevel@tonic-gate 		(void) strcpy(defaultpath, rootfs.bo_name);
7320Sstevel@tonic-gate 		defaultpath[strlen(defaultpath) - 1] = 'b';
7330Sstevel@tonic-gate 	}
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate retry:
7360Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
7370Sstevel@tonic-gate 		printf(fmt, askfor, defaultpath);
7380Sstevel@tonic-gate 		console_gets(name, namelen);
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 	if (*name == '\0')
7410Sstevel@tonic-gate 		(void) strcpy(name, defaultpath);
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if (strcmp(askfor, "swap") == 0)   {
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 		/*
7460Sstevel@tonic-gate 		 * Try to load and install the swap device driver.
7470Sstevel@tonic-gate 		 */
7480Sstevel@tonic-gate 		dev = ddi_pathname_to_dev_t(name);
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 		if (dev == (dev_t)-1)  {
7510Sstevel@tonic-gate 			printf("Not a supported device for swap.\n");
7520Sstevel@tonic-gate 			boothowto |= RB_ASKNAME | RB_VERBOSE;
7530Sstevel@tonic-gate 			goto retry;
7540Sstevel@tonic-gate 		}
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 		/*
7570Sstevel@tonic-gate 		 * Ensure that we're not trying to swap on the floppy.
7580Sstevel@tonic-gate 		 */
7590Sstevel@tonic-gate 		if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
7600Sstevel@tonic-gate 			printf("Too dangerous to swap on the floppy\n");
7610Sstevel@tonic-gate 			if (boothowto & RB_ASKNAME)
7620Sstevel@tonic-gate 				goto retry;
7630Sstevel@tonic-gate 			return (-1);
7640Sstevel@tonic-gate 		}
7650Sstevel@tonic-gate 	}
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	return (0);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate /*
7720Sstevel@tonic-gate  * Load a driver needed to boot.
7730Sstevel@tonic-gate  */
7740Sstevel@tonic-gate static int
load_boot_driver(char * drv)7750Sstevel@tonic-gate load_boot_driver(char *drv)
7760Sstevel@tonic-gate {
7774851Scth 	char		*drvname;
7784851Scth 	major_t		major;
7794851Scth #ifdef	sparc
7804851Scth 	struct devnames *dnp;
7814851Scth 	ddi_prop_t	*propp;
7824851Scth 	char		*module;
7834851Scth 	char		*dir, *mf;
7844851Scth 	int		plen;
7854851Scth 	int		mlen;
7864851Scth #endif	/* sparc */
7870Sstevel@tonic-gate 
7887009Scth 	if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
7890Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: no major number\n", drv);
7900Sstevel@tonic-gate 		return (-1);
7910Sstevel@tonic-gate 	}
7920Sstevel@tonic-gate 	/*
7930Sstevel@tonic-gate 	 * resolve aliases
7940Sstevel@tonic-gate 	 */
7950Sstevel@tonic-gate 	drvname = ddi_major_to_name(major);
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate #ifdef	DEBUG
7980Sstevel@tonic-gate 	if (strcmp(drv, drvname) == 0) {
7990Sstevel@tonic-gate 		BMDPRINTF(("load_boot_driver: %s\n", drv));
8000Sstevel@tonic-gate 	} else {
8010Sstevel@tonic-gate 		BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
8020Sstevel@tonic-gate 	}
8030Sstevel@tonic-gate #endif	/* DEBUG */
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	if (modloadonly("drv", drvname) == -1) {
8060Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
8070Sstevel@tonic-gate 		return (-1);
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8104851Scth #ifdef	sparc
8114851Scth 	/*
8124851Scth 	 * NOTE: this can be removed when newboot-sparc is delivered.
8134851Scth 	 *
8144851Scth 	 * Check to see if the driver had a 'ddi-forceload' global driver.conf
8154851Scth 	 * property to identify additional modules that need to be loaded.
8164851Scth 	 * The driver still needs to use ddi_modopen() to open these modules,
8174851Scth 	 * but the 'ddi-forceload' property allows the modules to be loaded
8184851Scth 	 * into memory prior to lights-out, so that driver ddi_modopen()
8194851Scth 	 * calls during lights-out (when mounting root) will work correctly.
8204851Scth 	 * Use of 'ddi-forceload' is only required for drivers involved in
8214851Scth 	 * getting root mounted.
8224851Scth 	 */
8234851Scth 	dnp = &devnamesp[major];
8244851Scth 	if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
8254851Scth 	    ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
8264851Scth 	    "ddi-forceload", DDI_PROP_TYPE_STRING,
8274851Scth 	    &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {
8284851Scth 
8294851Scth 		module = (char *)propp->prop_val;
8304851Scth 		plen = propp->prop_len;
8314851Scth 		while (plen > 0) {
8324851Scth 			mlen = strlen(module);
8334851Scth 			mf = strrchr(module, '/');
8344851Scth 			if (mf) {
8354851Scth 				dir = module;
8364851Scth 				*mf++ = '\0';		/* '/' -> '\0' */
8374851Scth 			} else {
8384851Scth 				dir = "misc";
8394851Scth 				mf = module;
8404851Scth 			}
8414851Scth 			if (modloadonly(dir, mf) == -1)
8424851Scth 				cmn_err(CE_CONT,
8434851Scth 				    "misc/%s: can't load module\n", mf);
8444851Scth 			if (mf != module)
8454851Scth 				*(mf - 1) = '/';	/* '\0' -> '/' */
8464851Scth 
8474851Scth 			module += mlen + 1;
8484851Scth 			plen -= mlen + 1;
8494851Scth 		}
8504851Scth 	}
8514851Scth #endif	/* sparc */
8524851Scth 
8530Sstevel@tonic-gate 	return (0);
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate  * For a given instance, load that driver and its parents
8590Sstevel@tonic-gate  */
8600Sstevel@tonic-gate static int
load_parent_drivers(dev_info_t * dip,char * path)8614145Scth load_parent_drivers(dev_info_t *dip, char *path)
8620Sstevel@tonic-gate {
8630Sstevel@tonic-gate 	int	rval = 0;
8647009Scth 	major_t	major = DDI_MAJOR_T_NONE;
8650Sstevel@tonic-gate 	char	*drv;
8664145Scth 	char	*p;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	while (dip) {
8694145Scth 		/* check for path-oriented alias */
8704145Scth 		if (path)
8714145Scth 			major = ddi_name_to_major(path);
8724145Scth 		else
8737009Scth 			major = DDI_MAJOR_T_NONE;
8744145Scth 
8757009Scth 		if (major != DDI_MAJOR_T_NONE)
8764145Scth 			drv = ddi_major_to_name(major);
8774145Scth 		else
8784145Scth 			drv = ddi_binding_name(dip);
8794145Scth 
8800Sstevel@tonic-gate 		if (load_boot_driver(drv) != 0)
8810Sstevel@tonic-gate 			rval = -1;
8824145Scth 
8830Sstevel@tonic-gate 		dip = ddi_get_parent(dip);
8844145Scth 		if (path) {
8854145Scth 			p = strrchr(path, '/');
8864145Scth 			if (p)
8874145Scth 				*p = 0;
8884145Scth 		}
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	return (rval);
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate /*
8960Sstevel@tonic-gate  * For a given path to a boot device,
8970Sstevel@tonic-gate  * load that driver and all its parents.
8980Sstevel@tonic-gate  */
8990Sstevel@tonic-gate static int
load_bootpath_drivers(char * bootpath)9000Sstevel@tonic-gate load_bootpath_drivers(char *bootpath)
9010Sstevel@tonic-gate {
9024145Scth 	dev_info_t	*dip;
9034145Scth 	char		*pathcopy;
9044145Scth 	int		pathcopy_len;
9054145Scth 	int		rval;
9064145Scth 	char		*p;
90710822SJack.Meng@Sun.COM 	int		proplen;
90810822SJack.Meng@Sun.COM 	char		iscsi_network_path[BO_MAXOBJNAME];
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	if (bootpath == NULL || *bootpath == 0)
9110Sstevel@tonic-gate 		return (-1);
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
91410822SJack.Meng@Sun.COM #ifdef _OBP
91510822SJack.Meng@Sun.COM 	if (netboot_over_iscsi()) {
91610822SJack.Meng@Sun.COM 		/* iscsi boot */
91710822SJack.Meng@Sun.COM 		if (root_is_ramdisk) {
91810905SJack.Meng@Sun.COM 			if (modloadonly("drv", "ramdisk") < 0)
91910905SJack.Meng@Sun.COM 				return (-1);
92010822SJack.Meng@Sun.COM 		}
92110822SJack.Meng@Sun.COM 		proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
92210822SJack.Meng@Sun.COM 		if (proplen > 0) {
92310822SJack.Meng@Sun.COM 			if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
92410822SJack.Meng@Sun.COM 			    iscsi_network_path) > 0) {
92510822SJack.Meng@Sun.COM 				p = strchr(iscsi_network_path, ':');
92610822SJack.Meng@Sun.COM 				if (p != NULL) {
92710822SJack.Meng@Sun.COM 					*p = '\0';
92810822SJack.Meng@Sun.COM 				}
92910822SJack.Meng@Sun.COM 				pathcopy = i_ddi_strdup(iscsi_network_path,
93010822SJack.Meng@Sun.COM 				    KM_SLEEP);
93110822SJack.Meng@Sun.COM 				pathcopy_len = strlen(pathcopy) + 1;
93210822SJack.Meng@Sun.COM 			} else {
93310822SJack.Meng@Sun.COM 				return (-1);
93410822SJack.Meng@Sun.COM 			}
93510822SJack.Meng@Sun.COM 		} else {
93610822SJack.Meng@Sun.COM 			return (-1);
93710822SJack.Meng@Sun.COM 		}
93810822SJack.Meng@Sun.COM 	} else {
93910822SJack.Meng@Sun.COM #endif
94010822SJack.Meng@Sun.COM 		pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
94110822SJack.Meng@Sun.COM 		pathcopy_len = strlen(pathcopy) + 1;
94210822SJack.Meng@Sun.COM #ifdef _OBP
94310822SJack.Meng@Sun.COM 	}
94410822SJack.Meng@Sun.COM #endif
9454145Scth 	dip = path_to_devinfo(pathcopy);
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
9480Sstevel@tonic-gate 	/*
9490Sstevel@tonic-gate 	 * i386 does not provide stub nodes for all boot devices,
9500Sstevel@tonic-gate 	 * but we should be able to find the node for the parent,
9510Sstevel@tonic-gate 	 * and the leaf of the boot path should be the driver name,
9520Sstevel@tonic-gate 	 * which we go ahead and load here.
9530Sstevel@tonic-gate 	 */
9540Sstevel@tonic-gate 	if (dip == NULL) {
9554145Scth 		char	*leaf;
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 		/*
9584145Scth 		 * Find last slash to build the full path to the
9594145Scth 		 * parent of the leaf boot device
9600Sstevel@tonic-gate 		 */
9614145Scth 		p = strrchr(pathcopy, '/');
9620Sstevel@tonic-gate 		*p++ = 0;
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		/*
9650Sstevel@tonic-gate 		 * Now isolate the driver name of the leaf device
9660Sstevel@tonic-gate 		 */
9674145Scth 		leaf = p;
9684145Scth 		p = strchr(leaf, '@');
9690Sstevel@tonic-gate 		*p = 0;
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 		BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
9724851Scth 		    bootpath, leaf));
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 		dip = path_to_devinfo(pathcopy);
9754145Scth 		if (leaf) {
9764145Scth 			rval = load_boot_driver(leaf, NULL);
9774145Scth 			if (rval == -1) {
9784145Scth 				kmem_free(pathcopy, pathcopy_len);
9794145Scth 				return (NULL);
9804145Scth 			}
9814145Scth 		}
9820Sstevel@tonic-gate 	}
9830Sstevel@tonic-gate #endif
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 	if (dip == NULL) {
9860Sstevel@tonic-gate 		cmn_err(CE_WARN, "can't bind driver for boot path <%s>",
9874851Scth 		    bootpath);
9884145Scth 		kmem_free(pathcopy, pathcopy_len);
9890Sstevel@tonic-gate 		return (NULL);
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate 	/*
9930Sstevel@tonic-gate 	 * Load IP over IB driver when netbooting over IB.
9940Sstevel@tonic-gate 	 * As per IB 1275 binding, IP over IB is represented as
9950Sstevel@tonic-gate 	 * service on the top of the HCA node. So, there is no
9960Sstevel@tonic-gate 	 * PROM node and generic framework cannot pre-load
9970Sstevel@tonic-gate 	 * IP over IB driver based on the bootpath. The following
9980Sstevel@tonic-gate 	 * code preloads IP over IB driver when doing netboot over
9990Sstevel@tonic-gate 	 * InfiniBand.
10000Sstevel@tonic-gate 	 */
10010Sstevel@tonic-gate 	if (netboot_over_ib(bootpath) &&
1002*12163SRamaswamy.Tummala@Sun.COM 	    modloadonly("drv", "ibp") == -1) {
1003*12163SRamaswamy.Tummala@Sun.COM 		cmn_err(CE_CONT, "ibp: cannot load platform driver\n");
10044145Scth 		kmem_free(pathcopy, pathcopy_len);
10050Sstevel@tonic-gate 		return (NULL);
10060Sstevel@tonic-gate 	}
10070Sstevel@tonic-gate 
10086420Svikram 	/*
10096420Svikram 	 * The PROM node for hubs have incomplete compatible
10106420Svikram 	 * properties and therefore do not bind to the hubd driver.
10116420Svikram 	 * As a result load_bootpath_drivers() loads the usb_mid driver
10126420Svikram 	 * for hub nodes rather than the hubd driver. This causes
10136420Svikram 	 * mountroot failures when booting off USB storage. To prevent
10146420Svikram 	 * this, if we are booting via USB hubs, we preload the hubd driver.
10156420Svikram 	 */
10166420Svikram 	if (strstr(bootpath, "/hub@") && modloadonly("drv", "hubd") == -1) {
10176420Svikram 		cmn_err(CE_WARN, "bootpath contains a USB hub, "
10186420Svikram 		    "but cannot load hubd driver");
10196420Svikram 	}
10206420Svikram 
10214145Scth 	/* get rid of minor node at end of copy (if not already done above) */
10224145Scth 	p = strrchr(pathcopy, '/');
10234145Scth 	if (p) {
10244145Scth 		p = strchr(p, ':');
10254145Scth 		if (p)
10264145Scth 			*p = 0;
10274145Scth 	}
10284145Scth 
10294145Scth 	rval = load_parent_drivers(dip, pathcopy);
10304145Scth 	kmem_free(pathcopy, pathcopy_len);
10314145Scth 	return (rval);
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate /*
10380Sstevel@tonic-gate  * Load drivers required for a platform
10390Sstevel@tonic-gate  * Since all hardware nodes should be available in the device
10400Sstevel@tonic-gate  * tree, walk the per-driver list and load the parents of
10410Sstevel@tonic-gate  * each node found. If not a hardware node, try to load it.
10420Sstevel@tonic-gate  * Pseudo nexus is already loaded.
10430Sstevel@tonic-gate  */
10440Sstevel@tonic-gate static int
load_boot_platform_modules(char * drv)10450Sstevel@tonic-gate load_boot_platform_modules(char *drv)
10460Sstevel@tonic-gate {
10470Sstevel@tonic-gate 	major_t	major;
10480Sstevel@tonic-gate 	dev_info_t *dip;
10490Sstevel@tonic-gate 	char	*drvname;
10500Sstevel@tonic-gate 	int	rval = 0;
10510Sstevel@tonic-gate 
10527009Scth 	if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
10530Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: no major number\n", drv);
10540Sstevel@tonic-gate 		return (-1);
10550Sstevel@tonic-gate 	}
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate 	/*
10580Sstevel@tonic-gate 	 * resolve aliases
10590Sstevel@tonic-gate 	 */
10600Sstevel@tonic-gate 	drvname = ddi_major_to_name(major);
10617009Scth 	if ((major = ddi_name_to_major(drvname)) == DDI_MAJOR_T_NONE)
10620Sstevel@tonic-gate 		return (-1);
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate #ifdef	DEBUG
10650Sstevel@tonic-gate 	if (strcmp(drv, drvname) == 0) {
10660Sstevel@tonic-gate 		BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
10670Sstevel@tonic-gate 	} else {
10680Sstevel@tonic-gate 		BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
10694851Scth 		    drv, drvname));
10700Sstevel@tonic-gate 	}
10710Sstevel@tonic-gate #endif	/* DEBUG */
10720Sstevel@tonic-gate 
10730Sstevel@tonic-gate 	dip = devnamesp[major].dn_head;
10740Sstevel@tonic-gate 	if (dip == NULL) {
10750Sstevel@tonic-gate 		/* pseudo node, not-enumerated, needs to be loaded */
10760Sstevel@tonic-gate 		if (modloadonly("drv", drvname) == -1) {
10770Sstevel@tonic-gate 			cmn_err(CE_CONT, "%s: cannot load platform driver\n",
10780Sstevel@tonic-gate 			    drvname);
10790Sstevel@tonic-gate 			rval = -1;
10800Sstevel@tonic-gate 		}
10810Sstevel@tonic-gate 	} else {
10820Sstevel@tonic-gate 		while (dip) {
10834145Scth 			if (load_parent_drivers(dip, NULL) != 0)
10840Sstevel@tonic-gate 				rval = -1;
10850Sstevel@tonic-gate 			dip = ddi_get_next(dip);
10860Sstevel@tonic-gate 		}
10870Sstevel@tonic-gate 	}
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	return (rval);
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate /*
10940Sstevel@tonic-gate  * i_find_node: Internal routine used by path_to_devinfo
10950Sstevel@tonic-gate  * to locate a given nodeid in the device tree.
10960Sstevel@tonic-gate  */
10970Sstevel@tonic-gate struct i_path_findnode {
1098789Sahrens 	pnode_t nodeid;
10990Sstevel@tonic-gate 	dev_info_t *dip;
11000Sstevel@tonic-gate };
11010Sstevel@tonic-gate 
11020Sstevel@tonic-gate static int
i_path_find_node(dev_info_t * dev,void * arg)11030Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg)
11040Sstevel@tonic-gate {
11050Sstevel@tonic-gate 	struct i_path_findnode *f = (struct i_path_findnode *)arg;
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 	if (ddi_get_nodeid(dev) == (int)f->nodeid) {
11090Sstevel@tonic-gate 		f->dip = dev;
11100Sstevel@tonic-gate 		return (DDI_WALK_TERMINATE);
11110Sstevel@tonic-gate 	}
11120Sstevel@tonic-gate 	return (DDI_WALK_CONTINUE);
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate /*
11160Sstevel@tonic-gate  * Return the devinfo node to a boot device
11170Sstevel@tonic-gate  */
11180Sstevel@tonic-gate static dev_info_t *
path_to_devinfo(char * path)11190Sstevel@tonic-gate path_to_devinfo(char *path)
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate 	struct i_path_findnode fn;
11220Sstevel@tonic-gate 	extern dev_info_t *top_devinfo;
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 	/*
11250Sstevel@tonic-gate 	 * Get the nodeid of the given pathname, if such a mapping exists.
11260Sstevel@tonic-gate 	 */
11270Sstevel@tonic-gate 	fn.dip = NULL;
11280Sstevel@tonic-gate 	fn.nodeid = prom_finddevice(path);
11290Sstevel@tonic-gate 	if (fn.nodeid != OBP_BADNODE) {
11300Sstevel@tonic-gate 		/*
11310Sstevel@tonic-gate 		 * Find the nodeid in our copy of the device tree and return
11320Sstevel@tonic-gate 		 * whatever name we used to bind this node to a driver.
11330Sstevel@tonic-gate 		 */
11340Sstevel@tonic-gate 		ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
11350Sstevel@tonic-gate 	}
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate #ifdef	DEBUG
11380Sstevel@tonic-gate 	/*
11390Sstevel@tonic-gate 	 * If we're bound to something other than the nodename,
11400Sstevel@tonic-gate 	 * note that in the message buffer and system log.
11410Sstevel@tonic-gate 	 */
11420Sstevel@tonic-gate 	if (fn.dip) {
11430Sstevel@tonic-gate 		char *p, *q;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 		p = ddi_binding_name(fn.dip);
11460Sstevel@tonic-gate 		q = ddi_node_name(fn.dip);
11470Sstevel@tonic-gate 		if (p && q && (strcmp(p, q) != 0)) {
11480Sstevel@tonic-gate 			BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
11490Sstevel@tonic-gate 			    path, p));
11500Sstevel@tonic-gate 		}
11510Sstevel@tonic-gate 	}
11520Sstevel@tonic-gate #endif	/* DEBUG */
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	return (fn.dip);
11550Sstevel@tonic-gate }
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate /*
11580Sstevel@tonic-gate  * This routine returns B_TRUE if the bootpath corresponds to
11590Sstevel@tonic-gate  * IP over IB driver.
11600Sstevel@tonic-gate  *
11610Sstevel@tonic-gate  * The format of the bootpath for the IP over IB looks like
11620Sstevel@tonic-gate  * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
11630Sstevel@tonic-gate  *
11640Sstevel@tonic-gate  * The minor node portion "port=1,pkey=8001,protocol=ip" represents
11650Sstevel@tonic-gate  * IP over IB driver.
11660Sstevel@tonic-gate  */
11670Sstevel@tonic-gate static boolean_t
netboot_over_ib(char * bootpath)11680Sstevel@tonic-gate netboot_over_ib(char *bootpath)
11690Sstevel@tonic-gate {
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 	char		*temp;
11720Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
1173789Sahrens 	pnode_t		node = prom_finddevice(bootpath);
11740Sstevel@tonic-gate 	int		len;
11750Sstevel@tonic-gate 	char		devicetype[OBP_MAXDRVNAME];
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate 	/* Is this IB node ? */
117810822SJack.Meng@Sun.COM 	if (node == OBP_BADNODE || node == OBP_NONODE) {
117910822SJack.Meng@Sun.COM 		return (B_FALSE);
118010822SJack.Meng@Sun.COM 	}
11810Sstevel@tonic-gate 	len = prom_getproplen(node, OBP_DEVICETYPE);
11820Sstevel@tonic-gate 	if (len <= 1 || len >= OBP_MAXDRVNAME)
11830Sstevel@tonic-gate 		return (B_FALSE);
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	(void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype);
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 	if (strncmp("ib", devicetype, 2) == 0) {
11880Sstevel@tonic-gate 		/* Check for proper IP over IB string */
11890Sstevel@tonic-gate 		if ((temp = strstr(bootpath, ":port=")) != NULL) {
11900Sstevel@tonic-gate 			if ((temp = strstr(temp, ",pkey=")) != NULL)
11910Sstevel@tonic-gate 				if ((temp = strstr(temp,
11920Sstevel@tonic-gate 				    ",protocol=ip")) != NULL) {
11930Sstevel@tonic-gate 					ret = B_TRUE;
11940Sstevel@tonic-gate 				}
11950Sstevel@tonic-gate 		}
11960Sstevel@tonic-gate 	}
11970Sstevel@tonic-gate 	return (ret);
11980Sstevel@tonic-gate }
119910822SJack.Meng@Sun.COM 
120010822SJack.Meng@Sun.COM static boolean_t
netboot_over_iscsi(void)120110822SJack.Meng@Sun.COM netboot_over_iscsi(void)
120210822SJack.Meng@Sun.COM {
120310822SJack.Meng@Sun.COM 	int proplen;
120410822SJack.Meng@Sun.COM 	boolean_t	ret = B_FALSE;
120510822SJack.Meng@Sun.COM 	char	bootpath[OBP_MAXPATHLEN];
120610822SJack.Meng@Sun.COM 
120710822SJack.Meng@Sun.COM 	proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH);
120810822SJack.Meng@Sun.COM 	if (proplen > 0) {
120910822SJack.Meng@Sun.COM 		if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) {
121010822SJack.Meng@Sun.COM 			if (memcmp(bootpath, BP_ISCSI_DISK,
121110822SJack.Meng@Sun.COM 			    strlen(BP_ISCSI_DISK)) == 0) {
121210822SJack.Meng@Sun.COM 				ret = B_TRUE;
121310822SJack.Meng@Sun.COM 			}
121410822SJack.Meng@Sun.COM 		}
121510822SJack.Meng@Sun.COM 	}
121610822SJack.Meng@Sun.COM 	return (ret);
121710822SJack.Meng@Sun.COM }
1218