17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
548aa2e6aSseb * Common Development and Distribution License (the "License").
648aa2e6aSseb * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21*e373b6e4SYuri Pankov
227c478bd9Sstevel@tonic-gate /*
231cfa752fSRamaswamy Tummala * Copyright (c) 1982, 2010, Oracle and/or its affiliates. All rights reserved.
24*e373b6e4SYuri Pankov * Copyright 2016 Nexenta Systems, Inc.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Configure root, swap and dump devices.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/cred.h>
367c478bd9Sstevel@tonic-gate #include <sys/proc.h>
377c478bd9Sstevel@tonic-gate #include <sys/user.h>
387c478bd9Sstevel@tonic-gate #include <sys/conf.h>
397c478bd9Sstevel@tonic-gate #include <sys/buf.h>
407c478bd9Sstevel@tonic-gate #include <sys/systm.h>
417c478bd9Sstevel@tonic-gate #include <sys/vm.h>
427c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
437c478bd9Sstevel@tonic-gate #include <sys/file.h>
447c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
457c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
467c478bd9Sstevel@tonic-gate #include <sys/errno.h>
477c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
487c478bd9Sstevel@tonic-gate #include <sys/uio.h>
497c478bd9Sstevel@tonic-gate #include <sys/open.h>
507c478bd9Sstevel@tonic-gate #include <sys/mount.h>
517c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
527c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
537c478bd9Sstevel@tonic-gate #include <sys/sysconf.h>
547c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
557c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
567c478bd9Sstevel@tonic-gate #include <sys/debug.h>
577c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h>
587c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
597c478bd9Sstevel@tonic-gate #include <sys/socket.h>
607c478bd9Sstevel@tonic-gate #include <net/if.h>
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
637c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
647c478bd9Sstevel@tonic-gate #include <sys/console.h>
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate #include <sys/conf.h>
677c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
687c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
697c478bd9Sstevel@tonic-gate #include <sys/hwconf.h>
707c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h>
717c478bd9Sstevel@tonic-gate #include <sys/promif.h>
72dedec472SJack Meng #include <sys/bootprops.h>
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * Local routines
767c478bd9Sstevel@tonic-gate */
777c478bd9Sstevel@tonic-gate static int preload_module(struct sysparam *, void *);
787c478bd9Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t);
797c478bd9Sstevel@tonic-gate static int getphysdev(char *, char *, size_t);
807c478bd9Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath);
817c478bd9Sstevel@tonic-gate static int load_boot_driver(char *drv);
827c478bd9Sstevel@tonic-gate static int load_boot_platform_modules(char *drv);
837c478bd9Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path);
847c478bd9Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath);
85dedec472SJack Meng static boolean_t netboot_over_iscsi(void);
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
897c478bd9Sstevel@tonic-gate */
907c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = {
91986fd29aSsetje &mod_miscops, "root and swap configuration"
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
957c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL
967c478bd9Sstevel@tonic-gate };
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate int
_init(void)997c478bd9Sstevel@tonic-gate _init(void)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage));
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate int
_fini(void)1057c478bd9Sstevel@tonic-gate _fini(void)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage));
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1117c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
116dedec472SJack Meng extern ib_boot_prop_t *iscsiboot_prop;
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * Configure root file system.
1197c478bd9Sstevel@tonic-gate */
1207c478bd9Sstevel@tonic-gate int
rootconf(void)1217c478bd9Sstevel@tonic-gate rootconf(void)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate int error;
1247c478bd9Sstevel@tonic-gate struct vfssw *vsw;
1257c478bd9Sstevel@tonic-gate extern void pm_init(void);
126dedec472SJack Meng int ret = -1;
1277c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
1287c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
1297c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
1307c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate * Install cluster modules that were only loaded during
1347c478bd9Sstevel@tonic-gate * loadrootmodules().
1357c478bd9Sstevel@tonic-gate */
1367c478bd9Sstevel@tonic-gate if (error = clboot_rootconf())
1377c478bd9Sstevel@tonic-gate return (error);
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate * Run _init on the root filesystem (we already loaded it
1417c478bd9Sstevel@tonic-gate * but we've been waiting until now to _init it) which will
1427c478bd9Sstevel@tonic-gate * have the side-effect of running vsw_init() on this vfs.
1437c478bd9Sstevel@tonic-gate * Because all the nfs filesystems are lumped into one
1447c478bd9Sstevel@tonic-gate * module we need to special case it.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
1477c478bd9Sstevel@tonic-gate if (modload("fs", "nfs") == -1) {
1487c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1497c478bd9Sstevel@tonic-gate rootfs.bo_fstype);
1507c478bd9Sstevel@tonic-gate return (ENXIO);
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate } else {
1537c478bd9Sstevel@tonic-gate if (modload("fs", rootfs.bo_fstype) == -1) {
1547c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
1557c478bd9Sstevel@tonic-gate rootfs.bo_fstype);
1567c478bd9Sstevel@tonic-gate return (ENXIO);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate }
1597c478bd9Sstevel@tonic-gate RLOCK_VFSSW();
1607c478bd9Sstevel@tonic-gate vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
1617c478bd9Sstevel@tonic-gate RUNLOCK_VFSSW();
16256c0b1daSPavel Filipensky if (vsw == NULL) {
16356c0b1daSPavel Filipensky cmn_err(CE_CONT, "Cannot find %s filesystem\n",
16456c0b1daSPavel Filipensky rootfs.bo_fstype);
16556c0b1daSPavel Filipensky return (ENXIO);
16656c0b1daSPavel Filipensky }
1677c478bd9Sstevel@tonic-gate VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
1687c478bd9Sstevel@tonic-gate VFS_HOLD(rootvfs);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate * This pm-releated call has to occur before root is mounted since we
1727c478bd9Sstevel@tonic-gate * need to power up all devices. It is placed after VFS_INIT() such
1737c478bd9Sstevel@tonic-gate * that opening a device via ddi_lyr_ interface just before root has
1747c478bd9Sstevel@tonic-gate * been mounted would work.
1757c478bd9Sstevel@tonic-gate */
1767c478bd9Sstevel@tonic-gate pm_init();
1777c478bd9Sstevel@tonic-gate
178dedec472SJack Meng if (netboot && iscsiboot_prop) {
179dedec472SJack Meng cmn_err(CE_WARN, "NFS boot and iSCSI boot"
180dedec472SJack Meng " shouldn't happen in the same time");
181dedec472SJack Meng return (EINVAL);
182dedec472SJack Meng }
183dedec472SJack Meng
184dedec472SJack Meng if (netboot || iscsiboot_prop) {
185dedec472SJack Meng ret = strplumb();
186dedec472SJack Meng if (ret != 0) {
187dedec472SJack Meng cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
188dedec472SJack Meng return (EFAULT);
189dedec472SJack Meng }
190dedec472SJack Meng }
191dedec472SJack Meng
192dedec472SJack Meng if ((ret == 0) && iscsiboot_prop) {
193dedec472SJack Meng ret = modload("drv", "iscsi");
194dedec472SJack Meng /* -1 indicates fail */
195dedec472SJack Meng if (ret == -1) {
196dedec472SJack Meng cmn_err(CE_WARN, "Failed to load iscsi module");
197dedec472SJack Meng iscsi_boot_prop_free();
198dedec472SJack Meng return (EINVAL);
199dedec472SJack Meng } else {
200dedec472SJack Meng if (!i_ddi_attach_pseudo_node("iscsi")) {
201dedec472SJack Meng cmn_err(CE_WARN,
202dedec472SJack Meng "Failed to attach iscsi driver");
203dedec472SJack Meng iscsi_boot_prop_free();
204dedec472SJack Meng return (ENODEV);
205dedec472SJack Meng }
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * ufs_mountroot() ends up calling getrootdev()
2117c478bd9Sstevel@tonic-gate * (below) which actually triggers the _init, identify,
2127c478bd9Sstevel@tonic-gate * probe and attach of the drivers that make up root device
2137c478bd9Sstevel@tonic-gate * bush; these are also quietly waiting in memory.
2147c478bd9Sstevel@tonic-gate */
2157c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
2187c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw);
2197c478bd9Sstevel@tonic-gate rootdev = rootvfs->vfs_dev;
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate if (error)
2227c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
2237c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype);
2247c478bd9Sstevel@tonic-gate else
2257c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root on %s fstype %s\n",
2267c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype);
2277c478bd9Sstevel@tonic-gate return (error);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * Under the assumption that our root file system is on a
2327c478bd9Sstevel@tonic-gate * disk partition, get the dev_t of the partition in question.
2337c478bd9Sstevel@tonic-gate *
2347c478bd9Sstevel@tonic-gate * By now, boot has faithfully loaded all our modules into memory, and
2357c478bd9Sstevel@tonic-gate * we've taken over resource management. Before we go any further, we
2367c478bd9Sstevel@tonic-gate * have to fire up the device drivers and stuff we need to mount the
2377c478bd9Sstevel@tonic-gate * root filesystem. That's what we do here. Fingers crossed.
2387c478bd9Sstevel@tonic-gate */
2397c478bd9Sstevel@tonic-gate dev_t
getrootdev(void)2407c478bd9Sstevel@tonic-gate getrootdev(void)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate dev_t d;
2437c478bd9Sstevel@tonic-gate
244dedec472SJack Meng d = ddi_pathname_to_dev_t(rootfs.bo_name);
245dedec472SJack Meng if ((d == NODEV) && (iscsiboot_prop != NULL)) {
246dedec472SJack Meng /* Give it another try with the 'disk' path */
247dedec472SJack Meng get_iscsi_bootpath_phy(rootfs.bo_name);
248dedec472SJack Meng d = ddi_pathname_to_dev_t(rootfs.bo_name);
249dedec472SJack Meng }
250dedec472SJack Meng if (d == NODEV)
2517c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
2527c478bd9Sstevel@tonic-gate rootfs.bo_name);
2537c478bd9Sstevel@tonic-gate return (d);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate * If booted with ASKNAME, prompt on the console for a filesystem
2587c478bd9Sstevel@tonic-gate * name and return it.
2597c478bd9Sstevel@tonic-gate */
2607c478bd9Sstevel@tonic-gate void
getfsname(char * askfor,char * name,size_t namelen)2617c478bd9Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) {
2647c478bd9Sstevel@tonic-gate printf("%s name: ", askfor);
2657c478bd9Sstevel@tonic-gate console_gets(name, namelen);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
2707c478bd9Sstevel@tonic-gate static int
preload_module(struct sysparam * sysp,void * p)2717c478bd9Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p)
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate static char *wmesg = "forceload of %s failed";
2747c478bd9Sstevel@tonic-gate char *name;
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate name = sysp->sys_ptr;
2777c478bd9Sstevel@tonic-gate BMDPRINTF(("preload_module: %s\n", name));
2787c478bd9Sstevel@tonic-gate if (modloadonly(NULL, name) < 0)
2797c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, wmesg, name);
2807c478bd9Sstevel@tonic-gate return (0);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate * We want to load all the modules needed to mount the root filesystem,
2857c478bd9Sstevel@tonic-gate * so that when we start the ball rolling in 'getrootdev', every module
2867c478bd9Sstevel@tonic-gate * should already be in memory, just waiting to be init-ed.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate int
loadrootmodules(void)2907c478bd9Sstevel@tonic-gate loadrootmodules(void)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate struct vfssw *vsw;
2937c478bd9Sstevel@tonic-gate char *this;
2947c478bd9Sstevel@tonic-gate char *name;
2957c478bd9Sstevel@tonic-gate int err;
296986fd29aSsetje int i, proplen;
2977c478bd9Sstevel@tonic-gate extern char *impl_module_list[];
2987c478bd9Sstevel@tonic-gate extern char *platform_module_list[];
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate /* Make sure that the PROM's devinfo tree has been created */
3017c478bd9Sstevel@tonic-gate ASSERT(ddi_root_node());
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
3047c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
3057c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * Get the root fstype and root device path from boot.
3097c478bd9Sstevel@tonic-gate */
3107c478bd9Sstevel@tonic-gate rootfs.bo_fstype[0] = '\0';
3117c478bd9Sstevel@tonic-gate rootfs.bo_name[0] = '\0';
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate * This lookup will result in modloadonly-ing the root
3157c478bd9Sstevel@tonic-gate * filesystem module - it gets _init-ed in rootconf()
3167c478bd9Sstevel@tonic-gate */
3177c478bd9Sstevel@tonic-gate if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
3187c478bd9Sstevel@tonic-gate return (ENXIO); /* in case we have no file system types */
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate (void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate * Load the favored drivers of the implementation.
3267c478bd9Sstevel@tonic-gate * e.g. 'sbus' and possibly 'zs' (even).
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * Called whilst boot is still loaded (because boot does
3297c478bd9Sstevel@tonic-gate * the i/o for us), and DDI services are unavailable.
3307c478bd9Sstevel@tonic-gate */
3317c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: impl_module_list\n"));
3327c478bd9Sstevel@tonic-gate for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
3337c478bd9Sstevel@tonic-gate if ((err = load_boot_driver(this)) != 0) {
3347c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this);
3357c478bd9Sstevel@tonic-gate return (err);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate /*
3397c478bd9Sstevel@tonic-gate * Now load the platform modules (if any)
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: platform_module_list\n"));
3427c478bd9Sstevel@tonic-gate for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
3437c478bd9Sstevel@tonic-gate if ((err = load_boot_platform_modules(this)) != 0) {
3447c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this);
3457c478bd9Sstevel@tonic-gate return (err);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate loop:
3507c478bd9Sstevel@tonic-gate (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
3517c478bd9Sstevel@tonic-gate /*
3527c478bd9Sstevel@tonic-gate * Given a physical pathname, load the correct set of driver
3537c478bd9Sstevel@tonic-gate * modules into memory, including all possible parents.
3547c478bd9Sstevel@tonic-gate *
3557c478bd9Sstevel@tonic-gate * NB: The code sets the variable 'name' for error reporting.
3567c478bd9Sstevel@tonic-gate */
3577c478bd9Sstevel@tonic-gate err = 0;
3587c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
3597c478bd9Sstevel@tonic-gate name = rootfs.bo_name;
3607c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(rootfs.bo_name);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate * Load driver modules in obp_bootpath, this is always
3647c478bd9Sstevel@tonic-gate * required for mountroot to succeed. obp_bootpath is
365*e373b6e4SYuri Pankov * is set if rootdev is set via /etc/system.
3667c478bd9Sstevel@tonic-gate */
3677c478bd9Sstevel@tonic-gate if ((err == 0) && obp_bootpath[0] != '\0') {
3687c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
3697c478bd9Sstevel@tonic-gate name = obp_bootpath;
3707c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(obp_bootpath);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate if (err != 0) {
3747c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
3757c478bd9Sstevel@tonic-gate goto out;
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate * Check to see if the booter performed DHCP configuration
3807c478bd9Sstevel@tonic-gate * ("bootp-response" boot property exists). If so, then before
3817c478bd9Sstevel@tonic-gate * bootops disappears we need to save the value of this property
3827c478bd9Sstevel@tonic-gate * such that the userland dhcpagent can adopt the DHCP management
383986fd29aSsetje * of our primary network interface.
3847c478bd9Sstevel@tonic-gate */
3857c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "bootp-response");
3867c478bd9Sstevel@tonic-gate if (proplen > 0) {
387986fd29aSsetje dhcack = kmem_zalloc(proplen, KM_SLEEP);
388986fd29aSsetje if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) {
3897c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of "
3907c478bd9Sstevel@tonic-gate "\"bootp-response\" failed\n");
3917c478bd9Sstevel@tonic-gate kmem_free(dhcack, dhcacklen);
3927c478bd9Sstevel@tonic-gate dhcack = NULL;
3937c478bd9Sstevel@tonic-gate goto out;
3947c478bd9Sstevel@tonic-gate }
395986fd29aSsetje dhcacklen = proplen;
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * Fetch the "netdev-path" boot property (if it exists), and
3997c478bd9Sstevel@tonic-gate * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
4007c478bd9Sstevel@tonic-gate */
4017c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "netdev-path");
4027c478bd9Sstevel@tonic-gate if (proplen > 0) {
4037c478bd9Sstevel@tonic-gate netdev_path = kmem_zalloc(proplen, KM_SLEEP);
4047c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "netdev-path",
4057c478bd9Sstevel@tonic-gate (uchar_t *)netdev_path) == -1) {
4067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of "
4077c478bd9Sstevel@tonic-gate "\"netdev-path\" failed\n");
4087c478bd9Sstevel@tonic-gate kmem_free(netdev_path, proplen);
4097c478bd9Sstevel@tonic-gate goto out;
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate * Preload (load-only, no init) all modules which
4167c478bd9Sstevel@tonic-gate * were added to the /etc/system file with the
4177c478bd9Sstevel@tonic-gate * FORCELOAD keyword.
4187c478bd9Sstevel@tonic-gate */
4197c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: preload_module\n"));
4207c478bd9Sstevel@tonic-gate (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate * If we booted otw then load in the plumbing
4247c478bd9Sstevel@tonic-gate * routine now while we still can. If we didn't
4257c478bd9Sstevel@tonic-gate * boot otw then we will load strplumb in main().
4267c478bd9Sstevel@tonic-gate *
4277c478bd9Sstevel@tonic-gate * NFS is actually a set of modules, the core routines,
4287c478bd9Sstevel@tonic-gate * a diskless helper module, rpcmod, and the tli interface. Load
4297c478bd9Sstevel@tonic-gate * them now while we still can.
4307c478bd9Sstevel@tonic-gate *
4317c478bd9Sstevel@tonic-gate * Because we glomb all versions of nfs into a single module
4327c478bd9Sstevel@tonic-gate * we check based on the initial string "nfs".
4337c478bd9Sstevel@tonic-gate *
4347c478bd9Sstevel@tonic-gate * XXX: A better test for this is to see if device_type
4357c478bd9Sstevel@tonic-gate * XXX: from the PROM is "network".
4367c478bd9Sstevel@tonic-gate */
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
4397c478bd9Sstevel@tonic-gate ++netboot;
4407c478bd9Sstevel@tonic-gate
441d62bc4baSyz147064 /*
442d62bc4baSyz147064 * Preload (load-only, no init) the dacf module. We cannot
443d62bc4baSyz147064 * init the module because one of its requisite modules is
444d62bc4baSyz147064 * dld whose _init function will call taskq_create(), which
445d62bc4baSyz147064 * will panic the system at this point.
446d62bc4baSyz147064 */
447d62bc4baSyz147064 if ((err = modloadonly("dacf", "net_dacf")) < 0) {
448d62bc4baSyz147064 cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
449d62bc4baSyz147064 goto out;
450d62bc4baSyz147064 }
4517c478bd9Sstevel@tonic-gate if ((err = modload("misc", "tlimod")) < 0) {
4527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
4537c478bd9Sstevel@tonic-gate goto out;
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate if ((err = modload("strmod", "rpcmod")) < 0) {
4567c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
4577c478bd9Sstevel@tonic-gate goto out;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate if ((err = modload("misc", "nfs_dlboot")) < 0) {
4607c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
4617c478bd9Sstevel@tonic-gate goto out;
4627c478bd9Sstevel@tonic-gate }
46348aa2e6aSseb if ((err = modload("mac", "mac_ether")) < 0) {
46448aa2e6aSseb cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
46548aa2e6aSseb goto out;
46648aa2e6aSseb }
4677c478bd9Sstevel@tonic-gate if ((err = modload("misc", "strplumb")) < 0) {
4687c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
4697c478bd9Sstevel@tonic-gate goto out;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate if ((err = strplumb_load()) < 0) {
4727c478bd9Sstevel@tonic-gate goto out;
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate }
475dedec472SJack Meng if (netboot_over_iscsi() == B_TRUE) {
476dedec472SJack Meng /* iscsi boot */
477dedec472SJack Meng if ((err = modloadonly("dacf", "net_dacf")) < 0) {
478dedec472SJack Meng cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
479dedec472SJack Meng goto out;
480dedec472SJack Meng }
481dedec472SJack Meng if ((err = modload("misc", "tlimod")) < 0) {
482dedec472SJack Meng cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
483dedec472SJack Meng goto out;
484dedec472SJack Meng }
485dedec472SJack Meng if ((err = modload("mac", "mac_ether")) < 0) {
486dedec472SJack Meng cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
487dedec472SJack Meng goto out;
488dedec472SJack Meng }
489dedec472SJack Meng if ((err = modloadonly("drv", "iscsi")) < 0) {
490dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/iscsi\n");
491dedec472SJack Meng goto out;
492dedec472SJack Meng }
493dedec472SJack Meng if ((err = modloadonly("drv", "ssd")) < 0) {
494dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/ssd\n");
495dedec472SJack Meng goto out;
496dedec472SJack Meng }
497dedec472SJack Meng if ((err = modloadonly("drv", "sd")) < 0) {
498dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/sd\n");
499dedec472SJack Meng goto out;
500dedec472SJack Meng }
501dedec472SJack Meng if ((err = modload("misc", "strplumb")) < 0) {
502dedec472SJack Meng cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
503dedec472SJack Meng goto out;
504dedec472SJack Meng }
505dedec472SJack Meng if ((err = strplumb_load()) < 0) {
506dedec472SJack Meng goto out;
507dedec472SJack Meng }
508dedec472SJack Meng }
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate * Preload modules needed for booting as a cluster.
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate err = clboot_loadrootmodules();
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate out:
5157c478bd9Sstevel@tonic-gate if (err != 0 && (boothowto & RB_ASKNAME))
5167c478bd9Sstevel@tonic-gate goto loop;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate return (err);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
521986fd29aSsetje static int
get_bootpath_prop(char * bootpath)522986fd29aSsetje get_bootpath_prop(char *bootpath)
523986fd29aSsetje {
524986fd29aSsetje if (root_is_ramdisk) {
525986fd29aSsetje if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1)
526986fd29aSsetje return (-1);
527986fd29aSsetje (void) strlcat(bootpath, ":a", BO_MAXOBJNAME);
528986fd29aSsetje } else {
529986fd29aSsetje /*
530986fd29aSsetje * Look for the 1275 compliant name 'bootpath' first,
531986fd29aSsetje * but make certain it has a non-NULL value as well.
532986fd29aSsetje */
533986fd29aSsetje if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) ||
534986fd29aSsetje strlen(bootpath) == 0) {
535986fd29aSsetje if (BOP_GETPROP(bootops,
536986fd29aSsetje "boot-path", bootpath) == -1)
537986fd29aSsetje return (-1);
538986fd29aSsetje }
539dedec472SJack Meng if (memcmp(bootpath, BP_ISCSI_DISK,
540dedec472SJack Meng strlen(BP_ISCSI_DISK)) == 0) {
541dedec472SJack Meng /* iscsi boot */
542dedec472SJack Meng get_iscsi_bootpath_vhci(bootpath);
543dedec472SJack Meng }
544986fd29aSsetje }
545986fd29aSsetje return (0);
546986fd29aSsetje }
547986fd29aSsetje
548986fd29aSsetje static int
get_fstype_prop(char * fstype)549986fd29aSsetje get_fstype_prop(char *fstype)
550986fd29aSsetje {
551986fd29aSsetje char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype";
552986fd29aSsetje
553986fd29aSsetje return (BOP_GETPROP(bootops, prop, fstype));
554986fd29aSsetje }
555986fd29aSsetje
5567c478bd9Sstevel@tonic-gate /*
5577c478bd9Sstevel@tonic-gate * Get the name of the root or swap filesystem type, and return
5587c478bd9Sstevel@tonic-gate * the corresponding entry in the vfs switch.
5597c478bd9Sstevel@tonic-gate *
5607c478bd9Sstevel@tonic-gate * If we're not asking the user, and we're trying to find the
5617c478bd9Sstevel@tonic-gate * root filesystem type, we ask boot for the filesystem
5627c478bd9Sstevel@tonic-gate * type that it came from and use that. Similarly, if we're
5637c478bd9Sstevel@tonic-gate * trying to find the swap filesystem, we try and derive it from
5647c478bd9Sstevel@tonic-gate * the root filesystem type.
5657c478bd9Sstevel@tonic-gate *
5667c478bd9Sstevel@tonic-gate * If we are booting via NFS we currently have these options:
5677c478bd9Sstevel@tonic-gate * nfs - dynamically choose NFS V2. V3, or V4 (default)
5687c478bd9Sstevel@tonic-gate * nfs2 - force NFS V2
5697c478bd9Sstevel@tonic-gate * nfs3 - force NFS V3
5707c478bd9Sstevel@tonic-gate * nfs4 - force NFS V4
5717c478bd9Sstevel@tonic-gate * Because we need to maintain backward compatibility with the naming
5727c478bd9Sstevel@tonic-gate * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
5737c478bd9Sstevel@tonic-gate * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic
5747c478bd9Sstevel@tonic-gate * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
575bd93c05dSAlexander Eremin * This is only for root filesystems, all other uses will expect
576bd93c05dSAlexander Eremin * that "nfs" == NFS V2.
5777c478bd9Sstevel@tonic-gate *
5787c478bd9Sstevel@tonic-gate * If the filesystem isn't already loaded, vfs_getvfssw() will load
5797c478bd9Sstevel@tonic-gate * it for us, but if (at the time we call it) modrootloaded is
5807c478bd9Sstevel@tonic-gate * still not set, it won't run the filesystems _init routine (and
5817c478bd9Sstevel@tonic-gate * implicitly it won't run the filesystems vsw_init() entry either).
5827c478bd9Sstevel@tonic-gate * We do that explicitly in rootconf().
5837c478bd9Sstevel@tonic-gate */
5847c478bd9Sstevel@tonic-gate static struct vfssw *
getfstype(char * askfor,char * fsname,size_t fsnamelen)5857c478bd9Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate struct vfssw *vsw;
5887c478bd9Sstevel@tonic-gate static char defaultfs[BO_MAXFSNAME];
5897c478bd9Sstevel@tonic-gate int root = 0;
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) {
592986fd29aSsetje (void) get_fstype_prop(defaultfs);
5937c478bd9Sstevel@tonic-gate root++;
5947c478bd9Sstevel@tonic-gate } else {
5957c478bd9Sstevel@tonic-gate (void) strcpy(defaultfs, "swapfs");
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) {
5997c478bd9Sstevel@tonic-gate for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') {
6007c478bd9Sstevel@tonic-gate printf("%s filesystem type [%s]: ", askfor, defaultfs);
6017c478bd9Sstevel@tonic-gate console_gets(fsname, fsnamelen);
6027c478bd9Sstevel@tonic-gate if (*fsname == '\0')
6037c478bd9Sstevel@tonic-gate (void) strcpy(fsname, defaultfs);
6047c478bd9Sstevel@tonic-gate if (root) {
6057c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0)
6067c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs");
6077c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0)
6087c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn");
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate if ((vsw = vfs_getvfssw(fsname)) != NULL)
6117c478bd9Sstevel@tonic-gate return (vsw);
6127c478bd9Sstevel@tonic-gate printf("Unknown filesystem type '%s'\n", fsname);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate } else if (*fsname == '\0') {
6157c478bd9Sstevel@tonic-gate fsname = defaultfs;
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate if (*fsname == '\0') {
6187c478bd9Sstevel@tonic-gate return (NULL);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate if (root) {
6227c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0)
6237c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs");
6247c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0)
6257c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn");
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate return (vfs_getvfssw(fsname));
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * Get a physical device name, and maybe load and attach
6347c478bd9Sstevel@tonic-gate * the driver.
6357c478bd9Sstevel@tonic-gate *
6367c478bd9Sstevel@tonic-gate * XXX Need better checking of whether or not a device
6377c478bd9Sstevel@tonic-gate * actually exists if the user typed in a pathname.
6387c478bd9Sstevel@tonic-gate *
6397c478bd9Sstevel@tonic-gate * XXX Are we sure we want to expose users to this sort
6407c478bd9Sstevel@tonic-gate * of physical namespace gobbledygook (now there's
6417c478bd9Sstevel@tonic-gate * a word to conjure with..)
6427c478bd9Sstevel@tonic-gate *
6437c478bd9Sstevel@tonic-gate * XXX Note that on an OBP machine, we can easily ask the
6447c478bd9Sstevel@tonic-gate * prom and pretty-print some plausible set of bootable
6457c478bd9Sstevel@tonic-gate * devices. We can also user the prom to verify any
6467c478bd9Sstevel@tonic-gate * such device. Later tim.. later.
6477c478bd9Sstevel@tonic-gate */
6487c478bd9Sstevel@tonic-gate static int
getphysdev(char * askfor,char * name,size_t namelen)6497c478bd9Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate static char fmt[] = "Enter physical name of %s device\n[%s]: ";
6527c478bd9Sstevel@tonic-gate dev_t dev;
6537c478bd9Sstevel@tonic-gate static char defaultpath[BO_MAXOBJNAME];
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /*
6567c478bd9Sstevel@tonic-gate * Establish 'default' values - we get the root device from
6577c478bd9Sstevel@tonic-gate * boot, and we infer the swap device is the same but with
6587c478bd9Sstevel@tonic-gate * a 'b' on the end instead of an 'a'. A first stab at
6597c478bd9Sstevel@tonic-gate * ease-of-use ..
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) {
662986fd29aSsetje if (get_bootpath_prop(defaultpath) == -1)
6637c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE;
6647c478bd9Sstevel@tonic-gate } else {
6657c478bd9Sstevel@tonic-gate (void) strcpy(defaultpath, rootfs.bo_name);
6667c478bd9Sstevel@tonic-gate defaultpath[strlen(defaultpath) - 1] = 'b';
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate retry:
6707c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) {
6717c478bd9Sstevel@tonic-gate printf(fmt, askfor, defaultpath);
6727c478bd9Sstevel@tonic-gate console_gets(name, namelen);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate if (*name == '\0')
6757c478bd9Sstevel@tonic-gate (void) strcpy(name, defaultpath);
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate if (strcmp(askfor, "swap") == 0) {
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate /*
6807c478bd9Sstevel@tonic-gate * Try to load and install the swap device driver.
6817c478bd9Sstevel@tonic-gate */
6827c478bd9Sstevel@tonic-gate dev = ddi_pathname_to_dev_t(name);
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate if (dev == (dev_t)-1) {
6857c478bd9Sstevel@tonic-gate printf("Not a supported device for swap.\n");
6867c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE;
6877c478bd9Sstevel@tonic-gate goto retry;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate /*
6917c478bd9Sstevel@tonic-gate * Ensure that we're not trying to swap on the floppy.
6927c478bd9Sstevel@tonic-gate */
6937c478bd9Sstevel@tonic-gate if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
6947c478bd9Sstevel@tonic-gate printf("Too dangerous to swap on the floppy\n");
6957c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME)
6967c478bd9Sstevel@tonic-gate goto retry;
6977c478bd9Sstevel@tonic-gate return (-1);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate return (0);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate /*
7067c478bd9Sstevel@tonic-gate * Load a driver needed to boot.
7077c478bd9Sstevel@tonic-gate */
7087c478bd9Sstevel@tonic-gate static int
load_boot_driver(char * drv)7097c478bd9Sstevel@tonic-gate load_boot_driver(char *drv)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate char *drvname;
7127c478bd9Sstevel@tonic-gate major_t major;
7131e1ddd6cScth #ifdef sparc
7141e1ddd6cScth struct devnames *dnp;
7151e1ddd6cScth ddi_prop_t *propp;
7161e1ddd6cScth char *module;
7171e1ddd6cScth char *dir, *mf;
7181e1ddd6cScth int plen;
7191e1ddd6cScth int mlen;
7201e1ddd6cScth #endif /* sparc */
7217c478bd9Sstevel@tonic-gate
722a204de77Scth if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
7237c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv);
7247c478bd9Sstevel@tonic-gate return (-1);
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate /*
7277c478bd9Sstevel@tonic-gate * resolve aliases
7287c478bd9Sstevel@tonic-gate */
7297c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major);
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate #ifdef DEBUG
7327c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) {
7337c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s\n", drv));
7347c478bd9Sstevel@tonic-gate } else {
7357c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate #endif /* DEBUG */
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) {
7407c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
7417c478bd9Sstevel@tonic-gate return (-1);
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate
7441e1ddd6cScth #ifdef sparc
7451e1ddd6cScth /*
7461e1ddd6cScth * NOTE: this can be removed when newboot-sparc is delivered.
7471e1ddd6cScth *
7481e1ddd6cScth * Check to see if the driver had a 'ddi-forceload' global driver.conf
7491e1ddd6cScth * property to identify additional modules that need to be loaded.
7501e1ddd6cScth * The driver still needs to use ddi_modopen() to open these modules,
7511e1ddd6cScth * but the 'ddi-forceload' property allows the modules to be loaded
7521e1ddd6cScth * into memory prior to lights-out, so that driver ddi_modopen()
7531e1ddd6cScth * calls during lights-out (when mounting root) will work correctly.
7541e1ddd6cScth * Use of 'ddi-forceload' is only required for drivers involved in
7551e1ddd6cScth * getting root mounted.
7561e1ddd6cScth */
7571e1ddd6cScth dnp = &devnamesp[major];
7581e1ddd6cScth if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
7591e1ddd6cScth ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
7601e1ddd6cScth "ddi-forceload", DDI_PROP_TYPE_STRING,
7611e1ddd6cScth &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {
7621e1ddd6cScth
7631e1ddd6cScth module = (char *)propp->prop_val;
7641e1ddd6cScth plen = propp->prop_len;
7651e1ddd6cScth while (plen > 0) {
7661e1ddd6cScth mlen = strlen(module);
7671e1ddd6cScth mf = strrchr(module, '/');
7681e1ddd6cScth if (mf) {
7691e1ddd6cScth dir = module;
7701e1ddd6cScth *mf++ = '\0'; /* '/' -> '\0' */
7711e1ddd6cScth } else {
7721e1ddd6cScth dir = "misc";
7731e1ddd6cScth mf = module;
7741e1ddd6cScth }
7751e1ddd6cScth if (modloadonly(dir, mf) == -1)
7761e1ddd6cScth cmn_err(CE_CONT,
7771e1ddd6cScth "misc/%s: can't load module\n", mf);
7781e1ddd6cScth if (mf != module)
7791e1ddd6cScth *(mf - 1) = '/'; /* '\0' -> '/' */
7801e1ddd6cScth
7811e1ddd6cScth module += mlen + 1;
7821e1ddd6cScth plen -= mlen + 1;
7831e1ddd6cScth }
7841e1ddd6cScth }
7851e1ddd6cScth #endif /* sparc */
7861e1ddd6cScth
7877c478bd9Sstevel@tonic-gate return (0);
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate /*
7927c478bd9Sstevel@tonic-gate * For a given instance, load that driver and its parents
7937c478bd9Sstevel@tonic-gate */
7947c478bd9Sstevel@tonic-gate static int
load_parent_drivers(dev_info_t * dip,char * path)795f4da9be0Scth load_parent_drivers(dev_info_t *dip, char *path)
7967c478bd9Sstevel@tonic-gate {
7977c478bd9Sstevel@tonic-gate int rval = 0;
798a204de77Scth major_t major = DDI_MAJOR_T_NONE;
7997c478bd9Sstevel@tonic-gate char *drv;
800f4da9be0Scth char *p;
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate while (dip) {
803f4da9be0Scth /* check for path-oriented alias */
804f4da9be0Scth if (path)
805f4da9be0Scth major = ddi_name_to_major(path);
806f4da9be0Scth else
807a204de77Scth major = DDI_MAJOR_T_NONE;
808f4da9be0Scth
809a204de77Scth if (major != DDI_MAJOR_T_NONE)
810f4da9be0Scth drv = ddi_major_to_name(major);
811f4da9be0Scth else
812f4da9be0Scth drv = ddi_binding_name(dip);
813f4da9be0Scth
8147c478bd9Sstevel@tonic-gate if (load_boot_driver(drv) != 0)
8157c478bd9Sstevel@tonic-gate rval = -1;
816f4da9be0Scth
8177c478bd9Sstevel@tonic-gate dip = ddi_get_parent(dip);
818f4da9be0Scth if (path) {
819f4da9be0Scth p = strrchr(path, '/');
820f4da9be0Scth if (p)
821f4da9be0Scth *p = 0;
822f4da9be0Scth }
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate
8257c478bd9Sstevel@tonic-gate return (rval);
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate /*
8307c478bd9Sstevel@tonic-gate * For a given path to a boot device,
8317c478bd9Sstevel@tonic-gate * load that driver and all its parents.
8327c478bd9Sstevel@tonic-gate */
8337c478bd9Sstevel@tonic-gate static int
load_bootpath_drivers(char * bootpath)8347c478bd9Sstevel@tonic-gate load_bootpath_drivers(char *bootpath)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate dev_info_t *dip;
837f4da9be0Scth char *pathcopy;
838f4da9be0Scth int pathcopy_len;
839f4da9be0Scth int rval;
840f4da9be0Scth char *p;
841dedec472SJack Meng int proplen;
842dedec472SJack Meng char iscsi_network_path[BO_MAXOBJNAME];
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate if (bootpath == NULL || *bootpath == 0)
8457c478bd9Sstevel@tonic-gate return (-1);
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
848dedec472SJack Meng #ifdef _OBP
849dedec472SJack Meng if (netboot_over_iscsi()) {
850dedec472SJack Meng /* iscsi boot */
851dedec472SJack Meng if (root_is_ramdisk) {
852b5267ad3SJack Meng if (modloadonly("drv", "ramdisk") < 0)
853b5267ad3SJack Meng return (-1);
854dedec472SJack Meng }
855dedec472SJack Meng proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
856dedec472SJack Meng if (proplen > 0) {
857dedec472SJack Meng if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
858dedec472SJack Meng iscsi_network_path) > 0) {
859dedec472SJack Meng p = strchr(iscsi_network_path, ':');
860dedec472SJack Meng if (p != NULL) {
861dedec472SJack Meng *p = '\0';
862dedec472SJack Meng }
863dedec472SJack Meng pathcopy = i_ddi_strdup(iscsi_network_path,
864dedec472SJack Meng KM_SLEEP);
865dedec472SJack Meng pathcopy_len = strlen(pathcopy) + 1;
866dedec472SJack Meng } else {
867dedec472SJack Meng return (-1);
868dedec472SJack Meng }
869dedec472SJack Meng } else {
870dedec472SJack Meng return (-1);
871dedec472SJack Meng }
872dedec472SJack Meng } else {
873dedec472SJack Meng #endif
874f4da9be0Scth pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
875f4da9be0Scth pathcopy_len = strlen(pathcopy) + 1;
876dedec472SJack Meng #ifdef _OBP
877dedec472SJack Meng }
878dedec472SJack Meng #endif
879f4da9be0Scth dip = path_to_devinfo(pathcopy);
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
8827c478bd9Sstevel@tonic-gate /*
8837c478bd9Sstevel@tonic-gate * i386 does not provide stub nodes for all boot devices,
8847c478bd9Sstevel@tonic-gate * but we should be able to find the node for the parent,
8857c478bd9Sstevel@tonic-gate * and the leaf of the boot path should be the driver name,
8867c478bd9Sstevel@tonic-gate * which we go ahead and load here.
8877c478bd9Sstevel@tonic-gate */
8887c478bd9Sstevel@tonic-gate if (dip == NULL) {
889f4da9be0Scth char *leaf;
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate /*
892f4da9be0Scth * Find last slash to build the full path to the
893f4da9be0Scth * parent of the leaf boot device
8947c478bd9Sstevel@tonic-gate */
895f4da9be0Scth p = strrchr(pathcopy, '/');
8967c478bd9Sstevel@tonic-gate *p++ = 0;
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate * Now isolate the driver name of the leaf device
9007c478bd9Sstevel@tonic-gate */
901f4da9be0Scth leaf = p;
902f4da9be0Scth p = strchr(leaf, '@');
9037c478bd9Sstevel@tonic-gate *p = 0;
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
906f4da9be0Scth bootpath, leaf));
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate dip = path_to_devinfo(pathcopy);
909f4da9be0Scth if (leaf) {
910f4da9be0Scth rval = load_boot_driver(leaf, NULL);
911f4da9be0Scth if (rval == -1) {
912f4da9be0Scth kmem_free(pathcopy, pathcopy_len);
9137c478bd9Sstevel@tonic-gate return (NULL);
914f4da9be0Scth }
915f4da9be0Scth }
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate #endif
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate if (dip == NULL) {
9207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "can't bind driver for boot path <%s>",
9217c478bd9Sstevel@tonic-gate bootpath);
922f4da9be0Scth kmem_free(pathcopy, pathcopy_len);
9237c478bd9Sstevel@tonic-gate return (NULL);
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate /*
9277c478bd9Sstevel@tonic-gate * Load IP over IB driver when netbooting over IB.
9287c478bd9Sstevel@tonic-gate * As per IB 1275 binding, IP over IB is represented as
9297c478bd9Sstevel@tonic-gate * service on the top of the HCA node. So, there is no
9307c478bd9Sstevel@tonic-gate * PROM node and generic framework cannot pre-load
9317c478bd9Sstevel@tonic-gate * IP over IB driver based on the bootpath. The following
9327c478bd9Sstevel@tonic-gate * code preloads IP over IB driver when doing netboot over
9337c478bd9Sstevel@tonic-gate * InfiniBand.
9347c478bd9Sstevel@tonic-gate */
9357c478bd9Sstevel@tonic-gate if (netboot_over_ib(bootpath) &&
9361cfa752fSRamaswamy Tummala modloadonly("drv", "ibp") == -1) {
9371cfa752fSRamaswamy Tummala cmn_err(CE_CONT, "ibp: cannot load platform driver\n");
938f4da9be0Scth kmem_free(pathcopy, pathcopy_len);
9397c478bd9Sstevel@tonic-gate return (NULL);
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate
942c29cc384Svikram /*
943c29cc384Svikram * The PROM node for hubs have incomplete compatible
944c29cc384Svikram * properties and therefore do not bind to the hubd driver.
945c29cc384Svikram * As a result load_bootpath_drivers() loads the usb_mid driver
946c29cc384Svikram * for hub nodes rather than the hubd driver. This causes
947c29cc384Svikram * mountroot failures when booting off USB storage. To prevent
948c29cc384Svikram * this, if we are booting via USB hubs, we preload the hubd driver.
949c29cc384Svikram */
950c29cc384Svikram if (strstr(bootpath, "/hub@") && modloadonly("drv", "hubd") == -1) {
951c29cc384Svikram cmn_err(CE_WARN, "bootpath contains a USB hub, "
952c29cc384Svikram "but cannot load hubd driver");
953c29cc384Svikram }
954c29cc384Svikram
955f4da9be0Scth /* get rid of minor node at end of copy (if not already done above) */
956f4da9be0Scth p = strrchr(pathcopy, '/');
957f4da9be0Scth if (p) {
958f4da9be0Scth p = strchr(p, ':');
959f4da9be0Scth if (p)
960f4da9be0Scth *p = 0;
961f4da9be0Scth }
962f4da9be0Scth
963f4da9be0Scth rval = load_parent_drivers(dip, pathcopy);
964f4da9be0Scth kmem_free(pathcopy, pathcopy_len);
965f4da9be0Scth return (rval);
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate /*
9727c478bd9Sstevel@tonic-gate * Load drivers required for a platform
9737c478bd9Sstevel@tonic-gate * Since all hardware nodes should be available in the device
9747c478bd9Sstevel@tonic-gate * tree, walk the per-driver list and load the parents of
9757c478bd9Sstevel@tonic-gate * each node found. If not a hardware node, try to load it.
9767c478bd9Sstevel@tonic-gate * Pseudo nexus is already loaded.
9777c478bd9Sstevel@tonic-gate */
9787c478bd9Sstevel@tonic-gate static int
load_boot_platform_modules(char * drv)9797c478bd9Sstevel@tonic-gate load_boot_platform_modules(char *drv)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate major_t major;
9827c478bd9Sstevel@tonic-gate dev_info_t *dip;
9837c478bd9Sstevel@tonic-gate char *drvname;
9847c478bd9Sstevel@tonic-gate int rval = 0;
9857c478bd9Sstevel@tonic-gate
986a204de77Scth if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
9877c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv);
9887c478bd9Sstevel@tonic-gate return (-1);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate /*
9927c478bd9Sstevel@tonic-gate * resolve aliases
9937c478bd9Sstevel@tonic-gate */
9947c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major);
995a204de77Scth if ((major = ddi_name_to_major(drvname)) == DDI_MAJOR_T_NONE)
9967c478bd9Sstevel@tonic-gate return (-1);
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate #ifdef DEBUG
9997c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) {
10007c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
10017c478bd9Sstevel@tonic-gate } else {
10027c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
10037c478bd9Sstevel@tonic-gate drv, drvname));
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate #endif /* DEBUG */
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate dip = devnamesp[major].dn_head;
10087c478bd9Sstevel@tonic-gate if (dip == NULL) {
10097c478bd9Sstevel@tonic-gate /* pseudo node, not-enumerated, needs to be loaded */
10107c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) {
10117c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load platform driver\n",
10127c478bd9Sstevel@tonic-gate drvname);
10137c478bd9Sstevel@tonic-gate rval = -1;
10147c478bd9Sstevel@tonic-gate }
10157c478bd9Sstevel@tonic-gate } else {
10167c478bd9Sstevel@tonic-gate while (dip) {
1017f4da9be0Scth if (load_parent_drivers(dip, NULL) != 0)
10187c478bd9Sstevel@tonic-gate rval = -1;
10197c478bd9Sstevel@tonic-gate dip = ddi_get_next(dip);
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate return (rval);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate /*
10287c478bd9Sstevel@tonic-gate * i_find_node: Internal routine used by path_to_devinfo
10297c478bd9Sstevel@tonic-gate * to locate a given nodeid in the device tree.
10307c478bd9Sstevel@tonic-gate */
10317c478bd9Sstevel@tonic-gate struct i_path_findnode {
1032fa9e4066Sahrens pnode_t nodeid;
10337c478bd9Sstevel@tonic-gate dev_info_t *dip;
10347c478bd9Sstevel@tonic-gate };
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate static int
i_path_find_node(dev_info_t * dev,void * arg)10377c478bd9Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg)
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate struct i_path_findnode *f = (struct i_path_findnode *)arg;
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate if (ddi_get_nodeid(dev) == (int)f->nodeid) {
10437c478bd9Sstevel@tonic-gate f->dip = dev;
10447c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE);
10457c478bd9Sstevel@tonic-gate }
10467c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE);
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate /*
10507c478bd9Sstevel@tonic-gate * Return the devinfo node to a boot device
10517c478bd9Sstevel@tonic-gate */
10527c478bd9Sstevel@tonic-gate static dev_info_t *
path_to_devinfo(char * path)10537c478bd9Sstevel@tonic-gate path_to_devinfo(char *path)
10547c478bd9Sstevel@tonic-gate {
10557c478bd9Sstevel@tonic-gate struct i_path_findnode fn;
10567c478bd9Sstevel@tonic-gate extern dev_info_t *top_devinfo;
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate /*
10597c478bd9Sstevel@tonic-gate * Get the nodeid of the given pathname, if such a mapping exists.
10607c478bd9Sstevel@tonic-gate */
10617c478bd9Sstevel@tonic-gate fn.dip = NULL;
10627c478bd9Sstevel@tonic-gate fn.nodeid = prom_finddevice(path);
10637c478bd9Sstevel@tonic-gate if (fn.nodeid != OBP_BADNODE) {
10647c478bd9Sstevel@tonic-gate /*
10657c478bd9Sstevel@tonic-gate * Find the nodeid in our copy of the device tree and return
10667c478bd9Sstevel@tonic-gate * whatever name we used to bind this node to a driver.
10677c478bd9Sstevel@tonic-gate */
10687c478bd9Sstevel@tonic-gate ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate #ifdef DEBUG
10727c478bd9Sstevel@tonic-gate /*
10737c478bd9Sstevel@tonic-gate * If we're bound to something other than the nodename,
10747c478bd9Sstevel@tonic-gate * note that in the message buffer and system log.
10757c478bd9Sstevel@tonic-gate */
10767c478bd9Sstevel@tonic-gate if (fn.dip) {
10777c478bd9Sstevel@tonic-gate char *p, *q;
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate p = ddi_binding_name(fn.dip);
10807c478bd9Sstevel@tonic-gate q = ddi_node_name(fn.dip);
10817c478bd9Sstevel@tonic-gate if (p && q && (strcmp(p, q) != 0)) {
10827c478bd9Sstevel@tonic-gate BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
10837c478bd9Sstevel@tonic-gate path, p));
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate #endif /* DEBUG */
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate return (fn.dip);
10897c478bd9Sstevel@tonic-gate }
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate /*
10927c478bd9Sstevel@tonic-gate * This routine returns B_TRUE if the bootpath corresponds to
10937c478bd9Sstevel@tonic-gate * IP over IB driver.
10947c478bd9Sstevel@tonic-gate *
10957c478bd9Sstevel@tonic-gate * The format of the bootpath for the IP over IB looks like
10967c478bd9Sstevel@tonic-gate * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
10977c478bd9Sstevel@tonic-gate *
10987c478bd9Sstevel@tonic-gate * The minor node portion "port=1,pkey=8001,protocol=ip" represents
10997c478bd9Sstevel@tonic-gate * IP over IB driver.
11007c478bd9Sstevel@tonic-gate */
11017c478bd9Sstevel@tonic-gate static boolean_t
netboot_over_ib(char * bootpath)11027c478bd9Sstevel@tonic-gate netboot_over_ib(char *bootpath)
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate char *temp;
11067c478bd9Sstevel@tonic-gate boolean_t ret = B_FALSE;
1107fa9e4066Sahrens pnode_t node = prom_finddevice(bootpath);
11087c478bd9Sstevel@tonic-gate int len;
11097c478bd9Sstevel@tonic-gate char devicetype[OBP_MAXDRVNAME];
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate /* Is this IB node ? */
1112dedec472SJack Meng if (node == OBP_BADNODE || node == OBP_NONODE) {
1113dedec472SJack Meng return (B_FALSE);
1114dedec472SJack Meng }
11157c478bd9Sstevel@tonic-gate len = prom_getproplen(node, OBP_DEVICETYPE);
11167c478bd9Sstevel@tonic-gate if (len <= 1 || len >= OBP_MAXDRVNAME)
11177c478bd9Sstevel@tonic-gate return (B_FALSE);
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype);
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate if (strncmp("ib", devicetype, 2) == 0) {
11227c478bd9Sstevel@tonic-gate /* Check for proper IP over IB string */
11237c478bd9Sstevel@tonic-gate if ((temp = strstr(bootpath, ":port=")) != NULL) {
11247c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, ",pkey=")) != NULL)
11257c478bd9Sstevel@tonic-gate if ((temp = strstr(temp,
11267c478bd9Sstevel@tonic-gate ",protocol=ip")) != NULL) {
11277c478bd9Sstevel@tonic-gate ret = B_TRUE;
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate }
11317c478bd9Sstevel@tonic-gate return (ret);
11327c478bd9Sstevel@tonic-gate }
1133dedec472SJack Meng
1134dedec472SJack Meng static boolean_t
netboot_over_iscsi(void)1135dedec472SJack Meng netboot_over_iscsi(void)
1136dedec472SJack Meng {
1137dedec472SJack Meng int proplen;
1138dedec472SJack Meng boolean_t ret = B_FALSE;
1139dedec472SJack Meng char bootpath[OBP_MAXPATHLEN];
1140dedec472SJack Meng
1141dedec472SJack Meng proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH);
1142dedec472SJack Meng if (proplen > 0) {
1143dedec472SJack Meng if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) {
1144dedec472SJack Meng if (memcmp(bootpath, BP_ISCSI_DISK,
1145dedec472SJack Meng strlen(BP_ISCSI_DISK)) == 0) {
1146dedec472SJack Meng ret = B_TRUE;
1147dedec472SJack Meng }
1148dedec472SJack Meng }
1149dedec472SJack Meng }
1150dedec472SJack Meng return (ret);
1151dedec472SJack Meng }
1152