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