swapgeneric.c revision 4851:5e98cf4c2164
122347Spst/*
222347Spst * CDDL HEADER START
329964Sache *
429964Sache * The contents of this file are subject to the terms of the
522347Spst * Common Development and Distribution License (the "License").
622347Spst * You may not use this file except in compliance with the License.
722347Spst *
822347Spst * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
922347Spst * or http://www.opensolaris.org/os/licensing.
1022347Spst * See the License for the specific language governing permissions
1129964Sache * and limitations under the License.
1229964Sache *
1329964Sache * When distributing Covered Code, include this CDDL HEADER in each
1422347Spst * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1522347Spst * If applicable, add the following below this CDDL HEADER, with the
1622347Spst * fields enclosed by brackets "[]" replaced with your own identifying
1722347Spst * information: Portions Copyright [yyyy] [name of copyright owner]
1822347Spst *
1922347Spst * CDDL HEADER END
2022347Spst */
2122347Spst/* ONC_PLUS EXTRACT START */
2222347Spst/*
2322347Spst * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2422347Spst * Use is subject to license terms.
2522347Spst */
2629964Sache
2722347Spst#pragma ident	"%Z%%M%	%I%	%E% SMI"
2822347Spst/* ONC_PLUS EXTRACT END */
2922347Spst
3022347Spst/*
3122347Spst * Configure root, swap and dump devices.
3222347Spst */
3322347Spst
3422347Spst#include <sys/types.h>
3522347Spst#include <sys/param.h>
3622347Spst#include <sys/sysmacros.h>
3722347Spst#include <sys/signal.h>
3829964Sache#include <sys/cred.h>
3922347Spst#include <sys/proc.h>
4022347Spst#include <sys/user.h>
4122347Spst#include <sys/conf.h>
4222347Spst#include <sys/buf.h>
4322347Spst#include <sys/systm.h>
4422347Spst#include <sys/vm.h>
4522347Spst#include <sys/reboot.h>
4622347Spst#include <sys/file.h>
4722347Spst#include <sys/vfs.h>
4822347Spst#include <sys/vnode.h>
4922347Spst#include <sys/errno.h>
5022347Spst#include <sys/kmem.h>
5122347Spst#include <sys/uio.h>
5222347Spst#include <sys/open.h>
5322347Spst#include <sys/mount.h>
5422347Spst#include <sys/kobj.h>
5522347Spst#include <sys/bootconf.h>
5622347Spst#include <sys/sysconf.h>
5722347Spst#include <sys/modctl.h>
5822347Spst#include <sys/autoconf.h>
5922347Spst#include <sys/debug.h>
6022347Spst#include <sys/fs/snode.h>
6122347Spst#include <fs/fs_subr.h>
6222347Spst#include <sys/socket.h>
6322347Spst#include <net/if.h>
6422347Spst
6522347Spst#include <sys/mkdev.h>
6622347Spst#include <sys/cmn_err.h>
6722347Spst#include <sys/console.h>
6822347Spst
6922347Spst#include <sys/conf.h>
7022347Spst#include <sys/ddi.h>
7122347Spst#include <sys/sunddi.h>
7222347Spst#include <sys/hwconf.h>
7322347Spst#include <sys/dc_ki.h>
7422347Spst#include <sys/promif.h>
7522347Spst
7622347Spst
7722347Spst/*
7822347Spst * Local routines
7922347Spst */
8022347Spststatic int preload_module(struct sysparam *, void *);
8122347Spststatic struct vfssw *getfstype(char *, char *, size_t);
8222347Spststatic int getphysdev(char *, char *, size_t);
8322347Spststatic int load_bootpath_drivers(char *bootpath);
8422347Spststatic int load_boot_driver(char *drv);
8522347Spststatic int load_boot_platform_modules(char *drv);
8622347Spststatic dev_info_t *path_to_devinfo(char *path);
8722347Spststatic boolean_t netboot_over_ib(char *bootpath);
8822347Spst
8922347Spst
9022347Spst/*
9122347Spst * Module linkage information for the kernel.
9222347Spst */
9322347Spststatic struct modlmisc modlmisc = {
9422347Spst	&mod_miscops, "root and swap configuration %I%"
9522347Spst};
9622347Spst
9722347Spststatic struct modlinkage modlinkage = {
9822347Spst	MODREV_1, (void *)&modlmisc, NULL
9922347Spst};
10022347Spst
10122347Spstint
10222347Spst_init(void)
10322347Spst{
10422347Spst	return (mod_install(&modlinkage));
10522347Spst}
10622347Spst
10722347Spstint
10822347Spst_fini(void)
10922347Spst{
11022347Spst	return (mod_remove(&modlinkage));
11122347Spst}
11222347Spst
11322347Spstint
11422347Spst_info(struct modinfo *modinfop)
11522347Spst{
11622347Spst	return (mod_info(&modlinkage, modinfop));
11722347Spst}
11822347Spst
11922347Spst/*
12022347Spst * Configure root file system.
12122347Spst */
12222347Spstint
12322347Spstrootconf(void)
12422347Spst{
12529964Sache	int error;
12622347Spst	struct vfssw *vsw;
12722347Spst	extern void pm_init(void);
12822347Spst
12929964Sache	BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
13022347Spst	BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
13122347Spst	BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
13222347Spst	BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));
13322347Spst
13422347Spst	/*
13522347Spst	 * Install cluster modules that were only loaded during
13622347Spst	 * loadrootmodules().
13729964Sache	 */
13822347Spst	if (error = clboot_rootconf())
13922347Spst		return (error);
14022347Spst
14122347Spst	if (root_is_svm) {
14222347Spst		(void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME);
14322347Spst
14422347Spst		BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name));
14522347Spst		BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath));
14622347Spst	}
14722347Spst
14822347Spst	/*
14922347Spst	 * Run _init on the root filesystem (we already loaded it
15022347Spst	 * but we've been waiting until now to _init it) which will
15122347Spst	 * have the side-effect of running vsw_init() on this vfs.
15222347Spst	 * Because all the nfs filesystems are lumped into one
15322347Spst	 * module we need to special case it.
15422347Spst	 */
15522347Spst	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
15622347Spst		if (modload("fs", "nfs") == -1) {
15722347Spst			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
15822347Spst			    rootfs.bo_fstype);
15922347Spst			return (ENXIO);
16022347Spst		}
16122347Spst	} else {
16222347Spst		if (modload("fs", rootfs.bo_fstype) == -1) {
16322347Spst			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
16422347Spst			    rootfs.bo_fstype);
16522347Spst			return (ENXIO);
16622347Spst		}
16722347Spst	}
16822347Spst	RLOCK_VFSSW();
16922347Spst	vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
17022347Spst	RUNLOCK_VFSSW();
17122347Spst	VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
17222347Spst	VFS_HOLD(rootvfs);
17322347Spst
17422347Spst	if (root_is_svm) {
17522347Spst		rootvfs->vfs_flag |= VFS_RDONLY;
17622347Spst	}
17722347Spst
17822347Spst	/*
17929964Sache	 * This pm-releated call has to occur before root is mounted since we
18022347Spst	 * need to power up all devices.  It is placed after VFS_INIT() such
18122347Spst	 * that opening a device via ddi_lyr_ interface just before root has
18222347Spst	 * been mounted would work.
18322347Spst	 */
18422347Spst	pm_init();
18522347Spst
18622347Spst	if (netboot) {
18722347Spst		if ((error = strplumb()) != 0) {
18822347Spst			cmn_err(CE_CONT, "Cannot plumb network device\n");
18922347Spst			return (error);
19022347Spst		}
19122347Spst	}
19222347Spst
19322347Spst	/*
19422347Spst	 * ufs_mountroot() ends up calling getrootdev()
19522347Spst	 * (below) which actually triggers the _init, identify,
19622347Spst	 * probe and attach of the drivers that make up root device
19722347Spst	 * bush; these are also quietly waiting in memory.
19822347Spst	 */
19922347Spst	BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));
20022347Spst
20122347Spst	error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
20222347Spst	vfs_unrefvfssw(vsw);
20322347Spst	rootdev = rootvfs->vfs_dev;
20422347Spst
20522347Spst	if (error)
20622347Spst		cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
20722347Spst		    rootfs.bo_name, rootfs.bo_fstype);
20822347Spst	else
20922347Spst		cmn_err(CE_CONT, "?root on %s fstype %s\n",
21022347Spst		    rootfs.bo_name, rootfs.bo_fstype);
21122347Spst	return (error);
21222347Spst}
21322347Spst
21422347Spst/*
21522347Spst * Remount root on an SVM mirror root device
216 * Only supported on UFS filesystems at present
217 */
218int
219svm_rootconf(void)
220{
221	int	error;
222	extern int ufs_remountroot(struct vfs *vfsp);
223
224	ASSERT(root_is_svm == 1);
225
226	if (strcmp(rootfs.bo_fstype, "ufs") != 0) {
227		cmn_err(CE_CONT, "Mounting root on %s with filesystem "
228		    "type %s is not supported\n",
229		    rootfs.bo_name, rootfs.bo_fstype);
230		return (EINVAL);
231	}
232
233	(void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME);
234
235	BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name));
236
237	error = ufs_remountroot(rootvfs);
238
239	if (error) {
240		cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n",
241		    rootfs.bo_name, rootfs.bo_fstype);
242	} else {
243		cmn_err(CE_CONT, "?root remounted on %s fstype %s\n",
244		    rootfs.bo_name, rootfs.bo_fstype);
245	}
246	return (error);
247}
248
249/*
250 * Under the assumption that our root file system is on a
251 * disk partition, get the dev_t of the partition in question.
252 *
253 * By now, boot has faithfully loaded all our modules into memory, and
254 * we've taken over resource management.  Before we go any further, we
255 * have to fire up the device drivers and stuff we need to mount the
256 * root filesystem.  That's what we do here.  Fingers crossed.
257 */
258dev_t
259getrootdev(void)
260{
261	dev_t	d;
262
263	if ((d = ddi_pathname_to_dev_t(rootfs.bo_name)) == NODEV)
264		cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
265		    rootfs.bo_name);
266	return (d);
267}
268
269/*
270 * If booted with ASKNAME, prompt on the console for a filesystem
271 * name and return it.
272 */
273void
274getfsname(char *askfor, char *name, size_t namelen)
275{
276	if (boothowto & RB_ASKNAME) {
277		printf("%s name: ", askfor);
278		console_gets(name, namelen);
279	}
280}
281
282/*ARGSUSED1*/
283static int
284preload_module(struct sysparam *sysp, void *p)
285{
286	static char *wmesg = "forceload of %s failed";
287	char *name;
288
289	name = sysp->sys_ptr;
290	BMDPRINTF(("preload_module: %s\n", name));
291	if (modloadonly(NULL, name) < 0)
292		cmn_err(CE_WARN, wmesg, name);
293	return (0);
294}
295
296/* ONC_PLUS EXTRACT START */
297/*
298 * We want to load all the modules needed to mount the root filesystem,
299 * so that when we start the ball rolling in 'getrootdev', every module
300 * should already be in memory, just waiting to be init-ed.
301 */
302
303int
304loadrootmodules(void)
305{
306	struct vfssw	*vsw;
307	char		*this;
308	char		*name;
309	int		err;
310/* ONC_PLUS EXTRACT END */
311	int		i, proplen, dhcacklen;
312	extern char	*impl_module_list[];
313	extern char	*platform_module_list[];
314
315	/* Make sure that the PROM's devinfo tree has been created */
316	ASSERT(ddi_root_node());
317
318	BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
319	BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
320	BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));
321
322	/*
323	 * zzz We need to honor what's in rootfs if it's not null.
324	 * non-null means use what's there.  This way we can
325	 * change rootfs with /etc/system AND with tunetool.
326	 */
327	if (root_is_svm) {
328		/* user replaced rootdev, record obp_bootpath */
329		obp_bootpath[0] = '\0';
330		(void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME);
331		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
332	} else {
333		/*
334		 * Get the root fstype and root device path from boot.
335		 */
336		rootfs.bo_fstype[0] = '\0';
337		rootfs.bo_name[0] = '\0';
338	}
339
340	/*
341	 * This lookup will result in modloadonly-ing the root
342	 * filesystem module - it gets _init-ed in rootconf()
343	 */
344	if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
345		return (ENXIO);	/* in case we have no file system types */
346
347	(void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
348
349	vfs_unrefvfssw(vsw);
350
351	/*
352	 * Load the favored drivers of the implementation.
353	 * e.g. 'sbus' and possibly 'zs' (even).
354	 *
355	 * Called whilst boot is still loaded (because boot does
356	 * the i/o for us), and DDI services are unavailable.
357	 */
358	BMDPRINTF(("loadrootmodules: impl_module_list\n"));
359	for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
360		if ((err = load_boot_driver(this)) != 0) {
361			cmn_err(CE_WARN, "Cannot load drv/%s", this);
362			return (err);
363			/* NOTREACHED */
364		}
365	}
366	/*
367	 * Now load the platform modules (if any)
368	 */
369	BMDPRINTF(("loadrootmodules: platform_module_list\n"));
370	for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
371		if ((err = load_boot_platform_modules(this)) != 0) {
372			cmn_err(CE_WARN, "Cannot load drv/%s", this);
373			return (err);
374			/* NOTREACHED */
375		}
376	}
377
378loop:
379	(void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
380
381	/*
382	 * Given a physical pathname, load the correct set of driver
383	 * modules into memory, including all possible parents.
384	 *
385	 * NB: The code sets the variable 'name' for error reporting.
386	 */
387	err = 0;
388	BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
389	if (root_is_svm == 0) {
390		BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
391		name = rootfs.bo_name;
392		err = load_bootpath_drivers(rootfs.bo_name);
393	}
394
395	/*
396	 * Load driver modules in obp_bootpath, this is always
397	 * required for mountroot to succeed. obp_bootpath is
398	 * is set if rootdev is set via /etc/system, which is
399	 * the case if booting of a SVM/VxVM mirror.
400	 */
401	if ((err == 0) && obp_bootpath[0] != '\0') {
402		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
403		name = obp_bootpath;
404		err = load_bootpath_drivers(obp_bootpath);
405	}
406
407	if (err != 0) {
408		cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
409		goto out;
410		/* NOTREACHED */
411	}
412
413	/*
414	 * Check to see if the booter performed DHCP configuration
415	 * ("bootp-response" boot property exists). If so, then before
416	 * bootops disappears we need to save the value of this property
417	 * such that the userland dhcpagent can adopt the DHCP management
418	 * of our primary network interface. We leave room at the beginning of
419	 * saved property to cache the interface name we used to boot the
420	 * client. This context is necessary for the user land dhcpagent
421	 * to do its job properly on a multi-homed system.
422	 */
423	proplen = BOP_GETPROPLEN(bootops, "bootp-response");
424	if (proplen > 0) {
425		dhcacklen = proplen + IFNAMSIZ;
426		dhcack = kmem_zalloc(dhcacklen, KM_SLEEP);
427		if (BOP_GETPROP(bootops, "bootp-response",
428		    (uchar_t *)&dhcack[IFNAMSIZ]) == -1) {
429			cmn_err(CE_WARN, "BOP_GETPROP of  "
430			    "\"bootp-response\" failed\n");
431			kmem_free(dhcack, dhcacklen);
432			dhcack = NULL;
433			goto out;
434		}
435
436		/*
437		 * Fetch the "netdev-path" boot property (if it exists), and
438		 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
439		 */
440		proplen = BOP_GETPROPLEN(bootops, "netdev-path");
441		if (proplen > 0) {
442			netdev_path = kmem_zalloc(proplen, KM_SLEEP);
443			if (BOP_GETPROP(bootops, "netdev-path",
444			    (uchar_t *)netdev_path) == -1) {
445				cmn_err(CE_WARN, "BOP_GETPROP of  "
446				    "\"netdev-path\" failed\n");
447				kmem_free(netdev_path, proplen);
448				goto out;
449			}
450		}
451	}
452
453	/*
454	 * Preload (load-only, no init) all modules which
455	 * were added to the /etc/system file with the
456	 * FORCELOAD keyword.
457	 */
458	BMDPRINTF(("loadrootmodules: preload_module\n"));
459	(void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);
460
461/* ONC_PLUS EXTRACT START */
462	/*
463	 * If we booted otw then load in the plumbing
464	 * routine now while we still can. If we didn't
465	 * boot otw then we will load strplumb in main().
466	 *
467	 * NFS is actually a set of modules, the core routines,
468	 * a diskless helper module, rpcmod, and the tli interface.  Load
469	 * them now while we still can.
470	 *
471	 * Because we glomb all versions of nfs into a single module
472	 * we check based on the initial string "nfs".
473	 *
474	 * XXX: A better test for this is to see if device_type
475	 * XXX: from the PROM is "network".
476	 */
477
478	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
479		++netboot;
480
481		if ((err = modload("misc", "tlimod")) < 0)  {
482			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
483			goto out;
484			/* NOTREACHED */
485		}
486		if ((err = modload("strmod", "rpcmod")) < 0)  {
487			cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
488			goto out;
489			/* NOTREACHED */
490		}
491		if ((err = modload("misc", "nfs_dlboot")) < 0)  {
492			cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
493			goto out;
494			/* NOTREACHED */
495		}
496		if ((err = modload("mac", "mac_ether")) < 0)  {
497			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
498			goto out;
499			/* NOTREACHED */
500		}
501		if ((err = modload("misc", "strplumb")) < 0)  {
502			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
503			goto out;
504			/* NOTREACHED */
505		}
506		if ((err = strplumb_load()) < 0) {
507			goto out;
508			/* NOTREACHED */
509		}
510	}
511
512	/*
513	 * Preload modules needed for booting as a cluster.
514	 */
515	err = clboot_loadrootmodules();
516
517out:
518	if (err != 0 && (boothowto & RB_ASKNAME))
519		goto loop;
520
521	return (err);
522}
523/* ONC_PLUS EXTRACT END */
524
525/*
526 * Get the name of the root or swap filesystem type, and return
527 * the corresponding entry in the vfs switch.
528 *
529 * If we're not asking the user, and we're trying to find the
530 * root filesystem type, we ask boot for the filesystem
531 * type that it came from and use that.  Similarly, if we're
532 * trying to find the swap filesystem, we try and derive it from
533 * the root filesystem type.
534 *
535 * If we are booting via NFS we currently have these options:
536 *	nfs -	dynamically choose NFS V2. V3, or V4 (default)
537 *	nfs2 -	force NFS V2
538 *	nfs3 -	force NFS V3
539 *	nfs4 -	force NFS V4
540 * Because we need to maintain backward compatibility with the naming
541 * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
542 * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs".  The dynamic
543 * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
544 * This is only for root filesystems, all other uses such as cachefs
545 * will expect that "nfs" == NFS V2.
546 *
547 * If the filesystem isn't already loaded, vfs_getvfssw() will load
548 * it for us, but if (at the time we call it) modrootloaded is
549 * still not set, it won't run the filesystems _init routine (and
550 * implicitly it won't run the filesystems vsw_init() entry either).
551 * We do that explicitly in rootconf().
552 */
553static struct vfssw *
554getfstype(char *askfor, char *fsname, size_t fsnamelen)
555{
556	struct vfssw *vsw;
557	static char defaultfs[BO_MAXFSNAME];
558	int root = 0;
559
560	if (strcmp(askfor, "root") == 0) {
561		(void) BOP_GETPROP(bootops, "fstype", defaultfs);
562		root++;
563	} else {
564		(void) strcpy(defaultfs, "swapfs");
565	}
566
567	if (boothowto & RB_ASKNAME) {
568		for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') {
569			printf("%s filesystem type [%s]: ", askfor, defaultfs);
570			console_gets(fsname, fsnamelen);
571			if (*fsname == '\0')
572				(void) strcpy(fsname, defaultfs);
573			if (root) {
574				if (strcmp(fsname, "nfs2") == 0)
575					(void) strcpy(fsname, "nfs");
576				else if (strcmp(fsname, "nfs") == 0)
577					(void) strcpy(fsname, "nfsdyn");
578			}
579			if ((vsw = vfs_getvfssw(fsname)) != NULL)
580				return (vsw);
581			printf("Unknown filesystem type '%s'\n", fsname);
582		}
583	} else if (*fsname == '\0') {
584		fsname = defaultfs;
585	}
586	if (*fsname == '\0') {
587		return (NULL);
588	}
589
590	if (root) {
591		if (strcmp(fsname, "nfs2") == 0)
592			(void) strcpy(fsname, "nfs");
593		else if (strcmp(fsname, "nfs") == 0)
594			(void) strcpy(fsname, "nfsdyn");
595	}
596
597	return (vfs_getvfssw(fsname));
598}
599
600
601/*
602 * Get a physical device name, and maybe load and attach
603 * the driver.
604 *
605 * XXX	Need better checking of whether or not a device
606 *	actually exists if the user typed in a pathname.
607 *
608 * XXX	Are we sure we want to expose users to this sort
609 *	of physical namespace gobbledygook (now there's
610 *	a word to conjure with..)
611 *
612 * XXX	Note that on an OBP machine, we can easily ask the
613 *	prom and pretty-print some plausible set of bootable
614 *	devices.  We can also user the prom to verify any
615 *	such device.  Later tim.. later.
616 */
617static int
618getphysdev(char *askfor, char *name, size_t namelen)
619{
620	static char fmt[] = "Enter physical name of %s device\n[%s]: ";
621	dev_t dev;
622	static char defaultpath[BO_MAXOBJNAME];
623
624	/*
625	 * Establish 'default' values - we get the root device from
626	 * boot, and we infer the swap device is the same but with
627	 * a 'b' on the end instead of an 'a'.  A first stab at
628	 * ease-of-use ..
629	 */
630	if (strcmp(askfor, "root") == 0) {
631		/*
632		 * Look for the 1275 compliant name 'bootpath' first,
633		 * but make certain it has a non-NULL value as well.
634		 */
635		if ((BOP_GETPROP(bootops, "bootpath", defaultpath) == -1) ||
636		    strlen(defaultpath) == 0) {
637			if (BOP_GETPROP(bootops,
638			    "boot-path", defaultpath) == -1)
639				boothowto |= RB_ASKNAME | RB_VERBOSE;
640		}
641	} else {
642		(void) strcpy(defaultpath, rootfs.bo_name);
643		defaultpath[strlen(defaultpath) - 1] = 'b';
644	}
645
646retry:
647	if (boothowto & RB_ASKNAME) {
648		printf(fmt, askfor, defaultpath);
649		console_gets(name, namelen);
650	}
651	if (*name == '\0')
652		(void) strcpy(name, defaultpath);
653
654	if (strcmp(askfor, "swap") == 0)   {
655
656		/*
657		 * Try to load and install the swap device driver.
658		 */
659		dev = ddi_pathname_to_dev_t(name);
660
661		if (dev == (dev_t)-1)  {
662			printf("Not a supported device for swap.\n");
663			boothowto |= RB_ASKNAME | RB_VERBOSE;
664			goto retry;
665		}
666
667		/*
668		 * Ensure that we're not trying to swap on the floppy.
669		 */
670		if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
671			printf("Too dangerous to swap on the floppy\n");
672			if (boothowto & RB_ASKNAME)
673				goto retry;
674			return (-1);
675		}
676	}
677
678	return (0);
679}
680
681
682/*
683 * Load a driver needed to boot.
684 */
685static int
686load_boot_driver(char *drv)
687{
688	char		*drvname;
689	major_t		major;
690#ifdef	sparc
691	struct devnames *dnp;
692	ddi_prop_t	*propp;
693	char		*module;
694	char		*dir, *mf;
695	int		plen;
696	int		mlen;
697#endif	/* sparc */
698
699	if ((major = ddi_name_to_major(drv)) == (major_t)-1) {
700		cmn_err(CE_CONT, "%s: no major number\n", drv);
701		return (-1);
702	}
703	/*
704	 * resolve aliases
705	 */
706	drvname = ddi_major_to_name(major);
707
708#ifdef	DEBUG
709	if (strcmp(drv, drvname) == 0) {
710		BMDPRINTF(("load_boot_driver: %s\n", drv));
711	} else {
712		BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
713	}
714#endif	/* DEBUG */
715
716	if (modloadonly("drv", drvname) == -1) {
717		cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
718		return (-1);
719	}
720
721#ifdef	sparc
722	/*
723	 * NOTE: this can be removed when newboot-sparc is delivered.
724	 *
725	 * Check to see if the driver had a 'ddi-forceload' global driver.conf
726	 * property to identify additional modules that need to be loaded.
727	 * The driver still needs to use ddi_modopen() to open these modules,
728	 * but the 'ddi-forceload' property allows the modules to be loaded
729	 * into memory prior to lights-out, so that driver ddi_modopen()
730	 * calls during lights-out (when mounting root) will work correctly.
731	 * Use of 'ddi-forceload' is only required for drivers involved in
732	 * getting root mounted.
733	 */
734	dnp = &devnamesp[major];
735	if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
736	    ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
737	    "ddi-forceload", DDI_PROP_TYPE_STRING,
738	    &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {
739
740		module = (char *)propp->prop_val;
741		plen = propp->prop_len;
742		while (plen > 0) {
743			mlen = strlen(module);
744			mf = strrchr(module, '/');
745			if (mf) {
746				dir = module;
747				*mf++ = '\0';		/* '/' -> '\0' */
748			} else {
749				dir = "misc";
750				mf = module;
751			}
752			if (modloadonly(dir, mf) == -1)
753				cmn_err(CE_CONT,
754				    "misc/%s: can't load module\n", mf);
755			if (mf != module)
756				*(mf - 1) = '/';	/* '\0' -> '/' */
757
758			module += mlen + 1;
759			plen -= mlen + 1;
760		}
761	}
762#endif	/* sparc */
763
764	return (0);
765}
766
767
768/*
769 * For a given instance, load that driver and its parents
770 */
771static int
772load_parent_drivers(dev_info_t *dip, char *path)
773{
774	int	rval = 0;
775	major_t	major = (major_t)-1;
776	char	*drv;
777	char	*p;
778
779	while (dip) {
780		/* check for path-oriented alias */
781		if (path)
782			major = ddi_name_to_major(path);
783		else
784			major = (major_t)-1;
785
786		if (major != (major_t)-1)
787			drv = ddi_major_to_name(major);
788		else
789			drv = ddi_binding_name(dip);
790
791		if (load_boot_driver(drv) != 0)
792			rval = -1;
793
794		dip = ddi_get_parent(dip);
795		if (path) {
796			p = strrchr(path, '/');
797			if (p)
798				*p = 0;
799		}
800	}
801
802	return (rval);
803}
804
805
806/*
807 * For a given path to a boot device,
808 * load that driver and all its parents.
809 */
810static int
811load_bootpath_drivers(char *bootpath)
812{
813	dev_info_t	*dip;
814	char		*pathcopy;
815	int		pathcopy_len;
816	int		rval;
817	char		*p;
818
819	if (bootpath == NULL || *bootpath == 0)
820		return (-1);
821
822	BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
823
824	pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
825	pathcopy_len = strlen(pathcopy) + 1;
826
827	dip = path_to_devinfo(pathcopy);
828
829#if defined(__i386) || defined(__amd64)
830	/*
831	 * i386 does not provide stub nodes for all boot devices,
832	 * but we should be able to find the node for the parent,
833	 * and the leaf of the boot path should be the driver name,
834	 * which we go ahead and load here.
835	 */
836	if (dip == NULL) {
837		char	*leaf;
838
839		/*
840		 * Find last slash to build the full path to the
841		 * parent of the leaf boot device
842		 */
843		p = strrchr(pathcopy, '/');
844		*p++ = 0;
845
846		/*
847		 * Now isolate the driver name of the leaf device
848		 */
849		leaf = p;
850		p = strchr(leaf, '@');
851		*p = 0;
852
853		BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
854		    bootpath, leaf));
855
856		dip = path_to_devinfo(pathcopy);
857		if (leaf) {
858			rval = load_boot_driver(leaf, NULL);
859			if (rval == -1) {
860				kmem_free(pathcopy, pathcopy_len);
861				return (NULL);
862			}
863		}
864	}
865#endif
866
867	if (dip == NULL) {
868		cmn_err(CE_WARN, "can't bind driver for boot path <%s>",
869		    bootpath);
870		kmem_free(pathcopy, pathcopy_len);
871		return (NULL);
872	}
873
874	/*
875	 * Load IP over IB driver when netbooting over IB.
876	 * As per IB 1275 binding, IP over IB is represented as
877	 * service on the top of the HCA node. So, there is no
878	 * PROM node and generic framework cannot pre-load
879	 * IP over IB driver based on the bootpath. The following
880	 * code preloads IP over IB driver when doing netboot over
881	 * InfiniBand.
882	 */
883	if (netboot_over_ib(bootpath) &&
884	    modloadonly("drv", "ibd") == -1) {
885		cmn_err(CE_CONT, "ibd: cannot load platform driver\n");
886		kmem_free(pathcopy, pathcopy_len);
887		return (NULL);
888	}
889
890	/* get rid of minor node at end of copy (if not already done above) */
891	p = strrchr(pathcopy, '/');
892	if (p) {
893		p = strchr(p, ':');
894		if (p)
895			*p = 0;
896	}
897
898	rval = load_parent_drivers(dip, pathcopy);
899	kmem_free(pathcopy, pathcopy_len);
900	return (rval);
901}
902
903
904
905
906/*
907 * Load drivers required for a platform
908 * Since all hardware nodes should be available in the device
909 * tree, walk the per-driver list and load the parents of
910 * each node found. If not a hardware node, try to load it.
911 * Pseudo nexus is already loaded.
912 */
913static int
914load_boot_platform_modules(char *drv)
915{
916	major_t	major;
917	dev_info_t *dip;
918	char	*drvname;
919	int	rval = 0;
920
921	if ((major = ddi_name_to_major(drv)) == (major_t)-1) {
922		cmn_err(CE_CONT, "%s: no major number\n", drv);
923		return (-1);
924	}
925
926	/*
927	 * resolve aliases
928	 */
929	drvname = ddi_major_to_name(major);
930	if ((major = ddi_name_to_major(drvname)) == (major_t)-1)
931		return (-1);
932
933#ifdef	DEBUG
934	if (strcmp(drv, drvname) == 0) {
935		BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
936	} else {
937		BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
938		    drv, drvname));
939	}
940#endif	/* DEBUG */
941
942	dip = devnamesp[major].dn_head;
943	if (dip == NULL) {
944		/* pseudo node, not-enumerated, needs to be loaded */
945		if (modloadonly("drv", drvname) == -1) {
946			cmn_err(CE_CONT, "%s: cannot load platform driver\n",
947			    drvname);
948			rval = -1;
949		}
950	} else {
951		while (dip) {
952			if (load_parent_drivers(dip, NULL) != 0)
953				rval = -1;
954			dip = ddi_get_next(dip);
955		}
956	}
957
958	return (rval);
959}
960
961
962/*
963 * i_find_node: Internal routine used by path_to_devinfo
964 * to locate a given nodeid in the device tree.
965 */
966struct i_path_findnode {
967	pnode_t nodeid;
968	dev_info_t *dip;
969};
970
971static int
972i_path_find_node(dev_info_t *dev, void *arg)
973{
974	struct i_path_findnode *f = (struct i_path_findnode *)arg;
975
976
977	if (ddi_get_nodeid(dev) == (int)f->nodeid) {
978		f->dip = dev;
979		return (DDI_WALK_TERMINATE);
980	}
981	return (DDI_WALK_CONTINUE);
982}
983
984/*
985 * Return the devinfo node to a boot device
986 */
987static dev_info_t *
988path_to_devinfo(char *path)
989{
990	struct i_path_findnode fn;
991	extern dev_info_t *top_devinfo;
992
993	/*
994	 * Get the nodeid of the given pathname, if such a mapping exists.
995	 */
996	fn.dip = NULL;
997	fn.nodeid = prom_finddevice(path);
998	if (fn.nodeid != OBP_BADNODE) {
999		/*
1000		 * Find the nodeid in our copy of the device tree and return
1001		 * whatever name we used to bind this node to a driver.
1002		 */
1003		ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
1004	}
1005
1006#ifdef	DEBUG
1007	/*
1008	 * If we're bound to something other than the nodename,
1009	 * note that in the message buffer and system log.
1010	 */
1011	if (fn.dip) {
1012		char *p, *q;
1013
1014		p = ddi_binding_name(fn.dip);
1015		q = ddi_node_name(fn.dip);
1016		if (p && q && (strcmp(p, q) != 0)) {
1017			BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
1018			    path, p));
1019		}
1020	}
1021#endif	/* DEBUG */
1022
1023	return (fn.dip);
1024}
1025
1026/*
1027 * This routine returns B_TRUE if the bootpath corresponds to
1028 * IP over IB driver.
1029 *
1030 * The format of the bootpath for the IP over IB looks like
1031 * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
1032 *
1033 * The minor node portion "port=1,pkey=8001,protocol=ip" represents
1034 * IP over IB driver.
1035 */
1036static boolean_t
1037netboot_over_ib(char *bootpath)
1038{
1039
1040	char		*temp;
1041	boolean_t	ret = B_FALSE;
1042	pnode_t		node = prom_finddevice(bootpath);
1043	int		len;
1044	char		devicetype[OBP_MAXDRVNAME];
1045
1046	/* Is this IB node ? */
1047	len = prom_getproplen(node, OBP_DEVICETYPE);
1048	if (len <= 1 || len >= OBP_MAXDRVNAME)
1049		return (B_FALSE);
1050
1051	(void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype);
1052
1053	if (strncmp("ib", devicetype, 2) == 0) {
1054		/* Check for proper IP over IB string */
1055		if ((temp = strstr(bootpath, ":port=")) != NULL) {
1056			if ((temp = strstr(temp, ",pkey=")) != NULL)
1057				if ((temp = strstr(temp,
1058				    ",protocol=ip")) != NULL) {
1059					ret = B_TRUE;
1060				}
1061		}
1062	}
1063	return (ret);
1064}
1065