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