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