xref: /titanic_44/usr/src/uts/common/os/swapgeneric.c (revision b5267ad36ebb2cd3897bb277be97efe63d3092cf)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
548aa2e6aSseb  * Common Development and Distribution License (the "License").
648aa2e6aSseb  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
227c478bd9Sstevel@tonic-gate /*
23dedec472SJack Meng  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Configure root, swap and dump devices.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/param.h>
347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
357c478bd9Sstevel@tonic-gate #include <sys/signal.h>
367c478bd9Sstevel@tonic-gate #include <sys/cred.h>
377c478bd9Sstevel@tonic-gate #include <sys/proc.h>
387c478bd9Sstevel@tonic-gate #include <sys/user.h>
397c478bd9Sstevel@tonic-gate #include <sys/conf.h>
407c478bd9Sstevel@tonic-gate #include <sys/buf.h>
417c478bd9Sstevel@tonic-gate #include <sys/systm.h>
427c478bd9Sstevel@tonic-gate #include <sys/vm.h>
437c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
447c478bd9Sstevel@tonic-gate #include <sys/file.h>
457c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
467c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
477c478bd9Sstevel@tonic-gate #include <sys/errno.h>
487c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
497c478bd9Sstevel@tonic-gate #include <sys/uio.h>
507c478bd9Sstevel@tonic-gate #include <sys/open.h>
517c478bd9Sstevel@tonic-gate #include <sys/mount.h>
527c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
537c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
547c478bd9Sstevel@tonic-gate #include <sys/sysconf.h>
557c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
567c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
577c478bd9Sstevel@tonic-gate #include <sys/debug.h>
587c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h>
597c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
607c478bd9Sstevel@tonic-gate #include <sys/socket.h>
617c478bd9Sstevel@tonic-gate #include <net/if.h>
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
647c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
657c478bd9Sstevel@tonic-gate #include <sys/console.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #include <sys/conf.h>
687c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
697c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
707c478bd9Sstevel@tonic-gate #include <sys/hwconf.h>
717c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h>
727c478bd9Sstevel@tonic-gate #include <sys/promif.h>
73dedec472SJack Meng #include <sys/bootprops.h>
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * Local routines
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate static int preload_module(struct sysparam *, void *);
797c478bd9Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t);
807c478bd9Sstevel@tonic-gate static int getphysdev(char *, char *, size_t);
817c478bd9Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath);
827c478bd9Sstevel@tonic-gate static int load_boot_driver(char *drv);
837c478bd9Sstevel@tonic-gate static int load_boot_platform_modules(char *drv);
847c478bd9Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path);
857c478bd9Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath);
86dedec472SJack Meng static boolean_t netboot_over_iscsi(void);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = {
92986fd29aSsetje 	&mod_miscops, "root and swap configuration"
937c478bd9Sstevel@tonic-gate };
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
967c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modlmisc, NULL
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate int
1007c478bd9Sstevel@tonic-gate _init(void)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate int
1067c478bd9Sstevel@tonic-gate _fini(void)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate int
1127c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
117dedec472SJack Meng extern ib_boot_prop_t *iscsiboot_prop;
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * Configure root file system.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate int
1227c478bd9Sstevel@tonic-gate rootconf(void)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate 	int		error;
1257c478bd9Sstevel@tonic-gate 	struct vfssw	*vsw;
1267c478bd9Sstevel@tonic-gate 	extern void pm_init(void);
127dedec472SJack Meng 	int ret = -1;
1287c478bd9Sstevel@tonic-gate 	BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
1297c478bd9Sstevel@tonic-gate 	BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
1307c478bd9Sstevel@tonic-gate 	BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
1317c478bd9Sstevel@tonic-gate 	BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	/*
1347c478bd9Sstevel@tonic-gate 	 * Install cluster modules that were only loaded during
1357c478bd9Sstevel@tonic-gate 	 * loadrootmodules().
1367c478bd9Sstevel@tonic-gate 	 */
1377c478bd9Sstevel@tonic-gate 	if (error = clboot_rootconf())
1387c478bd9Sstevel@tonic-gate 		return (error);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	if (root_is_svm) {
1417c478bd9Sstevel@tonic-gate 		(void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 		BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name));
1447c478bd9Sstevel@tonic-gate 		BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath));
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/*
1487c478bd9Sstevel@tonic-gate 	 * Run _init on the root filesystem (we already loaded it
1497c478bd9Sstevel@tonic-gate 	 * but we've been waiting until now to _init it) which will
1507c478bd9Sstevel@tonic-gate 	 * have the side-effect of running vsw_init() on this vfs.
1517c478bd9Sstevel@tonic-gate 	 * Because all the nfs filesystems are lumped into one
1527c478bd9Sstevel@tonic-gate 	 * module we need to special case it.
1537c478bd9Sstevel@tonic-gate 	 */
1547c478bd9Sstevel@tonic-gate 	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
1557c478bd9Sstevel@tonic-gate 		if (modload("fs", "nfs") == -1) {
1567c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1577c478bd9Sstevel@tonic-gate 			    rootfs.bo_fstype);
1587c478bd9Sstevel@tonic-gate 			return (ENXIO);
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 	} else {
1617c478bd9Sstevel@tonic-gate 		if (modload("fs", rootfs.bo_fstype) == -1) {
1627c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1637c478bd9Sstevel@tonic-gate 			    rootfs.bo_fstype);
1647c478bd9Sstevel@tonic-gate 			return (ENXIO);
1657c478bd9Sstevel@tonic-gate 		}
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	RLOCK_VFSSW();
1687c478bd9Sstevel@tonic-gate 	vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
1697c478bd9Sstevel@tonic-gate 	RUNLOCK_VFSSW();
17056c0b1daSPavel Filipensky 	if (vsw == NULL) {
17156c0b1daSPavel Filipensky 		cmn_err(CE_CONT, "Cannot find %s filesystem\n",
17256c0b1daSPavel Filipensky 		    rootfs.bo_fstype);
17356c0b1daSPavel Filipensky 		return (ENXIO);
17456c0b1daSPavel Filipensky 	}
1757c478bd9Sstevel@tonic-gate 	VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
1767c478bd9Sstevel@tonic-gate 	VFS_HOLD(rootvfs);
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	if (root_is_svm) {
1797c478bd9Sstevel@tonic-gate 		rootvfs->vfs_flag |= VFS_RDONLY;
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/*
1837c478bd9Sstevel@tonic-gate 	 * This pm-releated call has to occur before root is mounted since we
1847c478bd9Sstevel@tonic-gate 	 * need to power up all devices.  It is placed after VFS_INIT() such
1857c478bd9Sstevel@tonic-gate 	 * that opening a device via ddi_lyr_ interface just before root has
1867c478bd9Sstevel@tonic-gate 	 * been mounted would work.
1877c478bd9Sstevel@tonic-gate 	 */
1887c478bd9Sstevel@tonic-gate 	pm_init();
1897c478bd9Sstevel@tonic-gate 
190dedec472SJack Meng 	if (netboot && iscsiboot_prop) {
191dedec472SJack Meng 		cmn_err(CE_WARN, "NFS boot and iSCSI boot"
192dedec472SJack Meng 		    " shouldn't happen in the same time");
193dedec472SJack Meng 		return (EINVAL);
194dedec472SJack Meng 	}
195dedec472SJack Meng 
196dedec472SJack Meng 	if (netboot || iscsiboot_prop) {
197dedec472SJack Meng 		ret = strplumb();
198dedec472SJack Meng 		if (ret != 0) {
199dedec472SJack Meng 			cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
200dedec472SJack Meng 			return (EFAULT);
201dedec472SJack Meng 		}
202dedec472SJack Meng 	}
203dedec472SJack Meng 
204dedec472SJack Meng 	if ((ret == 0) && iscsiboot_prop) {
205dedec472SJack Meng 		ret = modload("drv", "iscsi");
206dedec472SJack Meng 		/* -1 indicates fail */
207dedec472SJack Meng 		if (ret == -1) {
208dedec472SJack Meng 			cmn_err(CE_WARN, "Failed to load iscsi module");
209dedec472SJack Meng 			iscsi_boot_prop_free();
210dedec472SJack Meng 			return (EINVAL);
211dedec472SJack Meng 		} else {
212dedec472SJack Meng 			if (!i_ddi_attach_pseudo_node("iscsi")) {
213dedec472SJack Meng 				cmn_err(CE_WARN,
214dedec472SJack Meng 				    "Failed to attach iscsi driver");
215dedec472SJack Meng 				iscsi_boot_prop_free();
216dedec472SJack Meng 				return (ENODEV);
217dedec472SJack Meng 			}
2187c478bd9Sstevel@tonic-gate 		}
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/*
2227c478bd9Sstevel@tonic-gate 	 * ufs_mountroot() ends up calling getrootdev()
2237c478bd9Sstevel@tonic-gate 	 * (below) which actually triggers the _init, identify,
2247c478bd9Sstevel@tonic-gate 	 * probe and attach of the drivers that make up root device
2257c478bd9Sstevel@tonic-gate 	 * bush; these are also quietly waiting in memory.
2267c478bd9Sstevel@tonic-gate 	 */
2277c478bd9Sstevel@tonic-gate 	BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
2307c478bd9Sstevel@tonic-gate 	vfs_unrefvfssw(vsw);
2317c478bd9Sstevel@tonic-gate 	rootdev = rootvfs->vfs_dev;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (error)
2347c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
2357c478bd9Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2367c478bd9Sstevel@tonic-gate 	else
2377c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "?root on %s fstype %s\n",
2387c478bd9Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2397c478bd9Sstevel@tonic-gate 	return (error);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate  * Remount root on an SVM mirror root device
2447c478bd9Sstevel@tonic-gate  * Only supported on UFS filesystems at present
2457c478bd9Sstevel@tonic-gate  */
2467c478bd9Sstevel@tonic-gate int
2477c478bd9Sstevel@tonic-gate svm_rootconf(void)
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate 	int	error;
2507c478bd9Sstevel@tonic-gate 	extern int ufs_remountroot(struct vfs *vfsp);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	ASSERT(root_is_svm == 1);
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	if (strcmp(rootfs.bo_fstype, "ufs") != 0) {
2557c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Mounting root on %s with filesystem "
2567c478bd9Sstevel@tonic-gate 		    "type %s is not supported\n",
2577c478bd9Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2587c478bd9Sstevel@tonic-gate 		return (EINVAL);
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	(void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name));
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	error = ufs_remountroot(rootvfs);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if (error) {
2687c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n",
2697c478bd9Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2707c478bd9Sstevel@tonic-gate 	} else {
2717c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "?root remounted on %s fstype %s\n",
2727c478bd9Sstevel@tonic-gate 		    rootfs.bo_name, rootfs.bo_fstype);
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 	return (error);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate  * Under the assumption that our root file system is on a
2797c478bd9Sstevel@tonic-gate  * disk partition, get the dev_t of the partition in question.
2807c478bd9Sstevel@tonic-gate  *
2817c478bd9Sstevel@tonic-gate  * By now, boot has faithfully loaded all our modules into memory, and
2827c478bd9Sstevel@tonic-gate  * we've taken over resource management.  Before we go any further, we
2837c478bd9Sstevel@tonic-gate  * have to fire up the device drivers and stuff we need to mount the
2847c478bd9Sstevel@tonic-gate  * root filesystem.  That's what we do here.  Fingers crossed.
2857c478bd9Sstevel@tonic-gate  */
2867c478bd9Sstevel@tonic-gate dev_t
2877c478bd9Sstevel@tonic-gate getrootdev(void)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	dev_t	d;
2907c478bd9Sstevel@tonic-gate 
291dedec472SJack Meng 	d = ddi_pathname_to_dev_t(rootfs.bo_name);
292dedec472SJack Meng 	if ((d == NODEV) && (iscsiboot_prop != NULL)) {
293dedec472SJack Meng 		/* Give it another try with the 'disk' path */
294dedec472SJack Meng 		get_iscsi_bootpath_phy(rootfs.bo_name);
295dedec472SJack Meng 		d = ddi_pathname_to_dev_t(rootfs.bo_name);
296dedec472SJack Meng 	}
297dedec472SJack Meng 	if (d == NODEV)
2987c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
2997c478bd9Sstevel@tonic-gate 		    rootfs.bo_name);
3007c478bd9Sstevel@tonic-gate 	return (d);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate  * If booted with ASKNAME, prompt on the console for a filesystem
3057c478bd9Sstevel@tonic-gate  * name and return it.
3067c478bd9Sstevel@tonic-gate  */
3077c478bd9Sstevel@tonic-gate void
3087c478bd9Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
3117c478bd9Sstevel@tonic-gate 		printf("%s name: ", askfor);
3127c478bd9Sstevel@tonic-gate 		console_gets(name, namelen);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
3177c478bd9Sstevel@tonic-gate static int
3187c478bd9Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	static char *wmesg = "forceload of %s failed";
3217c478bd9Sstevel@tonic-gate 	char *name;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	name = sysp->sys_ptr;
3247c478bd9Sstevel@tonic-gate 	BMDPRINTF(("preload_module: %s\n", name));
3257c478bd9Sstevel@tonic-gate 	if (modloadonly(NULL, name) < 0)
3267c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, wmesg, name);
3277c478bd9Sstevel@tonic-gate 	return (0);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate  * We want to load all the modules needed to mount the root filesystem,
3337c478bd9Sstevel@tonic-gate  * so that when we start the ball rolling in 'getrootdev', every module
3347c478bd9Sstevel@tonic-gate  * should already be in memory, just waiting to be init-ed.
3357c478bd9Sstevel@tonic-gate  */
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate int
3387c478bd9Sstevel@tonic-gate loadrootmodules(void)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate 	struct vfssw	*vsw;
3417c478bd9Sstevel@tonic-gate 	char		*this;
3427c478bd9Sstevel@tonic-gate 	char		*name;
3437c478bd9Sstevel@tonic-gate 	int		err;
3447c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
345986fd29aSsetje 	int		i, proplen;
3467c478bd9Sstevel@tonic-gate 	extern char	*impl_module_list[];
3477c478bd9Sstevel@tonic-gate 	extern char	*platform_module_list[];
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	/* Make sure that the PROM's devinfo tree has been created */
3507c478bd9Sstevel@tonic-gate 	ASSERT(ddi_root_node());
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
3537c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
3547c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * zzz We need to honor what's in rootfs if it's not null.
3587c478bd9Sstevel@tonic-gate 	 * non-null means use what's there.  This way we can
3597c478bd9Sstevel@tonic-gate 	 * change rootfs with /etc/system AND with tunetool.
3607c478bd9Sstevel@tonic-gate 	 */
3617c478bd9Sstevel@tonic-gate 	if (root_is_svm) {
3627c478bd9Sstevel@tonic-gate 		/* user replaced rootdev, record obp_bootpath */
3637c478bd9Sstevel@tonic-gate 		obp_bootpath[0] = '\0';
3647c478bd9Sstevel@tonic-gate 		(void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME);
3657c478bd9Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
3667c478bd9Sstevel@tonic-gate 	} else {
3677c478bd9Sstevel@tonic-gate 		/*
3687c478bd9Sstevel@tonic-gate 		 * Get the root fstype and root device path from boot.
3697c478bd9Sstevel@tonic-gate 		 */
3707c478bd9Sstevel@tonic-gate 		rootfs.bo_fstype[0] = '\0';
3717c478bd9Sstevel@tonic-gate 		rootfs.bo_name[0] = '\0';
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	/*
3757c478bd9Sstevel@tonic-gate 	 * This lookup will result in modloadonly-ing the root
3767c478bd9Sstevel@tonic-gate 	 * filesystem module - it gets _init-ed in rootconf()
3777c478bd9Sstevel@tonic-gate 	 */
3787c478bd9Sstevel@tonic-gate 	if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
3797c478bd9Sstevel@tonic-gate 		return (ENXIO);	/* in case we have no file system types */
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	(void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	vfs_unrefvfssw(vsw);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/*
3867c478bd9Sstevel@tonic-gate 	 * Load the favored drivers of the implementation.
3877c478bd9Sstevel@tonic-gate 	 * e.g. 'sbus' and possibly 'zs' (even).
3887c478bd9Sstevel@tonic-gate 	 *
3897c478bd9Sstevel@tonic-gate 	 * Called whilst boot is still loaded (because boot does
3907c478bd9Sstevel@tonic-gate 	 * the i/o for us), and DDI services are unavailable.
3917c478bd9Sstevel@tonic-gate 	 */
3927c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: impl_module_list\n"));
3937c478bd9Sstevel@tonic-gate 	for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
3947c478bd9Sstevel@tonic-gate 		if ((err = load_boot_driver(this)) != 0) {
3957c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "Cannot load drv/%s", this);
3967c478bd9Sstevel@tonic-gate 			return (err);
3977c478bd9Sstevel@tonic-gate 		}
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 	/*
4007c478bd9Sstevel@tonic-gate 	 * Now load the platform modules (if any)
4017c478bd9Sstevel@tonic-gate 	 */
4027c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: platform_module_list\n"));
4037c478bd9Sstevel@tonic-gate 	for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
4047c478bd9Sstevel@tonic-gate 		if ((err = load_boot_platform_modules(this)) != 0) {
4057c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "Cannot load drv/%s", this);
4067c478bd9Sstevel@tonic-gate 			return (err);
4077c478bd9Sstevel@tonic-gate 		}
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate loop:
4117c478bd9Sstevel@tonic-gate 	(void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
4127c478bd9Sstevel@tonic-gate 	/*
4137c478bd9Sstevel@tonic-gate 	 * Given a physical pathname, load the correct set of driver
4147c478bd9Sstevel@tonic-gate 	 * modules into memory, including all possible parents.
4157c478bd9Sstevel@tonic-gate 	 *
4167c478bd9Sstevel@tonic-gate 	 * NB: The code sets the variable 'name' for error reporting.
4177c478bd9Sstevel@tonic-gate 	 */
4187c478bd9Sstevel@tonic-gate 	err = 0;
4197c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
4207c478bd9Sstevel@tonic-gate 	if (root_is_svm == 0) {
4217c478bd9Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
4227c478bd9Sstevel@tonic-gate 		name = rootfs.bo_name;
4237c478bd9Sstevel@tonic-gate 		err = load_bootpath_drivers(rootfs.bo_name);
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	/*
4277c478bd9Sstevel@tonic-gate 	 * Load driver modules in obp_bootpath, this is always
4287c478bd9Sstevel@tonic-gate 	 * required for mountroot to succeed. obp_bootpath is
4297c478bd9Sstevel@tonic-gate 	 * is set if rootdev is set via /etc/system, which is
4307c478bd9Sstevel@tonic-gate 	 * the case if booting of a SVM/VxVM mirror.
4317c478bd9Sstevel@tonic-gate 	 */
4327c478bd9Sstevel@tonic-gate 	if ((err == 0) && obp_bootpath[0] != '\0') {
4337c478bd9Sstevel@tonic-gate 		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
4347c478bd9Sstevel@tonic-gate 		name = obp_bootpath;
4357c478bd9Sstevel@tonic-gate 		err = load_bootpath_drivers(obp_bootpath);
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	if (err != 0) {
4397c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
4407c478bd9Sstevel@tonic-gate 		goto out;
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	/*
4447c478bd9Sstevel@tonic-gate 	 * Check to see if the booter performed DHCP configuration
4457c478bd9Sstevel@tonic-gate 	 * ("bootp-response" boot property exists). If so, then before
4467c478bd9Sstevel@tonic-gate 	 * bootops disappears we need to save the value of this property
4477c478bd9Sstevel@tonic-gate 	 * such that the userland dhcpagent can adopt the DHCP management
448986fd29aSsetje 	 * of our primary network interface.
4497c478bd9Sstevel@tonic-gate 	 */
4507c478bd9Sstevel@tonic-gate 	proplen = BOP_GETPROPLEN(bootops, "bootp-response");
4517c478bd9Sstevel@tonic-gate 	if (proplen > 0) {
452986fd29aSsetje 		dhcack = kmem_zalloc(proplen, KM_SLEEP);
453986fd29aSsetje 		if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) {
4547c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "BOP_GETPROP of  "
4557c478bd9Sstevel@tonic-gate 			    "\"bootp-response\" failed\n");
4567c478bd9Sstevel@tonic-gate 			kmem_free(dhcack, dhcacklen);
4577c478bd9Sstevel@tonic-gate 			dhcack = NULL;
4587c478bd9Sstevel@tonic-gate 			goto out;
4597c478bd9Sstevel@tonic-gate 		}
460986fd29aSsetje 		dhcacklen = proplen;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		/*
4637c478bd9Sstevel@tonic-gate 		 * Fetch the "netdev-path" boot property (if it exists), and
4647c478bd9Sstevel@tonic-gate 		 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 		proplen = BOP_GETPROPLEN(bootops, "netdev-path");
4677c478bd9Sstevel@tonic-gate 		if (proplen > 0) {
4687c478bd9Sstevel@tonic-gate 			netdev_path = kmem_zalloc(proplen, KM_SLEEP);
4697c478bd9Sstevel@tonic-gate 			if (BOP_GETPROP(bootops, "netdev-path",
4707c478bd9Sstevel@tonic-gate 			    (uchar_t *)netdev_path) == -1) {
4717c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "BOP_GETPROP of  "
4727c478bd9Sstevel@tonic-gate 				    "\"netdev-path\" failed\n");
4737c478bd9Sstevel@tonic-gate 				kmem_free(netdev_path, proplen);
4747c478bd9Sstevel@tonic-gate 				goto out;
4757c478bd9Sstevel@tonic-gate 			}
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	/*
4807c478bd9Sstevel@tonic-gate 	 * Preload (load-only, no init) all modules which
4817c478bd9Sstevel@tonic-gate 	 * were added to the /etc/system file with the
4827c478bd9Sstevel@tonic-gate 	 * FORCELOAD keyword.
4837c478bd9Sstevel@tonic-gate 	 */
4847c478bd9Sstevel@tonic-gate 	BMDPRINTF(("loadrootmodules: preload_module\n"));
4857c478bd9Sstevel@tonic-gate 	(void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
4887c478bd9Sstevel@tonic-gate 	/*
4897c478bd9Sstevel@tonic-gate 	 * If we booted otw then load in the plumbing
4907c478bd9Sstevel@tonic-gate 	 * routine now while we still can. If we didn't
4917c478bd9Sstevel@tonic-gate 	 * boot otw then we will load strplumb in main().
4927c478bd9Sstevel@tonic-gate 	 *
4937c478bd9Sstevel@tonic-gate 	 * NFS is actually a set of modules, the core routines,
4947c478bd9Sstevel@tonic-gate 	 * a diskless helper module, rpcmod, and the tli interface.  Load
4957c478bd9Sstevel@tonic-gate 	 * them now while we still can.
4967c478bd9Sstevel@tonic-gate 	 *
4977c478bd9Sstevel@tonic-gate 	 * Because we glomb all versions of nfs into a single module
4987c478bd9Sstevel@tonic-gate 	 * we check based on the initial string "nfs".
4997c478bd9Sstevel@tonic-gate 	 *
5007c478bd9Sstevel@tonic-gate 	 * XXX: A better test for this is to see if device_type
5017c478bd9Sstevel@tonic-gate 	 * XXX: from the PROM is "network".
5027c478bd9Sstevel@tonic-gate 	 */
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
5057c478bd9Sstevel@tonic-gate 		++netboot;
5067c478bd9Sstevel@tonic-gate 
507d62bc4baSyz147064 		/*
508d62bc4baSyz147064 		 * Preload (load-only, no init) the dacf module. We cannot
509d62bc4baSyz147064 		 * init the module because one of its requisite modules is
510d62bc4baSyz147064 		 * dld whose _init function will call taskq_create(), which
511d62bc4baSyz147064 		 * will panic the system at this point.
512d62bc4baSyz147064 		 */
513d62bc4baSyz147064 		if ((err = modloadonly("dacf", "net_dacf")) < 0)  {
514d62bc4baSyz147064 			cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
515d62bc4baSyz147064 			goto out;
516d62bc4baSyz147064 		}
5177c478bd9Sstevel@tonic-gate 		if ((err = modload("misc", "tlimod")) < 0)  {
5187c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
5197c478bd9Sstevel@tonic-gate 			goto out;
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 		if ((err = modload("strmod", "rpcmod")) < 0)  {
5227c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
5237c478bd9Sstevel@tonic-gate 			goto out;
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 		if ((err = modload("misc", "nfs_dlboot")) < 0)  {
5267c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
5277c478bd9Sstevel@tonic-gate 			goto out;
5287c478bd9Sstevel@tonic-gate 		}
52948aa2e6aSseb 		if ((err = modload("mac", "mac_ether")) < 0)  {
53048aa2e6aSseb 			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
53148aa2e6aSseb 			goto out;
53248aa2e6aSseb 		}
5337c478bd9Sstevel@tonic-gate 		if ((err = modload("misc", "strplumb")) < 0)  {
5347c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
5357c478bd9Sstevel@tonic-gate 			goto out;
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 		if ((err = strplumb_load()) < 0) {
5387c478bd9Sstevel@tonic-gate 			goto out;
5397c478bd9Sstevel@tonic-gate 		}
5407c478bd9Sstevel@tonic-gate 	}
541dedec472SJack Meng 	if (netboot_over_iscsi() == B_TRUE) {
542dedec472SJack Meng 		/* iscsi boot */
543dedec472SJack Meng 		if ((err = modloadonly("dacf", "net_dacf")) < 0) {
544dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
545dedec472SJack Meng 			goto out;
546dedec472SJack Meng 		}
547dedec472SJack Meng 		if ((err = modload("misc", "tlimod")) < 0) {
548dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
549dedec472SJack Meng 			goto out;
550dedec472SJack Meng 		}
551dedec472SJack Meng 		if ((err = modload("mac", "mac_ether")) < 0) {
552dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
553dedec472SJack Meng 			goto out;
554dedec472SJack Meng 		}
555dedec472SJack Meng 		if ((err = modloadonly("drv", "iscsi")) < 0) {
556dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load drv/iscsi\n");
557dedec472SJack Meng 			goto out;
558dedec472SJack Meng 		}
559dedec472SJack Meng 		if ((err = modloadonly("drv", "ssd")) < 0) {
560dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load drv/ssd\n");
561dedec472SJack Meng 			goto out;
562dedec472SJack Meng 		}
563dedec472SJack Meng 		if ((err = modloadonly("drv", "sd")) < 0) {
564dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load drv/sd\n");
565dedec472SJack Meng 			goto out;
566dedec472SJack Meng 		}
567dedec472SJack Meng 		if ((err = modload("misc", "strplumb")) < 0) {
568dedec472SJack Meng 			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
569dedec472SJack Meng 			goto out;
570dedec472SJack Meng 		}
571dedec472SJack Meng 		if ((err = strplumb_load()) < 0) {
572dedec472SJack Meng 			goto out;
573dedec472SJack Meng 		}
574dedec472SJack Meng 	}
5757c478bd9Sstevel@tonic-gate 	/*
5767c478bd9Sstevel@tonic-gate 	 * Preload modules needed for booting as a cluster.
5777c478bd9Sstevel@tonic-gate 	 */
5787c478bd9Sstevel@tonic-gate 	err = clboot_loadrootmodules();
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate out:
5817c478bd9Sstevel@tonic-gate 	if (err != 0 && (boothowto & RB_ASKNAME))
5827c478bd9Sstevel@tonic-gate 		goto loop;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	return (err);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
5877c478bd9Sstevel@tonic-gate 
588986fd29aSsetje static int
589986fd29aSsetje get_bootpath_prop(char *bootpath)
590986fd29aSsetje {
591986fd29aSsetje 	if (root_is_ramdisk) {
592986fd29aSsetje 		if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1)
593986fd29aSsetje 			return (-1);
594986fd29aSsetje 		(void) strlcat(bootpath, ":a", BO_MAXOBJNAME);
595986fd29aSsetje 	} else {
596986fd29aSsetje 		/*
597986fd29aSsetje 		 * Look for the 1275 compliant name 'bootpath' first,
598986fd29aSsetje 		 * but make certain it has a non-NULL value as well.
599986fd29aSsetje 		 */
600986fd29aSsetje 		if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) ||
601986fd29aSsetje 		    strlen(bootpath) == 0) {
602986fd29aSsetje 			if (BOP_GETPROP(bootops,
603986fd29aSsetje 			    "boot-path", bootpath) == -1)
604986fd29aSsetje 				return (-1);
605986fd29aSsetje 		}
606dedec472SJack Meng 		if (memcmp(bootpath, BP_ISCSI_DISK,
607dedec472SJack Meng 		    strlen(BP_ISCSI_DISK)) == 0) {
608dedec472SJack Meng 			/* iscsi boot */
609dedec472SJack Meng 			get_iscsi_bootpath_vhci(bootpath);
610dedec472SJack Meng 		}
611986fd29aSsetje 	}
612986fd29aSsetje 	return (0);
613986fd29aSsetje }
614986fd29aSsetje 
615986fd29aSsetje static int
616986fd29aSsetje get_fstype_prop(char *fstype)
617986fd29aSsetje {
618986fd29aSsetje 	char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype";
619986fd29aSsetje 
620986fd29aSsetje 	return (BOP_GETPROP(bootops, prop, fstype));
621986fd29aSsetje }
622986fd29aSsetje 
6237c478bd9Sstevel@tonic-gate /*
6247c478bd9Sstevel@tonic-gate  * Get the name of the root or swap filesystem type, and return
6257c478bd9Sstevel@tonic-gate  * the corresponding entry in the vfs switch.
6267c478bd9Sstevel@tonic-gate  *
6277c478bd9Sstevel@tonic-gate  * If we're not asking the user, and we're trying to find the
6287c478bd9Sstevel@tonic-gate  * root filesystem type, we ask boot for the filesystem
6297c478bd9Sstevel@tonic-gate  * type that it came from and use that.  Similarly, if we're
6307c478bd9Sstevel@tonic-gate  * trying to find the swap filesystem, we try and derive it from
6317c478bd9Sstevel@tonic-gate  * the root filesystem type.
6327c478bd9Sstevel@tonic-gate  *
6337c478bd9Sstevel@tonic-gate  * If we are booting via NFS we currently have these options:
6347c478bd9Sstevel@tonic-gate  *	nfs -	dynamically choose NFS V2. V3, or V4 (default)
6357c478bd9Sstevel@tonic-gate  *	nfs2 -	force NFS V2
6367c478bd9Sstevel@tonic-gate  *	nfs3 -	force NFS V3
6377c478bd9Sstevel@tonic-gate  *	nfs4 -	force NFS V4
6387c478bd9Sstevel@tonic-gate  * Because we need to maintain backward compatibility with the naming
6397c478bd9Sstevel@tonic-gate  * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
6407c478bd9Sstevel@tonic-gate  * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs".  The dynamic
6417c478bd9Sstevel@tonic-gate  * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
6427c478bd9Sstevel@tonic-gate  * This is only for root filesystems, all other uses such as cachefs
6437c478bd9Sstevel@tonic-gate  * will expect that "nfs" == NFS V2.
6447c478bd9Sstevel@tonic-gate  *
6457c478bd9Sstevel@tonic-gate  * If the filesystem isn't already loaded, vfs_getvfssw() will load
6467c478bd9Sstevel@tonic-gate  * it for us, but if (at the time we call it) modrootloaded is
6477c478bd9Sstevel@tonic-gate  * still not set, it won't run the filesystems _init routine (and
6487c478bd9Sstevel@tonic-gate  * implicitly it won't run the filesystems vsw_init() entry either).
6497c478bd9Sstevel@tonic-gate  * We do that explicitly in rootconf().
6507c478bd9Sstevel@tonic-gate  */
6517c478bd9Sstevel@tonic-gate static struct vfssw *
6527c478bd9Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen)
6537c478bd9Sstevel@tonic-gate {
6547c478bd9Sstevel@tonic-gate 	struct vfssw *vsw;
6557c478bd9Sstevel@tonic-gate 	static char defaultfs[BO_MAXFSNAME];
6567c478bd9Sstevel@tonic-gate 	int root = 0;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	if (strcmp(askfor, "root") == 0) {
659986fd29aSsetje 		(void) get_fstype_prop(defaultfs);
6607c478bd9Sstevel@tonic-gate 		root++;
6617c478bd9Sstevel@tonic-gate 	} else {
6627c478bd9Sstevel@tonic-gate 		(void) strcpy(defaultfs, "swapfs");
6637c478bd9Sstevel@tonic-gate 	}
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
6667c478bd9Sstevel@tonic-gate 		for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') {
6677c478bd9Sstevel@tonic-gate 			printf("%s filesystem type [%s]: ", askfor, defaultfs);
6687c478bd9Sstevel@tonic-gate 			console_gets(fsname, fsnamelen);
6697c478bd9Sstevel@tonic-gate 			if (*fsname == '\0')
6707c478bd9Sstevel@tonic-gate 				(void) strcpy(fsname, defaultfs);
6717c478bd9Sstevel@tonic-gate 			if (root) {
6727c478bd9Sstevel@tonic-gate 				if (strcmp(fsname, "nfs2") == 0)
6737c478bd9Sstevel@tonic-gate 					(void) strcpy(fsname, "nfs");
6747c478bd9Sstevel@tonic-gate 				else if (strcmp(fsname, "nfs") == 0)
6757c478bd9Sstevel@tonic-gate 					(void) strcpy(fsname, "nfsdyn");
6767c478bd9Sstevel@tonic-gate 			}
6777c478bd9Sstevel@tonic-gate 			if ((vsw = vfs_getvfssw(fsname)) != NULL)
6787c478bd9Sstevel@tonic-gate 				return (vsw);
6797c478bd9Sstevel@tonic-gate 			printf("Unknown filesystem type '%s'\n", fsname);
6807c478bd9Sstevel@tonic-gate 		}
6817c478bd9Sstevel@tonic-gate 	} else if (*fsname == '\0') {
6827c478bd9Sstevel@tonic-gate 		fsname = defaultfs;
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 	if (*fsname == '\0') {
6857c478bd9Sstevel@tonic-gate 		return (NULL);
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	if (root) {
6897c478bd9Sstevel@tonic-gate 		if (strcmp(fsname, "nfs2") == 0)
6907c478bd9Sstevel@tonic-gate 			(void) strcpy(fsname, "nfs");
6917c478bd9Sstevel@tonic-gate 		else if (strcmp(fsname, "nfs") == 0)
6927c478bd9Sstevel@tonic-gate 			(void) strcpy(fsname, "nfsdyn");
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	return (vfs_getvfssw(fsname));
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  * Get a physical device name, and maybe load and attach
7017c478bd9Sstevel@tonic-gate  * the driver.
7027c478bd9Sstevel@tonic-gate  *
7037c478bd9Sstevel@tonic-gate  * XXX	Need better checking of whether or not a device
7047c478bd9Sstevel@tonic-gate  *	actually exists if the user typed in a pathname.
7057c478bd9Sstevel@tonic-gate  *
7067c478bd9Sstevel@tonic-gate  * XXX	Are we sure we want to expose users to this sort
7077c478bd9Sstevel@tonic-gate  *	of physical namespace gobbledygook (now there's
7087c478bd9Sstevel@tonic-gate  *	a word to conjure with..)
7097c478bd9Sstevel@tonic-gate  *
7107c478bd9Sstevel@tonic-gate  * XXX	Note that on an OBP machine, we can easily ask the
7117c478bd9Sstevel@tonic-gate  *	prom and pretty-print some plausible set of bootable
7127c478bd9Sstevel@tonic-gate  *	devices.  We can also user the prom to verify any
7137c478bd9Sstevel@tonic-gate  *	such device.  Later tim.. later.
7147c478bd9Sstevel@tonic-gate  */
7157c478bd9Sstevel@tonic-gate static int
7167c478bd9Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen)
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate 	static char fmt[] = "Enter physical name of %s device\n[%s]: ";
7197c478bd9Sstevel@tonic-gate 	dev_t dev;
7207c478bd9Sstevel@tonic-gate 	static char defaultpath[BO_MAXOBJNAME];
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	/*
7237c478bd9Sstevel@tonic-gate 	 * Establish 'default' values - we get the root device from
7247c478bd9Sstevel@tonic-gate 	 * boot, and we infer the swap device is the same but with
7257c478bd9Sstevel@tonic-gate 	 * a 'b' on the end instead of an 'a'.  A first stab at
7267c478bd9Sstevel@tonic-gate 	 * ease-of-use ..
7277c478bd9Sstevel@tonic-gate 	 */
7287c478bd9Sstevel@tonic-gate 	if (strcmp(askfor, "root") == 0) {
729986fd29aSsetje 		if (get_bootpath_prop(defaultpath) == -1)
7307c478bd9Sstevel@tonic-gate 			boothowto |= RB_ASKNAME | RB_VERBOSE;
7317c478bd9Sstevel@tonic-gate 	} else {
7327c478bd9Sstevel@tonic-gate 		(void) strcpy(defaultpath, rootfs.bo_name);
7337c478bd9Sstevel@tonic-gate 		defaultpath[strlen(defaultpath) - 1] = 'b';
7347c478bd9Sstevel@tonic-gate 	}
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate retry:
7377c478bd9Sstevel@tonic-gate 	if (boothowto & RB_ASKNAME) {
7387c478bd9Sstevel@tonic-gate 		printf(fmt, askfor, defaultpath);
7397c478bd9Sstevel@tonic-gate 		console_gets(name, namelen);
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 	if (*name == '\0')
7427c478bd9Sstevel@tonic-gate 		(void) strcpy(name, defaultpath);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	if (strcmp(askfor, "swap") == 0)   {
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 		/*
7477c478bd9Sstevel@tonic-gate 		 * Try to load and install the swap device driver.
7487c478bd9Sstevel@tonic-gate 		 */
7497c478bd9Sstevel@tonic-gate 		dev = ddi_pathname_to_dev_t(name);
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 		if (dev == (dev_t)-1)  {
7527c478bd9Sstevel@tonic-gate 			printf("Not a supported device for swap.\n");
7537c478bd9Sstevel@tonic-gate 			boothowto |= RB_ASKNAME | RB_VERBOSE;
7547c478bd9Sstevel@tonic-gate 			goto retry;
7557c478bd9Sstevel@tonic-gate 		}
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 		/*
7587c478bd9Sstevel@tonic-gate 		 * Ensure that we're not trying to swap on the floppy.
7597c478bd9Sstevel@tonic-gate 		 */
7607c478bd9Sstevel@tonic-gate 		if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
7617c478bd9Sstevel@tonic-gate 			printf("Too dangerous to swap on the floppy\n");
7627c478bd9Sstevel@tonic-gate 			if (boothowto & RB_ASKNAME)
7637c478bd9Sstevel@tonic-gate 				goto retry;
7647c478bd9Sstevel@tonic-gate 			return (-1);
7657c478bd9Sstevel@tonic-gate 		}
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	return (0);
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate  * Load a driver needed to boot.
7747c478bd9Sstevel@tonic-gate  */
7757c478bd9Sstevel@tonic-gate static int
7767c478bd9Sstevel@tonic-gate load_boot_driver(char *drv)
7777c478bd9Sstevel@tonic-gate {
7787c478bd9Sstevel@tonic-gate 	char		*drvname;
7797c478bd9Sstevel@tonic-gate 	major_t		major;
7801e1ddd6cScth #ifdef	sparc
7811e1ddd6cScth 	struct devnames *dnp;
7821e1ddd6cScth 	ddi_prop_t	*propp;
7831e1ddd6cScth 	char		*module;
7841e1ddd6cScth 	char		*dir, *mf;
7851e1ddd6cScth 	int		plen;
7861e1ddd6cScth 	int		mlen;
7871e1ddd6cScth #endif	/* sparc */
7887c478bd9Sstevel@tonic-gate 
789a204de77Scth 	if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
7907c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: no major number\n", drv);
7917c478bd9Sstevel@tonic-gate 		return (-1);
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 	/*
7947c478bd9Sstevel@tonic-gate 	 * resolve aliases
7957c478bd9Sstevel@tonic-gate 	 */
7967c478bd9Sstevel@tonic-gate 	drvname = ddi_major_to_name(major);
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7997c478bd9Sstevel@tonic-gate 	if (strcmp(drv, drvname) == 0) {
8007c478bd9Sstevel@tonic-gate 		BMDPRINTF(("load_boot_driver: %s\n", drv));
8017c478bd9Sstevel@tonic-gate 	} else {
8027c478bd9Sstevel@tonic-gate 		BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
8037c478bd9Sstevel@tonic-gate 	}
8047c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	if (modloadonly("drv", drvname) == -1) {
8077c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
8087c478bd9Sstevel@tonic-gate 		return (-1);
8097c478bd9Sstevel@tonic-gate 	}
8107c478bd9Sstevel@tonic-gate 
8111e1ddd6cScth #ifdef	sparc
8121e1ddd6cScth 	/*
8131e1ddd6cScth 	 * NOTE: this can be removed when newboot-sparc is delivered.
8141e1ddd6cScth 	 *
8151e1ddd6cScth 	 * Check to see if the driver had a 'ddi-forceload' global driver.conf
8161e1ddd6cScth 	 * property to identify additional modules that need to be loaded.
8171e1ddd6cScth 	 * The driver still needs to use ddi_modopen() to open these modules,
8181e1ddd6cScth 	 * but the 'ddi-forceload' property allows the modules to be loaded
8191e1ddd6cScth 	 * into memory prior to lights-out, so that driver ddi_modopen()
8201e1ddd6cScth 	 * calls during lights-out (when mounting root) will work correctly.
8211e1ddd6cScth 	 * Use of 'ddi-forceload' is only required for drivers involved in
8221e1ddd6cScth 	 * getting root mounted.
8231e1ddd6cScth 	 */
8241e1ddd6cScth 	dnp = &devnamesp[major];
8251e1ddd6cScth 	if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
8261e1ddd6cScth 	    ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
8271e1ddd6cScth 	    "ddi-forceload", DDI_PROP_TYPE_STRING,
8281e1ddd6cScth 	    &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {
8291e1ddd6cScth 
8301e1ddd6cScth 		module = (char *)propp->prop_val;
8311e1ddd6cScth 		plen = propp->prop_len;
8321e1ddd6cScth 		while (plen > 0) {
8331e1ddd6cScth 			mlen = strlen(module);
8341e1ddd6cScth 			mf = strrchr(module, '/');
8351e1ddd6cScth 			if (mf) {
8361e1ddd6cScth 				dir = module;
8371e1ddd6cScth 				*mf++ = '\0';		/* '/' -> '\0' */
8381e1ddd6cScth 			} else {
8391e1ddd6cScth 				dir = "misc";
8401e1ddd6cScth 				mf = module;
8411e1ddd6cScth 			}
8421e1ddd6cScth 			if (modloadonly(dir, mf) == -1)
8431e1ddd6cScth 				cmn_err(CE_CONT,
8441e1ddd6cScth 				    "misc/%s: can't load module\n", mf);
8451e1ddd6cScth 			if (mf != module)
8461e1ddd6cScth 				*(mf - 1) = '/';	/* '\0' -> '/' */
8471e1ddd6cScth 
8481e1ddd6cScth 			module += mlen + 1;
8491e1ddd6cScth 			plen -= mlen + 1;
8501e1ddd6cScth 		}
8511e1ddd6cScth 	}
8521e1ddd6cScth #endif	/* sparc */
8531e1ddd6cScth 
8547c478bd9Sstevel@tonic-gate 	return (0);
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate /*
8597c478bd9Sstevel@tonic-gate  * For a given instance, load that driver and its parents
8607c478bd9Sstevel@tonic-gate  */
8617c478bd9Sstevel@tonic-gate static int
862f4da9be0Scth load_parent_drivers(dev_info_t *dip, char *path)
8637c478bd9Sstevel@tonic-gate {
8647c478bd9Sstevel@tonic-gate 	int	rval = 0;
865a204de77Scth 	major_t	major = DDI_MAJOR_T_NONE;
8667c478bd9Sstevel@tonic-gate 	char	*drv;
867f4da9be0Scth 	char	*p;
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	while (dip) {
870f4da9be0Scth 		/* check for path-oriented alias */
871f4da9be0Scth 		if (path)
872f4da9be0Scth 			major = ddi_name_to_major(path);
873f4da9be0Scth 		else
874a204de77Scth 			major = DDI_MAJOR_T_NONE;
875f4da9be0Scth 
876a204de77Scth 		if (major != DDI_MAJOR_T_NONE)
877f4da9be0Scth 			drv = ddi_major_to_name(major);
878f4da9be0Scth 		else
879f4da9be0Scth 			drv = ddi_binding_name(dip);
880f4da9be0Scth 
8817c478bd9Sstevel@tonic-gate 		if (load_boot_driver(drv) != 0)
8827c478bd9Sstevel@tonic-gate 			rval = -1;
883f4da9be0Scth 
8847c478bd9Sstevel@tonic-gate 		dip = ddi_get_parent(dip);
885f4da9be0Scth 		if (path) {
886f4da9be0Scth 			p = strrchr(path, '/');
887f4da9be0Scth 			if (p)
888f4da9be0Scth 				*p = 0;
889f4da9be0Scth 		}
8907c478bd9Sstevel@tonic-gate 	}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	return (rval);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate /*
8977c478bd9Sstevel@tonic-gate  * For a given path to a boot device,
8987c478bd9Sstevel@tonic-gate  * load that driver and all its parents.
8997c478bd9Sstevel@tonic-gate  */
9007c478bd9Sstevel@tonic-gate static int
9017c478bd9Sstevel@tonic-gate load_bootpath_drivers(char *bootpath)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate 	dev_info_t	*dip;
904f4da9be0Scth 	char		*pathcopy;
905f4da9be0Scth 	int		pathcopy_len;
906f4da9be0Scth 	int		rval;
907f4da9be0Scth 	char		*p;
908dedec472SJack Meng 	int		proplen;
909dedec472SJack Meng 	char		iscsi_network_path[BO_MAXOBJNAME];
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	if (bootpath == NULL || *bootpath == 0)
9127c478bd9Sstevel@tonic-gate 		return (-1);
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
915dedec472SJack Meng #ifdef _OBP
916dedec472SJack Meng 	if (netboot_over_iscsi()) {
917dedec472SJack Meng 		/* iscsi boot */
918dedec472SJack Meng 		if (root_is_ramdisk) {
919*b5267ad3SJack Meng 			if (modloadonly("drv", "ramdisk") < 0)
920*b5267ad3SJack Meng 				return (-1);
921dedec472SJack Meng 		}
922dedec472SJack Meng 		proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
923dedec472SJack Meng 		if (proplen > 0) {
924dedec472SJack Meng 			if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
925dedec472SJack Meng 			    iscsi_network_path) > 0) {
926dedec472SJack Meng 				p = strchr(iscsi_network_path, ':');
927dedec472SJack Meng 				if (p != NULL) {
928dedec472SJack Meng 					*p = '\0';
929dedec472SJack Meng 				}
930dedec472SJack Meng 				pathcopy = i_ddi_strdup(iscsi_network_path,
931dedec472SJack Meng 				    KM_SLEEP);
932dedec472SJack Meng 				pathcopy_len = strlen(pathcopy) + 1;
933dedec472SJack Meng 			} else {
934dedec472SJack Meng 				return (-1);
935dedec472SJack Meng 			}
936dedec472SJack Meng 		} else {
937dedec472SJack Meng 			return (-1);
938dedec472SJack Meng 		}
939dedec472SJack Meng 	} else {
940dedec472SJack Meng #endif
941f4da9be0Scth 		pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
942f4da9be0Scth 		pathcopy_len = strlen(pathcopy) + 1;
943dedec472SJack Meng #ifdef _OBP
944dedec472SJack Meng 	}
945dedec472SJack Meng #endif
946f4da9be0Scth 	dip = path_to_devinfo(pathcopy);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
9497c478bd9Sstevel@tonic-gate 	/*
9507c478bd9Sstevel@tonic-gate 	 * i386 does not provide stub nodes for all boot devices,
9517c478bd9Sstevel@tonic-gate 	 * but we should be able to find the node for the parent,
9527c478bd9Sstevel@tonic-gate 	 * and the leaf of the boot path should be the driver name,
9537c478bd9Sstevel@tonic-gate 	 * which we go ahead and load here.
9547c478bd9Sstevel@tonic-gate 	 */
9557c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
956f4da9be0Scth 		char	*leaf;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 		/*
959f4da9be0Scth 		 * Find last slash to build the full path to the
960f4da9be0Scth 		 * parent of the leaf boot device
9617c478bd9Sstevel@tonic-gate 		 */
962f4da9be0Scth 		p = strrchr(pathcopy, '/');
9637c478bd9Sstevel@tonic-gate 		*p++ = 0;
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 		/*
9667c478bd9Sstevel@tonic-gate 		 * Now isolate the driver name of the leaf device
9677c478bd9Sstevel@tonic-gate 		 */
968f4da9be0Scth 		leaf = p;
969f4da9be0Scth 		p = strchr(leaf, '@');
9707c478bd9Sstevel@tonic-gate 		*p = 0;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
973f4da9be0Scth 		    bootpath, leaf));
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		dip = path_to_devinfo(pathcopy);
976f4da9be0Scth 		if (leaf) {
977f4da9be0Scth 			rval = load_boot_driver(leaf, NULL);
978f4da9be0Scth 			if (rval == -1) {
979f4da9be0Scth 				kmem_free(pathcopy, pathcopy_len);
9807c478bd9Sstevel@tonic-gate 				return (NULL);
981f4da9be0Scth 			}
982f4da9be0Scth 		}
9837c478bd9Sstevel@tonic-gate 	}
9847c478bd9Sstevel@tonic-gate #endif
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
9877c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "can't bind driver for boot path <%s>",
9887c478bd9Sstevel@tonic-gate 		    bootpath);
989f4da9be0Scth 		kmem_free(pathcopy, pathcopy_len);
9907c478bd9Sstevel@tonic-gate 		return (NULL);
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	/*
9947c478bd9Sstevel@tonic-gate 	 * Load IP over IB driver when netbooting over IB.
9957c478bd9Sstevel@tonic-gate 	 * As per IB 1275 binding, IP over IB is represented as
9967c478bd9Sstevel@tonic-gate 	 * service on the top of the HCA node. So, there is no
9977c478bd9Sstevel@tonic-gate 	 * PROM node and generic framework cannot pre-load
9987c478bd9Sstevel@tonic-gate 	 * IP over IB driver based on the bootpath. The following
9997c478bd9Sstevel@tonic-gate 	 * code preloads IP over IB driver when doing netboot over
10007c478bd9Sstevel@tonic-gate 	 * InfiniBand.
10017c478bd9Sstevel@tonic-gate 	 */
10027c478bd9Sstevel@tonic-gate 	if (netboot_over_ib(bootpath) &&
10037c478bd9Sstevel@tonic-gate 	    modloadonly("drv", "ibd") == -1) {
10047c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "ibd: cannot load platform driver\n");
1005f4da9be0Scth 		kmem_free(pathcopy, pathcopy_len);
10067c478bd9Sstevel@tonic-gate 		return (NULL);
10077c478bd9Sstevel@tonic-gate 	}
10087c478bd9Sstevel@tonic-gate 
1009c29cc384Svikram 	/*
1010c29cc384Svikram 	 * The PROM node for hubs have incomplete compatible
1011c29cc384Svikram 	 * properties and therefore do not bind to the hubd driver.
1012c29cc384Svikram 	 * As a result load_bootpath_drivers() loads the usb_mid driver
1013c29cc384Svikram 	 * for hub nodes rather than the hubd driver. This causes
1014c29cc384Svikram 	 * mountroot failures when booting off USB storage. To prevent
1015c29cc384Svikram 	 * this, if we are booting via USB hubs, we preload the hubd driver.
1016c29cc384Svikram 	 */
1017c29cc384Svikram 	if (strstr(bootpath, "/hub@") && modloadonly("drv", "hubd") == -1) {
1018c29cc384Svikram 		cmn_err(CE_WARN, "bootpath contains a USB hub, "
1019c29cc384Svikram 		    "but cannot load hubd driver");
1020c29cc384Svikram 	}
1021c29cc384Svikram 
1022f4da9be0Scth 	/* get rid of minor node at end of copy (if not already done above) */
1023f4da9be0Scth 	p = strrchr(pathcopy, '/');
1024f4da9be0Scth 	if (p) {
1025f4da9be0Scth 		p = strchr(p, ':');
1026f4da9be0Scth 		if (p)
1027f4da9be0Scth 			*p = 0;
1028f4da9be0Scth 	}
1029f4da9be0Scth 
1030f4da9be0Scth 	rval = load_parent_drivers(dip, pathcopy);
1031f4da9be0Scth 	kmem_free(pathcopy, pathcopy_len);
1032f4da9be0Scth 	return (rval);
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate /*
10397c478bd9Sstevel@tonic-gate  * Load drivers required for a platform
10407c478bd9Sstevel@tonic-gate  * Since all hardware nodes should be available in the device
10417c478bd9Sstevel@tonic-gate  * tree, walk the per-driver list and load the parents of
10427c478bd9Sstevel@tonic-gate  * each node found. If not a hardware node, try to load it.
10437c478bd9Sstevel@tonic-gate  * Pseudo nexus is already loaded.
10447c478bd9Sstevel@tonic-gate  */
10457c478bd9Sstevel@tonic-gate static int
10467c478bd9Sstevel@tonic-gate load_boot_platform_modules(char *drv)
10477c478bd9Sstevel@tonic-gate {
10487c478bd9Sstevel@tonic-gate 	major_t	major;
10497c478bd9Sstevel@tonic-gate 	dev_info_t *dip;
10507c478bd9Sstevel@tonic-gate 	char	*drvname;
10517c478bd9Sstevel@tonic-gate 	int	rval = 0;
10527c478bd9Sstevel@tonic-gate 
1053a204de77Scth 	if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
10547c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "%s: no major number\n", drv);
10557c478bd9Sstevel@tonic-gate 		return (-1);
10567c478bd9Sstevel@tonic-gate 	}
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	/*
10597c478bd9Sstevel@tonic-gate 	 * resolve aliases
10607c478bd9Sstevel@tonic-gate 	 */
10617c478bd9Sstevel@tonic-gate 	drvname = ddi_major_to_name(major);
1062a204de77Scth 	if ((major = ddi_name_to_major(drvname)) == DDI_MAJOR_T_NONE)
10637c478bd9Sstevel@tonic-gate 		return (-1);
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate #ifdef	DEBUG
10667c478bd9Sstevel@tonic-gate 	if (strcmp(drv, drvname) == 0) {
10677c478bd9Sstevel@tonic-gate 		BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
10687c478bd9Sstevel@tonic-gate 	} else {
10697c478bd9Sstevel@tonic-gate 		BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
10707c478bd9Sstevel@tonic-gate 		    drv, drvname));
10717c478bd9Sstevel@tonic-gate 	}
10727c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	dip = devnamesp[major].dn_head;
10757c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
10767c478bd9Sstevel@tonic-gate 		/* pseudo node, not-enumerated, needs to be loaded */
10777c478bd9Sstevel@tonic-gate 		if (modloadonly("drv", drvname) == -1) {
10787c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "%s: cannot load platform driver\n",
10797c478bd9Sstevel@tonic-gate 			    drvname);
10807c478bd9Sstevel@tonic-gate 			rval = -1;
10817c478bd9Sstevel@tonic-gate 		}
10827c478bd9Sstevel@tonic-gate 	} else {
10837c478bd9Sstevel@tonic-gate 		while (dip) {
1084f4da9be0Scth 			if (load_parent_drivers(dip, NULL) != 0)
10857c478bd9Sstevel@tonic-gate 				rval = -1;
10867c478bd9Sstevel@tonic-gate 			dip = ddi_get_next(dip);
10877c478bd9Sstevel@tonic-gate 		}
10887c478bd9Sstevel@tonic-gate 	}
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	return (rval);
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate /*
10957c478bd9Sstevel@tonic-gate  * i_find_node: Internal routine used by path_to_devinfo
10967c478bd9Sstevel@tonic-gate  * to locate a given nodeid in the device tree.
10977c478bd9Sstevel@tonic-gate  */
10987c478bd9Sstevel@tonic-gate struct i_path_findnode {
1099fa9e4066Sahrens 	pnode_t nodeid;
11007c478bd9Sstevel@tonic-gate 	dev_info_t *dip;
11017c478bd9Sstevel@tonic-gate };
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate static int
11047c478bd9Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg)
11057c478bd9Sstevel@tonic-gate {
11067c478bd9Sstevel@tonic-gate 	struct i_path_findnode *f = (struct i_path_findnode *)arg;
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	if (ddi_get_nodeid(dev) == (int)f->nodeid) {
11107c478bd9Sstevel@tonic-gate 		f->dip = dev;
11117c478bd9Sstevel@tonic-gate 		return (DDI_WALK_TERMINATE);
11127c478bd9Sstevel@tonic-gate 	}
11137c478bd9Sstevel@tonic-gate 	return (DDI_WALK_CONTINUE);
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate /*
11177c478bd9Sstevel@tonic-gate  * Return the devinfo node to a boot device
11187c478bd9Sstevel@tonic-gate  */
11197c478bd9Sstevel@tonic-gate static dev_info_t *
11207c478bd9Sstevel@tonic-gate path_to_devinfo(char *path)
11217c478bd9Sstevel@tonic-gate {
11227c478bd9Sstevel@tonic-gate 	struct i_path_findnode fn;
11237c478bd9Sstevel@tonic-gate 	extern dev_info_t *top_devinfo;
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 	/*
11267c478bd9Sstevel@tonic-gate 	 * Get the nodeid of the given pathname, if such a mapping exists.
11277c478bd9Sstevel@tonic-gate 	 */
11287c478bd9Sstevel@tonic-gate 	fn.dip = NULL;
11297c478bd9Sstevel@tonic-gate 	fn.nodeid = prom_finddevice(path);
11307c478bd9Sstevel@tonic-gate 	if (fn.nodeid != OBP_BADNODE) {
11317c478bd9Sstevel@tonic-gate 		/*
11327c478bd9Sstevel@tonic-gate 		 * Find the nodeid in our copy of the device tree and return
11337c478bd9Sstevel@tonic-gate 		 * whatever name we used to bind this node to a driver.
11347c478bd9Sstevel@tonic-gate 		 */
11357c478bd9Sstevel@tonic-gate 		ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
11367c478bd9Sstevel@tonic-gate 	}
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11397c478bd9Sstevel@tonic-gate 	/*
11407c478bd9Sstevel@tonic-gate 	 * If we're bound to something other than the nodename,
11417c478bd9Sstevel@tonic-gate 	 * note that in the message buffer and system log.
11427c478bd9Sstevel@tonic-gate 	 */
11437c478bd9Sstevel@tonic-gate 	if (fn.dip) {
11447c478bd9Sstevel@tonic-gate 		char *p, *q;
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 		p = ddi_binding_name(fn.dip);
11477c478bd9Sstevel@tonic-gate 		q = ddi_node_name(fn.dip);
11487c478bd9Sstevel@tonic-gate 		if (p && q && (strcmp(p, q) != 0)) {
11497c478bd9Sstevel@tonic-gate 			BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
11507c478bd9Sstevel@tonic-gate 			    path, p));
11517c478bd9Sstevel@tonic-gate 		}
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	return (fn.dip);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate /*
11597c478bd9Sstevel@tonic-gate  * This routine returns B_TRUE if the bootpath corresponds to
11607c478bd9Sstevel@tonic-gate  * IP over IB driver.
11617c478bd9Sstevel@tonic-gate  *
11627c478bd9Sstevel@tonic-gate  * The format of the bootpath for the IP over IB looks like
11637c478bd9Sstevel@tonic-gate  * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
11647c478bd9Sstevel@tonic-gate  *
11657c478bd9Sstevel@tonic-gate  * The minor node portion "port=1,pkey=8001,protocol=ip" represents
11667c478bd9Sstevel@tonic-gate  * IP over IB driver.
11677c478bd9Sstevel@tonic-gate  */
11687c478bd9Sstevel@tonic-gate static boolean_t
11697c478bd9Sstevel@tonic-gate netboot_over_ib(char *bootpath)
11707c478bd9Sstevel@tonic-gate {
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	char		*temp;
11737c478bd9Sstevel@tonic-gate 	boolean_t	ret = B_FALSE;
1174fa9e4066Sahrens 	pnode_t		node = prom_finddevice(bootpath);
11757c478bd9Sstevel@tonic-gate 	int		len;
11767c478bd9Sstevel@tonic-gate 	char		devicetype[OBP_MAXDRVNAME];
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	/* Is this IB node ? */
1179dedec472SJack Meng 	if (node == OBP_BADNODE || node == OBP_NONODE) {
1180dedec472SJack Meng 		return (B_FALSE);
1181dedec472SJack Meng 	}
11827c478bd9Sstevel@tonic-gate 	len = prom_getproplen(node, OBP_DEVICETYPE);
11837c478bd9Sstevel@tonic-gate 	if (len <= 1 || len >= OBP_MAXDRVNAME)
11847c478bd9Sstevel@tonic-gate 		return (B_FALSE);
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 	(void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype);
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 	if (strncmp("ib", devicetype, 2) == 0) {
11897c478bd9Sstevel@tonic-gate 		/* Check for proper IP over IB string */
11907c478bd9Sstevel@tonic-gate 		if ((temp = strstr(bootpath, ":port=")) != NULL) {
11917c478bd9Sstevel@tonic-gate 			if ((temp = strstr(temp, ",pkey=")) != NULL)
11927c478bd9Sstevel@tonic-gate 				if ((temp = strstr(temp,
11937c478bd9Sstevel@tonic-gate 				    ",protocol=ip")) != NULL) {
11947c478bd9Sstevel@tonic-gate 					ret = B_TRUE;
11957c478bd9Sstevel@tonic-gate 				}
11967c478bd9Sstevel@tonic-gate 		}
11977c478bd9Sstevel@tonic-gate 	}
11987c478bd9Sstevel@tonic-gate 	return (ret);
11997c478bd9Sstevel@tonic-gate }
1200dedec472SJack Meng 
1201dedec472SJack Meng static boolean_t
1202dedec472SJack Meng netboot_over_iscsi(void)
1203dedec472SJack Meng {
1204dedec472SJack Meng 	int proplen;
1205dedec472SJack Meng 	boolean_t	ret = B_FALSE;
1206dedec472SJack Meng 	char	bootpath[OBP_MAXPATHLEN];
1207dedec472SJack Meng 
1208dedec472SJack Meng 	proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH);
1209dedec472SJack Meng 	if (proplen > 0) {
1210dedec472SJack Meng 		if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) {
1211dedec472SJack Meng 			if (memcmp(bootpath, BP_ISCSI_DISK,
1212dedec472SJack Meng 			    strlen(BP_ISCSI_DISK)) == 0) {
1213dedec472SJack Meng 				ret = B_TRUE;
1214dedec472SJack Meng 			}
1215dedec472SJack Meng 		}
1216dedec472SJack Meng 	}
1217dedec472SJack Meng 	return (ret);
1218dedec472SJack Meng }
1219