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 */ 217c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 227c478bd9Sstevel@tonic-gate /* 23dedec472SJack Meng * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Configure root, swap and dump devices. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/param.h> 347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 357c478bd9Sstevel@tonic-gate #include <sys/signal.h> 367c478bd9Sstevel@tonic-gate #include <sys/cred.h> 377c478bd9Sstevel@tonic-gate #include <sys/proc.h> 387c478bd9Sstevel@tonic-gate #include <sys/user.h> 397c478bd9Sstevel@tonic-gate #include <sys/conf.h> 407c478bd9Sstevel@tonic-gate #include <sys/buf.h> 417c478bd9Sstevel@tonic-gate #include <sys/systm.h> 427c478bd9Sstevel@tonic-gate #include <sys/vm.h> 437c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 447c478bd9Sstevel@tonic-gate #include <sys/file.h> 457c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 467c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 477c478bd9Sstevel@tonic-gate #include <sys/errno.h> 487c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 497c478bd9Sstevel@tonic-gate #include <sys/uio.h> 507c478bd9Sstevel@tonic-gate #include <sys/open.h> 517c478bd9Sstevel@tonic-gate #include <sys/mount.h> 527c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 537c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 547c478bd9Sstevel@tonic-gate #include <sys/sysconf.h> 557c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 567c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 577c478bd9Sstevel@tonic-gate #include <sys/debug.h> 587c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h> 597c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 607c478bd9Sstevel@tonic-gate #include <sys/socket.h> 617c478bd9Sstevel@tonic-gate #include <net/if.h> 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 647c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 657c478bd9Sstevel@tonic-gate #include <sys/console.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include <sys/conf.h> 687c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 697c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 707c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 717c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h> 727c478bd9Sstevel@tonic-gate #include <sys/promif.h> 73dedec472SJack Meng #include <sys/bootprops.h> 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate * Local routines 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate static int preload_module(struct sysparam *, void *); 797c478bd9Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t); 807c478bd9Sstevel@tonic-gate static int getphysdev(char *, char *, size_t); 817c478bd9Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath); 827c478bd9Sstevel@tonic-gate static int load_boot_driver(char *drv); 837c478bd9Sstevel@tonic-gate static int load_boot_platform_modules(char *drv); 847c478bd9Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path); 857c478bd9Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath); 86dedec472SJack Meng static boolean_t netboot_over_iscsi(void); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 92986fd29aSsetje &mod_miscops, "root and swap configuration" 937c478bd9Sstevel@tonic-gate }; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 967c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 977c478bd9Sstevel@tonic-gate }; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate int 1007c478bd9Sstevel@tonic-gate _init(void) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate int 1067c478bd9Sstevel@tonic-gate _fini(void) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate int 1127c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 117dedec472SJack Meng extern ib_boot_prop_t *iscsiboot_prop; 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * Configure root file system. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate int 1227c478bd9Sstevel@tonic-gate rootconf(void) 1237c478bd9Sstevel@tonic-gate { 1247c478bd9Sstevel@tonic-gate int error; 1257c478bd9Sstevel@tonic-gate struct vfssw *vsw; 1267c478bd9Sstevel@tonic-gate extern void pm_init(void); 127dedec472SJack Meng int ret = -1; 1287c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); 1297c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); 1307c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); 1317c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Install cluster modules that were only loaded during 1357c478bd9Sstevel@tonic-gate * loadrootmodules(). 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate if (error = clboot_rootconf()) 1387c478bd9Sstevel@tonic-gate return (error); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (root_is_svm) { 1417c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); 1447c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Run _init on the root filesystem (we already loaded it 1497c478bd9Sstevel@tonic-gate * but we've been waiting until now to _init it) which will 1507c478bd9Sstevel@tonic-gate * have the side-effect of running vsw_init() on this vfs. 1517c478bd9Sstevel@tonic-gate * Because all the nfs filesystems are lumped into one 1527c478bd9Sstevel@tonic-gate * module we need to special case it. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 1557c478bd9Sstevel@tonic-gate if (modload("fs", "nfs") == -1) { 1567c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 1577c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 1587c478bd9Sstevel@tonic-gate return (ENXIO); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } else { 1617c478bd9Sstevel@tonic-gate if (modload("fs", rootfs.bo_fstype) == -1) { 1627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 1637c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 1647c478bd9Sstevel@tonic-gate return (ENXIO); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate RLOCK_VFSSW(); 1687c478bd9Sstevel@tonic-gate vsw = vfs_getvfsswbyname(rootfs.bo_fstype); 1697c478bd9Sstevel@tonic-gate RUNLOCK_VFSSW(); 17056c0b1daSPavel Filipensky if (vsw == NULL) { 17156c0b1daSPavel Filipensky cmn_err(CE_CONT, "Cannot find %s filesystem\n", 17256c0b1daSPavel Filipensky rootfs.bo_fstype); 17356c0b1daSPavel Filipensky return (ENXIO); 17456c0b1daSPavel Filipensky } 1757c478bd9Sstevel@tonic-gate VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); 1767c478bd9Sstevel@tonic-gate VFS_HOLD(rootvfs); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (root_is_svm) { 1797c478bd9Sstevel@tonic-gate rootvfs->vfs_flag |= VFS_RDONLY; 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * This pm-releated call has to occur before root is mounted since we 1847c478bd9Sstevel@tonic-gate * need to power up all devices. It is placed after VFS_INIT() such 1857c478bd9Sstevel@tonic-gate * that opening a device via ddi_lyr_ interface just before root has 1867c478bd9Sstevel@tonic-gate * been mounted would work. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate pm_init(); 1897c478bd9Sstevel@tonic-gate 190dedec472SJack Meng if (netboot && iscsiboot_prop) { 191dedec472SJack Meng cmn_err(CE_WARN, "NFS boot and iSCSI boot" 192dedec472SJack Meng " shouldn't happen in the same time"); 193dedec472SJack Meng return (EINVAL); 194dedec472SJack Meng } 195dedec472SJack Meng 196dedec472SJack Meng if (netboot || iscsiboot_prop) { 197dedec472SJack Meng ret = strplumb(); 198dedec472SJack Meng if (ret != 0) { 199dedec472SJack Meng cmn_err(CE_WARN, "Cannot plumb network device %d", ret); 200dedec472SJack Meng return (EFAULT); 201dedec472SJack Meng } 202dedec472SJack Meng } 203dedec472SJack Meng 204dedec472SJack Meng if ((ret == 0) && iscsiboot_prop) { 205dedec472SJack Meng ret = modload("drv", "iscsi"); 206dedec472SJack Meng /* -1 indicates fail */ 207dedec472SJack Meng if (ret == -1) { 208dedec472SJack Meng cmn_err(CE_WARN, "Failed to load iscsi module"); 209dedec472SJack Meng iscsi_boot_prop_free(); 210dedec472SJack Meng return (EINVAL); 211dedec472SJack Meng } else { 212dedec472SJack Meng if (!i_ddi_attach_pseudo_node("iscsi")) { 213dedec472SJack Meng cmn_err(CE_WARN, 214dedec472SJack Meng "Failed to attach iscsi driver"); 215dedec472SJack Meng iscsi_boot_prop_free(); 216dedec472SJack Meng return (ENODEV); 217dedec472SJack Meng } 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * ufs_mountroot() ends up calling getrootdev() 2237c478bd9Sstevel@tonic-gate * (below) which actually triggers the _init, identify, 2247c478bd9Sstevel@tonic-gate * probe and attach of the drivers that make up root device 2257c478bd9Sstevel@tonic-gate * bush; these are also quietly waiting in memory. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); 2307c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 2317c478bd9Sstevel@tonic-gate rootdev = rootvfs->vfs_dev; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate if (error) 2347c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", 2357c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2367c478bd9Sstevel@tonic-gate else 2377c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root on %s fstype %s\n", 2387c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2397c478bd9Sstevel@tonic-gate return (error); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Remount root on an SVM mirror root device 2447c478bd9Sstevel@tonic-gate * Only supported on UFS filesystems at present 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate int 2477c478bd9Sstevel@tonic-gate svm_rootconf(void) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate int error; 2507c478bd9Sstevel@tonic-gate extern int ufs_remountroot(struct vfs *vfsp); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate ASSERT(root_is_svm == 1); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if (strcmp(rootfs.bo_fstype, "ufs") != 0) { 2557c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Mounting root on %s with filesystem " 2567c478bd9Sstevel@tonic-gate "type %s is not supported\n", 2577c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2587c478bd9Sstevel@tonic-gate return (EINVAL); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name)); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate error = ufs_remountroot(rootvfs); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (error) { 2687c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n", 2697c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2707c478bd9Sstevel@tonic-gate } else { 2717c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root remounted on %s fstype %s\n", 2727c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate return (error); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Under the assumption that our root file system is on a 2797c478bd9Sstevel@tonic-gate * disk partition, get the dev_t of the partition in question. 2807c478bd9Sstevel@tonic-gate * 2817c478bd9Sstevel@tonic-gate * By now, boot has faithfully loaded all our modules into memory, and 2827c478bd9Sstevel@tonic-gate * we've taken over resource management. Before we go any further, we 2837c478bd9Sstevel@tonic-gate * have to fire up the device drivers and stuff we need to mount the 2847c478bd9Sstevel@tonic-gate * root filesystem. That's what we do here. Fingers crossed. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate dev_t 2877c478bd9Sstevel@tonic-gate getrootdev(void) 2887c478bd9Sstevel@tonic-gate { 2897c478bd9Sstevel@tonic-gate dev_t d; 2907c478bd9Sstevel@tonic-gate 291dedec472SJack Meng d = ddi_pathname_to_dev_t(rootfs.bo_name); 292dedec472SJack Meng if ((d == NODEV) && (iscsiboot_prop != NULL)) { 293dedec472SJack Meng /* Give it another try with the 'disk' path */ 294dedec472SJack Meng get_iscsi_bootpath_phy(rootfs.bo_name); 295dedec472SJack Meng d = ddi_pathname_to_dev_t(rootfs.bo_name); 296dedec472SJack Meng } 297dedec472SJack Meng if (d == NODEV) 2987c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n", 2997c478bd9Sstevel@tonic-gate rootfs.bo_name); 3007c478bd9Sstevel@tonic-gate return (d); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * If booted with ASKNAME, prompt on the console for a filesystem 3057c478bd9Sstevel@tonic-gate * name and return it. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate void 3087c478bd9Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen) 3097c478bd9Sstevel@tonic-gate { 3107c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 3117c478bd9Sstevel@tonic-gate printf("%s name: ", askfor); 3127c478bd9Sstevel@tonic-gate console_gets(name, namelen); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3177c478bd9Sstevel@tonic-gate static int 3187c478bd9Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p) 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate static char *wmesg = "forceload of %s failed"; 3217c478bd9Sstevel@tonic-gate char *name; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate name = sysp->sys_ptr; 3247c478bd9Sstevel@tonic-gate BMDPRINTF(("preload_module: %s\n", name)); 3257c478bd9Sstevel@tonic-gate if (modloadonly(NULL, name) < 0) 3267c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, wmesg, name); 3277c478bd9Sstevel@tonic-gate return (0); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * We want to load all the modules needed to mount the root filesystem, 3337c478bd9Sstevel@tonic-gate * so that when we start the ball rolling in 'getrootdev', every module 3347c478bd9Sstevel@tonic-gate * should already be in memory, just waiting to be init-ed. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate int 3387c478bd9Sstevel@tonic-gate loadrootmodules(void) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate struct vfssw *vsw; 3417c478bd9Sstevel@tonic-gate char *this; 3427c478bd9Sstevel@tonic-gate char *name; 3437c478bd9Sstevel@tonic-gate int err; 3447c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 345986fd29aSsetje int i, proplen; 3467c478bd9Sstevel@tonic-gate extern char *impl_module_list[]; 3477c478bd9Sstevel@tonic-gate extern char *platform_module_list[]; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* Make sure that the PROM's devinfo tree has been created */ 3507c478bd9Sstevel@tonic-gate ASSERT(ddi_root_node()); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype)); 3537c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name)); 3547c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags)); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * zzz We need to honor what's in rootfs if it's not null. 3587c478bd9Sstevel@tonic-gate * non-null means use what's there. This way we can 3597c478bd9Sstevel@tonic-gate * change rootfs with /etc/system AND with tunetool. 3607c478bd9Sstevel@tonic-gate */ 3617c478bd9Sstevel@tonic-gate if (root_is_svm) { 3627c478bd9Sstevel@tonic-gate /* user replaced rootdev, record obp_bootpath */ 3637c478bd9Sstevel@tonic-gate obp_bootpath[0] = '\0'; 3647c478bd9Sstevel@tonic-gate (void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME); 3657c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 3667c478bd9Sstevel@tonic-gate } else { 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Get the root fstype and root device path from boot. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate rootfs.bo_fstype[0] = '\0'; 3717c478bd9Sstevel@tonic-gate rootfs.bo_name[0] = '\0'; 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * This lookup will result in modloadonly-ing the root 3767c478bd9Sstevel@tonic-gate * filesystem module - it gets _init-ed in rootconf() 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL) 3797c478bd9Sstevel@tonic-gate return (ENXIO); /* in case we have no file system types */ 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate (void) strcpy(rootfs.bo_fstype, vsw->vsw_name); 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * Load the favored drivers of the implementation. 3877c478bd9Sstevel@tonic-gate * e.g. 'sbus' and possibly 'zs' (even). 3887c478bd9Sstevel@tonic-gate * 3897c478bd9Sstevel@tonic-gate * Called whilst boot is still loaded (because boot does 3907c478bd9Sstevel@tonic-gate * the i/o for us), and DDI services are unavailable. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: impl_module_list\n")); 3937c478bd9Sstevel@tonic-gate for (i = 0; (this = impl_module_list[i]) != NULL; i++) { 3947c478bd9Sstevel@tonic-gate if ((err = load_boot_driver(this)) != 0) { 3957c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 3967c478bd9Sstevel@tonic-gate return (err); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * Now load the platform modules (if any) 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: platform_module_list\n")); 4037c478bd9Sstevel@tonic-gate for (i = 0; (this = platform_module_list[i]) != NULL; i++) { 4047c478bd9Sstevel@tonic-gate if ((err = load_boot_platform_modules(this)) != 0) { 4057c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 4067c478bd9Sstevel@tonic-gate return (err); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate loop: 4117c478bd9Sstevel@tonic-gate (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME); 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * Given a physical pathname, load the correct set of driver 4147c478bd9Sstevel@tonic-gate * modules into memory, including all possible parents. 4157c478bd9Sstevel@tonic-gate * 4167c478bd9Sstevel@tonic-gate * NB: The code sets the variable 'name' for error reporting. 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate err = 0; 4197c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 4207c478bd9Sstevel@tonic-gate if (root_is_svm == 0) { 4217c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 4227c478bd9Sstevel@tonic-gate name = rootfs.bo_name; 4237c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(rootfs.bo_name); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Load driver modules in obp_bootpath, this is always 4287c478bd9Sstevel@tonic-gate * required for mountroot to succeed. obp_bootpath is 4297c478bd9Sstevel@tonic-gate * is set if rootdev is set via /etc/system, which is 4307c478bd9Sstevel@tonic-gate * the case if booting of a SVM/VxVM mirror. 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate if ((err == 0) && obp_bootpath[0] != '\0') { 4337c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 4347c478bd9Sstevel@tonic-gate name = obp_bootpath; 4357c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(obp_bootpath); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate if (err != 0) { 4397c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load drivers for %s\n", name); 4407c478bd9Sstevel@tonic-gate goto out; 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Check to see if the booter performed DHCP configuration 4457c478bd9Sstevel@tonic-gate * ("bootp-response" boot property exists). If so, then before 4467c478bd9Sstevel@tonic-gate * bootops disappears we need to save the value of this property 4477c478bd9Sstevel@tonic-gate * such that the userland dhcpagent can adopt the DHCP management 448986fd29aSsetje * of our primary network interface. 4497c478bd9Sstevel@tonic-gate */ 4507c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "bootp-response"); 4517c478bd9Sstevel@tonic-gate if (proplen > 0) { 452986fd29aSsetje dhcack = kmem_zalloc(proplen, KM_SLEEP); 453986fd29aSsetje if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) { 4547c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 4557c478bd9Sstevel@tonic-gate "\"bootp-response\" failed\n"); 4567c478bd9Sstevel@tonic-gate kmem_free(dhcack, dhcacklen); 4577c478bd9Sstevel@tonic-gate dhcack = NULL; 4587c478bd9Sstevel@tonic-gate goto out; 4597c478bd9Sstevel@tonic-gate } 460986fd29aSsetje dhcacklen = proplen; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate /* 4637c478bd9Sstevel@tonic-gate * Fetch the "netdev-path" boot property (if it exists), and 4647c478bd9Sstevel@tonic-gate * stash it for later use by sysinfo(SI_DHCP_CACHE, ...). 4657c478bd9Sstevel@tonic-gate */ 4667c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "netdev-path"); 4677c478bd9Sstevel@tonic-gate if (proplen > 0) { 4687c478bd9Sstevel@tonic-gate netdev_path = kmem_zalloc(proplen, KM_SLEEP); 4697c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "netdev-path", 4707c478bd9Sstevel@tonic-gate (uchar_t *)netdev_path) == -1) { 4717c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 4727c478bd9Sstevel@tonic-gate "\"netdev-path\" failed\n"); 4737c478bd9Sstevel@tonic-gate kmem_free(netdev_path, proplen); 4747c478bd9Sstevel@tonic-gate goto out; 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* 4807c478bd9Sstevel@tonic-gate * Preload (load-only, no init) all modules which 4817c478bd9Sstevel@tonic-gate * were added to the /etc/system file with the 4827c478bd9Sstevel@tonic-gate * FORCELOAD keyword. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: preload_module\n")); 4857c478bd9Sstevel@tonic-gate (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * If we booted otw then load in the plumbing 4907c478bd9Sstevel@tonic-gate * routine now while we still can. If we didn't 4917c478bd9Sstevel@tonic-gate * boot otw then we will load strplumb in main(). 4927c478bd9Sstevel@tonic-gate * 4937c478bd9Sstevel@tonic-gate * NFS is actually a set of modules, the core routines, 4947c478bd9Sstevel@tonic-gate * a diskless helper module, rpcmod, and the tli interface. Load 4957c478bd9Sstevel@tonic-gate * them now while we still can. 4967c478bd9Sstevel@tonic-gate * 4977c478bd9Sstevel@tonic-gate * Because we glomb all versions of nfs into a single module 4987c478bd9Sstevel@tonic-gate * we check based on the initial string "nfs". 4997c478bd9Sstevel@tonic-gate * 5007c478bd9Sstevel@tonic-gate * XXX: A better test for this is to see if device_type 5017c478bd9Sstevel@tonic-gate * XXX: from the PROM is "network". 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 5057c478bd9Sstevel@tonic-gate ++netboot; 5067c478bd9Sstevel@tonic-gate 507d62bc4baSyz147064 /* 508d62bc4baSyz147064 * Preload (load-only, no init) the dacf module. We cannot 509d62bc4baSyz147064 * init the module because one of its requisite modules is 510d62bc4baSyz147064 * dld whose _init function will call taskq_create(), which 511d62bc4baSyz147064 * will panic the system at this point. 512d62bc4baSyz147064 */ 513d62bc4baSyz147064 if ((err = modloadonly("dacf", "net_dacf")) < 0) { 514d62bc4baSyz147064 cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n"); 515d62bc4baSyz147064 goto out; 516d62bc4baSyz147064 } 5177c478bd9Sstevel@tonic-gate if ((err = modload("misc", "tlimod")) < 0) { 5187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/tlimod\n"); 5197c478bd9Sstevel@tonic-gate goto out; 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if ((err = modload("strmod", "rpcmod")) < 0) { 5227c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n"); 5237c478bd9Sstevel@tonic-gate goto out; 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate if ((err = modload("misc", "nfs_dlboot")) < 0) { 5267c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n"); 5277c478bd9Sstevel@tonic-gate goto out; 5287c478bd9Sstevel@tonic-gate } 52948aa2e6aSseb if ((err = modload("mac", "mac_ether")) < 0) { 53048aa2e6aSseb cmn_err(CE_CONT, "Cannot load mac/mac_ether\n"); 53148aa2e6aSseb goto out; 53248aa2e6aSseb } 5337c478bd9Sstevel@tonic-gate if ((err = modload("misc", "strplumb")) < 0) { 5347c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/strplumb\n"); 5357c478bd9Sstevel@tonic-gate goto out; 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate if ((err = strplumb_load()) < 0) { 5387c478bd9Sstevel@tonic-gate goto out; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate } 541dedec472SJack Meng if (netboot_over_iscsi() == B_TRUE) { 542dedec472SJack Meng /* iscsi boot */ 543dedec472SJack Meng if ((err = modloadonly("dacf", "net_dacf")) < 0) { 544dedec472SJack Meng cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n"); 545dedec472SJack Meng goto out; 546dedec472SJack Meng } 547dedec472SJack Meng if ((err = modload("misc", "tlimod")) < 0) { 548dedec472SJack Meng cmn_err(CE_CONT, "Cannot load misc/tlimod\n"); 549dedec472SJack Meng goto out; 550dedec472SJack Meng } 551dedec472SJack Meng if ((err = modload("mac", "mac_ether")) < 0) { 552dedec472SJack Meng cmn_err(CE_CONT, "Cannot load mac/mac_ether\n"); 553dedec472SJack Meng goto out; 554dedec472SJack Meng } 555dedec472SJack Meng if ((err = modloadonly("drv", "iscsi")) < 0) { 556dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/iscsi\n"); 557dedec472SJack Meng goto out; 558dedec472SJack Meng } 559dedec472SJack Meng if ((err = modloadonly("drv", "ssd")) < 0) { 560dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/ssd\n"); 561dedec472SJack Meng goto out; 562dedec472SJack Meng } 563dedec472SJack Meng if ((err = modloadonly("drv", "sd")) < 0) { 564dedec472SJack Meng cmn_err(CE_CONT, "Cannot load drv/sd\n"); 565dedec472SJack Meng goto out; 566dedec472SJack Meng } 567dedec472SJack Meng if ((err = modload("misc", "strplumb")) < 0) { 568dedec472SJack Meng cmn_err(CE_CONT, "Cannot load misc/strplumb\n"); 569dedec472SJack Meng goto out; 570dedec472SJack Meng } 571dedec472SJack Meng if ((err = strplumb_load()) < 0) { 572dedec472SJack Meng goto out; 573dedec472SJack Meng } 574dedec472SJack Meng } 5757c478bd9Sstevel@tonic-gate /* 5767c478bd9Sstevel@tonic-gate * Preload modules needed for booting as a cluster. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate err = clboot_loadrootmodules(); 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate out: 5817c478bd9Sstevel@tonic-gate if (err != 0 && (boothowto & RB_ASKNAME)) 5827c478bd9Sstevel@tonic-gate goto loop; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate return (err); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 5877c478bd9Sstevel@tonic-gate 588986fd29aSsetje static int 589986fd29aSsetje get_bootpath_prop(char *bootpath) 590986fd29aSsetje { 591986fd29aSsetje if (root_is_ramdisk) { 592986fd29aSsetje if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1) 593986fd29aSsetje return (-1); 594986fd29aSsetje (void) strlcat(bootpath, ":a", BO_MAXOBJNAME); 595986fd29aSsetje } else { 596986fd29aSsetje /* 597986fd29aSsetje * Look for the 1275 compliant name 'bootpath' first, 598986fd29aSsetje * but make certain it has a non-NULL value as well. 599986fd29aSsetje */ 600986fd29aSsetje if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) || 601986fd29aSsetje strlen(bootpath) == 0) { 602986fd29aSsetje if (BOP_GETPROP(bootops, 603986fd29aSsetje "boot-path", bootpath) == -1) 604986fd29aSsetje return (-1); 605986fd29aSsetje } 606dedec472SJack Meng if (memcmp(bootpath, BP_ISCSI_DISK, 607dedec472SJack Meng strlen(BP_ISCSI_DISK)) == 0) { 608dedec472SJack Meng /* iscsi boot */ 609dedec472SJack Meng get_iscsi_bootpath_vhci(bootpath); 610dedec472SJack Meng } 611986fd29aSsetje } 612986fd29aSsetje return (0); 613986fd29aSsetje } 614986fd29aSsetje 615986fd29aSsetje static int 616986fd29aSsetje get_fstype_prop(char *fstype) 617986fd29aSsetje { 618986fd29aSsetje char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype"; 619986fd29aSsetje 620986fd29aSsetje return (BOP_GETPROP(bootops, prop, fstype)); 621986fd29aSsetje } 622986fd29aSsetje 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Get the name of the root or swap filesystem type, and return 6257c478bd9Sstevel@tonic-gate * the corresponding entry in the vfs switch. 6267c478bd9Sstevel@tonic-gate * 6277c478bd9Sstevel@tonic-gate * If we're not asking the user, and we're trying to find the 6287c478bd9Sstevel@tonic-gate * root filesystem type, we ask boot for the filesystem 6297c478bd9Sstevel@tonic-gate * type that it came from and use that. Similarly, if we're 6307c478bd9Sstevel@tonic-gate * trying to find the swap filesystem, we try and derive it from 6317c478bd9Sstevel@tonic-gate * the root filesystem type. 6327c478bd9Sstevel@tonic-gate * 6337c478bd9Sstevel@tonic-gate * If we are booting via NFS we currently have these options: 6347c478bd9Sstevel@tonic-gate * nfs - dynamically choose NFS V2. V3, or V4 (default) 6357c478bd9Sstevel@tonic-gate * nfs2 - force NFS V2 6367c478bd9Sstevel@tonic-gate * nfs3 - force NFS V3 6377c478bd9Sstevel@tonic-gate * nfs4 - force NFS V4 6387c478bd9Sstevel@tonic-gate * Because we need to maintain backward compatibility with the naming 6397c478bd9Sstevel@tonic-gate * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c) 6407c478bd9Sstevel@tonic-gate * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic 6417c478bd9Sstevel@tonic-gate * nfs module will map the type back to either "nfs", "nfs3", or "nfs4". 6427c478bd9Sstevel@tonic-gate * This is only for root filesystems, all other uses such as cachefs 6437c478bd9Sstevel@tonic-gate * will expect that "nfs" == NFS V2. 6447c478bd9Sstevel@tonic-gate * 6457c478bd9Sstevel@tonic-gate * If the filesystem isn't already loaded, vfs_getvfssw() will load 6467c478bd9Sstevel@tonic-gate * it for us, but if (at the time we call it) modrootloaded is 6477c478bd9Sstevel@tonic-gate * still not set, it won't run the filesystems _init routine (and 6487c478bd9Sstevel@tonic-gate * implicitly it won't run the filesystems vsw_init() entry either). 6497c478bd9Sstevel@tonic-gate * We do that explicitly in rootconf(). 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate static struct vfssw * 6527c478bd9Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate struct vfssw *vsw; 6557c478bd9Sstevel@tonic-gate static char defaultfs[BO_MAXFSNAME]; 6567c478bd9Sstevel@tonic-gate int root = 0; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 659986fd29aSsetje (void) get_fstype_prop(defaultfs); 6607c478bd9Sstevel@tonic-gate root++; 6617c478bd9Sstevel@tonic-gate } else { 6627c478bd9Sstevel@tonic-gate (void) strcpy(defaultfs, "swapfs"); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 6667c478bd9Sstevel@tonic-gate for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') { 6677c478bd9Sstevel@tonic-gate printf("%s filesystem type [%s]: ", askfor, defaultfs); 6687c478bd9Sstevel@tonic-gate console_gets(fsname, fsnamelen); 6697c478bd9Sstevel@tonic-gate if (*fsname == '\0') 6707c478bd9Sstevel@tonic-gate (void) strcpy(fsname, defaultfs); 6717c478bd9Sstevel@tonic-gate if (root) { 6727c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 6737c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 6747c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 6757c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate if ((vsw = vfs_getvfssw(fsname)) != NULL) 6787c478bd9Sstevel@tonic-gate return (vsw); 6797c478bd9Sstevel@tonic-gate printf("Unknown filesystem type '%s'\n", fsname); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate } else if (*fsname == '\0') { 6827c478bd9Sstevel@tonic-gate fsname = defaultfs; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate if (*fsname == '\0') { 6857c478bd9Sstevel@tonic-gate return (NULL); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (root) { 6897c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 6907c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 6917c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 6927c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (vfs_getvfssw(fsname)); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* 7007c478bd9Sstevel@tonic-gate * Get a physical device name, and maybe load and attach 7017c478bd9Sstevel@tonic-gate * the driver. 7027c478bd9Sstevel@tonic-gate * 7037c478bd9Sstevel@tonic-gate * XXX Need better checking of whether or not a device 7047c478bd9Sstevel@tonic-gate * actually exists if the user typed in a pathname. 7057c478bd9Sstevel@tonic-gate * 7067c478bd9Sstevel@tonic-gate * XXX Are we sure we want to expose users to this sort 7077c478bd9Sstevel@tonic-gate * of physical namespace gobbledygook (now there's 7087c478bd9Sstevel@tonic-gate * a word to conjure with..) 7097c478bd9Sstevel@tonic-gate * 7107c478bd9Sstevel@tonic-gate * XXX Note that on an OBP machine, we can easily ask the 7117c478bd9Sstevel@tonic-gate * prom and pretty-print some plausible set of bootable 7127c478bd9Sstevel@tonic-gate * devices. We can also user the prom to verify any 7137c478bd9Sstevel@tonic-gate * such device. Later tim.. later. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate static int 7167c478bd9Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen) 7177c478bd9Sstevel@tonic-gate { 7187c478bd9Sstevel@tonic-gate static char fmt[] = "Enter physical name of %s device\n[%s]: "; 7197c478bd9Sstevel@tonic-gate dev_t dev; 7207c478bd9Sstevel@tonic-gate static char defaultpath[BO_MAXOBJNAME]; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * Establish 'default' values - we get the root device from 7247c478bd9Sstevel@tonic-gate * boot, and we infer the swap device is the same but with 7257c478bd9Sstevel@tonic-gate * a 'b' on the end instead of an 'a'. A first stab at 7267c478bd9Sstevel@tonic-gate * ease-of-use .. 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 729986fd29aSsetje if (get_bootpath_prop(defaultpath) == -1) 7307c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 7317c478bd9Sstevel@tonic-gate } else { 7327c478bd9Sstevel@tonic-gate (void) strcpy(defaultpath, rootfs.bo_name); 7337c478bd9Sstevel@tonic-gate defaultpath[strlen(defaultpath) - 1] = 'b'; 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate retry: 7377c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 7387c478bd9Sstevel@tonic-gate printf(fmt, askfor, defaultpath); 7397c478bd9Sstevel@tonic-gate console_gets(name, namelen); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate if (*name == '\0') 7427c478bd9Sstevel@tonic-gate (void) strcpy(name, defaultpath); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate if (strcmp(askfor, "swap") == 0) { 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * Try to load and install the swap device driver. 7487c478bd9Sstevel@tonic-gate */ 7497c478bd9Sstevel@tonic-gate dev = ddi_pathname_to_dev_t(name); 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate if (dev == (dev_t)-1) { 7527c478bd9Sstevel@tonic-gate printf("Not a supported device for swap.\n"); 7537c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 7547c478bd9Sstevel@tonic-gate goto retry; 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate /* 7587c478bd9Sstevel@tonic-gate * Ensure that we're not trying to swap on the floppy. 7597c478bd9Sstevel@tonic-gate */ 7607c478bd9Sstevel@tonic-gate if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) { 7617c478bd9Sstevel@tonic-gate printf("Too dangerous to swap on the floppy\n"); 7627c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) 7637c478bd9Sstevel@tonic-gate goto retry; 7647c478bd9Sstevel@tonic-gate return (-1); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate return (0); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * Load a driver needed to boot. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate static int 7767c478bd9Sstevel@tonic-gate load_boot_driver(char *drv) 7777c478bd9Sstevel@tonic-gate { 7787c478bd9Sstevel@tonic-gate char *drvname; 7797c478bd9Sstevel@tonic-gate major_t major; 7801e1ddd6cScth #ifdef sparc 7811e1ddd6cScth struct devnames *dnp; 7821e1ddd6cScth ddi_prop_t *propp; 7831e1ddd6cScth char *module; 7841e1ddd6cScth char *dir, *mf; 7851e1ddd6cScth int plen; 7861e1ddd6cScth int mlen; 7871e1ddd6cScth #endif /* sparc */ 7887c478bd9Sstevel@tonic-gate 789a204de77Scth if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) { 7907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 7917c478bd9Sstevel@tonic-gate return (-1); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * resolve aliases 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate #ifdef DEBUG 7997c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 8007c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s\n", drv)); 8017c478bd9Sstevel@tonic-gate } else { 8027c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname)); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 8077c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load driver\n", drvname); 8087c478bd9Sstevel@tonic-gate return (-1); 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8111e1ddd6cScth #ifdef sparc 8121e1ddd6cScth /* 8131e1ddd6cScth * NOTE: this can be removed when newboot-sparc is delivered. 8141e1ddd6cScth * 8151e1ddd6cScth * Check to see if the driver had a 'ddi-forceload' global driver.conf 8161e1ddd6cScth * property to identify additional modules that need to be loaded. 8171e1ddd6cScth * The driver still needs to use ddi_modopen() to open these modules, 8181e1ddd6cScth * but the 'ddi-forceload' property allows the modules to be loaded 8191e1ddd6cScth * into memory prior to lights-out, so that driver ddi_modopen() 8201e1ddd6cScth * calls during lights-out (when mounting root) will work correctly. 8211e1ddd6cScth * Use of 'ddi-forceload' is only required for drivers involved in 8221e1ddd6cScth * getting root mounted. 8231e1ddd6cScth */ 8241e1ddd6cScth dnp = &devnamesp[major]; 8251e1ddd6cScth if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list && 8261e1ddd6cScth ((propp = i_ddi_prop_search(DDI_DEV_T_ANY, 8271e1ddd6cScth "ddi-forceload", DDI_PROP_TYPE_STRING, 8281e1ddd6cScth &dnp->dn_global_prop_ptr->prop_list)) != NULL)) { 8291e1ddd6cScth 8301e1ddd6cScth module = (char *)propp->prop_val; 8311e1ddd6cScth plen = propp->prop_len; 8321e1ddd6cScth while (plen > 0) { 8331e1ddd6cScth mlen = strlen(module); 8341e1ddd6cScth mf = strrchr(module, '/'); 8351e1ddd6cScth if (mf) { 8361e1ddd6cScth dir = module; 8371e1ddd6cScth *mf++ = '\0'; /* '/' -> '\0' */ 8381e1ddd6cScth } else { 8391e1ddd6cScth dir = "misc"; 8401e1ddd6cScth mf = module; 8411e1ddd6cScth } 8421e1ddd6cScth if (modloadonly(dir, mf) == -1) 8431e1ddd6cScth cmn_err(CE_CONT, 8441e1ddd6cScth "misc/%s: can't load module\n", mf); 8451e1ddd6cScth if (mf != module) 8461e1ddd6cScth *(mf - 1) = '/'; /* '\0' -> '/' */ 8471e1ddd6cScth 8481e1ddd6cScth module += mlen + 1; 8491e1ddd6cScth plen -= mlen + 1; 8501e1ddd6cScth } 8511e1ddd6cScth } 8521e1ddd6cScth #endif /* sparc */ 8531e1ddd6cScth 8547c478bd9Sstevel@tonic-gate return (0); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * For a given instance, load that driver and its parents 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate static int 862f4da9be0Scth load_parent_drivers(dev_info_t *dip, char *path) 8637c478bd9Sstevel@tonic-gate { 8647c478bd9Sstevel@tonic-gate int rval = 0; 865a204de77Scth major_t major = DDI_MAJOR_T_NONE; 8667c478bd9Sstevel@tonic-gate char *drv; 867f4da9be0Scth char *p; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate while (dip) { 870f4da9be0Scth /* check for path-oriented alias */ 871f4da9be0Scth if (path) 872f4da9be0Scth major = ddi_name_to_major(path); 873f4da9be0Scth else 874a204de77Scth major = DDI_MAJOR_T_NONE; 875f4da9be0Scth 876a204de77Scth if (major != DDI_MAJOR_T_NONE) 877f4da9be0Scth drv = ddi_major_to_name(major); 878f4da9be0Scth else 879f4da9be0Scth drv = ddi_binding_name(dip); 880f4da9be0Scth 8817c478bd9Sstevel@tonic-gate if (load_boot_driver(drv) != 0) 8827c478bd9Sstevel@tonic-gate rval = -1; 883f4da9be0Scth 8847c478bd9Sstevel@tonic-gate dip = ddi_get_parent(dip); 885f4da9be0Scth if (path) { 886f4da9be0Scth p = strrchr(path, '/'); 887f4da9be0Scth if (p) 888f4da9be0Scth *p = 0; 889f4da9be0Scth } 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate return (rval); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate /* 8977c478bd9Sstevel@tonic-gate * For a given path to a boot device, 8987c478bd9Sstevel@tonic-gate * load that driver and all its parents. 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate static int 9017c478bd9Sstevel@tonic-gate load_bootpath_drivers(char *bootpath) 9027c478bd9Sstevel@tonic-gate { 9037c478bd9Sstevel@tonic-gate dev_info_t *dip; 904f4da9be0Scth char *pathcopy; 905f4da9be0Scth int pathcopy_len; 906f4da9be0Scth int rval; 907f4da9be0Scth char *p; 908dedec472SJack Meng int proplen; 909dedec472SJack Meng char iscsi_network_path[BO_MAXOBJNAME]; 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate if (bootpath == NULL || *bootpath == 0) 9127c478bd9Sstevel@tonic-gate return (-1); 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath)); 915dedec472SJack Meng #ifdef _OBP 916dedec472SJack Meng if (netboot_over_iscsi()) { 917dedec472SJack Meng /* iscsi boot */ 918dedec472SJack Meng if (root_is_ramdisk) { 919*b5267ad3SJack Meng if (modloadonly("drv", "ramdisk") < 0) 920*b5267ad3SJack Meng return (-1); 921dedec472SJack Meng } 922dedec472SJack Meng proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH); 923dedec472SJack Meng if (proplen > 0) { 924dedec472SJack Meng if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH, 925dedec472SJack Meng iscsi_network_path) > 0) { 926dedec472SJack Meng p = strchr(iscsi_network_path, ':'); 927dedec472SJack Meng if (p != NULL) { 928dedec472SJack Meng *p = '\0'; 929dedec472SJack Meng } 930dedec472SJack Meng pathcopy = i_ddi_strdup(iscsi_network_path, 931dedec472SJack Meng KM_SLEEP); 932dedec472SJack Meng pathcopy_len = strlen(pathcopy) + 1; 933dedec472SJack Meng } else { 934dedec472SJack Meng return (-1); 935dedec472SJack Meng } 936dedec472SJack Meng } else { 937dedec472SJack Meng return (-1); 938dedec472SJack Meng } 939dedec472SJack Meng } else { 940dedec472SJack Meng #endif 941f4da9be0Scth pathcopy = i_ddi_strdup(bootpath, KM_SLEEP); 942f4da9be0Scth pathcopy_len = strlen(pathcopy) + 1; 943dedec472SJack Meng #ifdef _OBP 944dedec472SJack Meng } 945dedec472SJack Meng #endif 946f4da9be0Scth dip = path_to_devinfo(pathcopy); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 9497c478bd9Sstevel@tonic-gate /* 9507c478bd9Sstevel@tonic-gate * i386 does not provide stub nodes for all boot devices, 9517c478bd9Sstevel@tonic-gate * but we should be able to find the node for the parent, 9527c478bd9Sstevel@tonic-gate * and the leaf of the boot path should be the driver name, 9537c478bd9Sstevel@tonic-gate * which we go ahead and load here. 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate if (dip == NULL) { 956f4da9be0Scth char *leaf; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 959f4da9be0Scth * Find last slash to build the full path to the 960f4da9be0Scth * parent of the leaf boot device 9617c478bd9Sstevel@tonic-gate */ 962f4da9be0Scth p = strrchr(pathcopy, '/'); 9637c478bd9Sstevel@tonic-gate *p++ = 0; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * Now isolate the driver name of the leaf device 9677c478bd9Sstevel@tonic-gate */ 968f4da9be0Scth leaf = p; 969f4da9be0Scth p = strchr(leaf, '@'); 9707c478bd9Sstevel@tonic-gate *p = 0; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n", 973f4da9be0Scth bootpath, leaf)); 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate dip = path_to_devinfo(pathcopy); 976f4da9be0Scth if (leaf) { 977f4da9be0Scth rval = load_boot_driver(leaf, NULL); 978f4da9be0Scth if (rval == -1) { 979f4da9be0Scth kmem_free(pathcopy, pathcopy_len); 9807c478bd9Sstevel@tonic-gate return (NULL); 981f4da9be0Scth } 982f4da9be0Scth } 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate #endif 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate if (dip == NULL) { 9877c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "can't bind driver for boot path <%s>", 9887c478bd9Sstevel@tonic-gate bootpath); 989f4da9be0Scth kmem_free(pathcopy, pathcopy_len); 9907c478bd9Sstevel@tonic-gate return (NULL); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * Load IP over IB driver when netbooting over IB. 9957c478bd9Sstevel@tonic-gate * As per IB 1275 binding, IP over IB is represented as 9967c478bd9Sstevel@tonic-gate * service on the top of the HCA node. So, there is no 9977c478bd9Sstevel@tonic-gate * PROM node and generic framework cannot pre-load 9987c478bd9Sstevel@tonic-gate * IP over IB driver based on the bootpath. The following 9997c478bd9Sstevel@tonic-gate * code preloads IP over IB driver when doing netboot over 10007c478bd9Sstevel@tonic-gate * InfiniBand. 10017c478bd9Sstevel@tonic-gate */ 10027c478bd9Sstevel@tonic-gate if (netboot_over_ib(bootpath) && 10037c478bd9Sstevel@tonic-gate modloadonly("drv", "ibd") == -1) { 10047c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ibd: cannot load platform driver\n"); 1005f4da9be0Scth kmem_free(pathcopy, pathcopy_len); 10067c478bd9Sstevel@tonic-gate return (NULL); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate 1009c29cc384Svikram /* 1010c29cc384Svikram * The PROM node for hubs have incomplete compatible 1011c29cc384Svikram * properties and therefore do not bind to the hubd driver. 1012c29cc384Svikram * As a result load_bootpath_drivers() loads the usb_mid driver 1013c29cc384Svikram * for hub nodes rather than the hubd driver. This causes 1014c29cc384Svikram * mountroot failures when booting off USB storage. To prevent 1015c29cc384Svikram * this, if we are booting via USB hubs, we preload the hubd driver. 1016c29cc384Svikram */ 1017c29cc384Svikram if (strstr(bootpath, "/hub@") && modloadonly("drv", "hubd") == -1) { 1018c29cc384Svikram cmn_err(CE_WARN, "bootpath contains a USB hub, " 1019c29cc384Svikram "but cannot load hubd driver"); 1020c29cc384Svikram } 1021c29cc384Svikram 1022f4da9be0Scth /* get rid of minor node at end of copy (if not already done above) */ 1023f4da9be0Scth p = strrchr(pathcopy, '/'); 1024f4da9be0Scth if (p) { 1025f4da9be0Scth p = strchr(p, ':'); 1026f4da9be0Scth if (p) 1027f4da9be0Scth *p = 0; 1028f4da9be0Scth } 1029f4da9be0Scth 1030f4da9be0Scth rval = load_parent_drivers(dip, pathcopy); 1031f4da9be0Scth kmem_free(pathcopy, pathcopy_len); 1032f4da9be0Scth return (rval); 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate /* 10397c478bd9Sstevel@tonic-gate * Load drivers required for a platform 10407c478bd9Sstevel@tonic-gate * Since all hardware nodes should be available in the device 10417c478bd9Sstevel@tonic-gate * tree, walk the per-driver list and load the parents of 10427c478bd9Sstevel@tonic-gate * each node found. If not a hardware node, try to load it. 10437c478bd9Sstevel@tonic-gate * Pseudo nexus is already loaded. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate static int 10467c478bd9Sstevel@tonic-gate load_boot_platform_modules(char *drv) 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate major_t major; 10497c478bd9Sstevel@tonic-gate dev_info_t *dip; 10507c478bd9Sstevel@tonic-gate char *drvname; 10517c478bd9Sstevel@tonic-gate int rval = 0; 10527c478bd9Sstevel@tonic-gate 1053a204de77Scth if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) { 10547c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 10557c478bd9Sstevel@tonic-gate return (-1); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * resolve aliases 10607c478bd9Sstevel@tonic-gate */ 10617c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 1062a204de77Scth if ((major = ddi_name_to_major(drvname)) == DDI_MAJOR_T_NONE) 10637c478bd9Sstevel@tonic-gate return (-1); 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate #ifdef DEBUG 10667c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 10677c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s\n", drv)); 10687c478bd9Sstevel@tonic-gate } else { 10697c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s -> %s\n", 10707c478bd9Sstevel@tonic-gate drv, drvname)); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate dip = devnamesp[major].dn_head; 10757c478bd9Sstevel@tonic-gate if (dip == NULL) { 10767c478bd9Sstevel@tonic-gate /* pseudo node, not-enumerated, needs to be loaded */ 10777c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 10787c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load platform driver\n", 10797c478bd9Sstevel@tonic-gate drvname); 10807c478bd9Sstevel@tonic-gate rval = -1; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate } else { 10837c478bd9Sstevel@tonic-gate while (dip) { 1084f4da9be0Scth if (load_parent_drivers(dip, NULL) != 0) 10857c478bd9Sstevel@tonic-gate rval = -1; 10867c478bd9Sstevel@tonic-gate dip = ddi_get_next(dip); 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate return (rval); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate /* 10957c478bd9Sstevel@tonic-gate * i_find_node: Internal routine used by path_to_devinfo 10967c478bd9Sstevel@tonic-gate * to locate a given nodeid in the device tree. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate struct i_path_findnode { 1099fa9e4066Sahrens pnode_t nodeid; 11007c478bd9Sstevel@tonic-gate dev_info_t *dip; 11017c478bd9Sstevel@tonic-gate }; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate static int 11047c478bd9Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg) 11057c478bd9Sstevel@tonic-gate { 11067c478bd9Sstevel@tonic-gate struct i_path_findnode *f = (struct i_path_findnode *)arg; 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate if (ddi_get_nodeid(dev) == (int)f->nodeid) { 11107c478bd9Sstevel@tonic-gate f->dip = dev; 11117c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* 11177c478bd9Sstevel@tonic-gate * Return the devinfo node to a boot device 11187c478bd9Sstevel@tonic-gate */ 11197c478bd9Sstevel@tonic-gate static dev_info_t * 11207c478bd9Sstevel@tonic-gate path_to_devinfo(char *path) 11217c478bd9Sstevel@tonic-gate { 11227c478bd9Sstevel@tonic-gate struct i_path_findnode fn; 11237c478bd9Sstevel@tonic-gate extern dev_info_t *top_devinfo; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* 11267c478bd9Sstevel@tonic-gate * Get the nodeid of the given pathname, if such a mapping exists. 11277c478bd9Sstevel@tonic-gate */ 11287c478bd9Sstevel@tonic-gate fn.dip = NULL; 11297c478bd9Sstevel@tonic-gate fn.nodeid = prom_finddevice(path); 11307c478bd9Sstevel@tonic-gate if (fn.nodeid != OBP_BADNODE) { 11317c478bd9Sstevel@tonic-gate /* 11327c478bd9Sstevel@tonic-gate * Find the nodeid in our copy of the device tree and return 11337c478bd9Sstevel@tonic-gate * whatever name we used to bind this node to a driver. 11347c478bd9Sstevel@tonic-gate */ 11357c478bd9Sstevel@tonic-gate ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn)); 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate #ifdef DEBUG 11397c478bd9Sstevel@tonic-gate /* 11407c478bd9Sstevel@tonic-gate * If we're bound to something other than the nodename, 11417c478bd9Sstevel@tonic-gate * note that in the message buffer and system log. 11427c478bd9Sstevel@tonic-gate */ 11437c478bd9Sstevel@tonic-gate if (fn.dip) { 11447c478bd9Sstevel@tonic-gate char *p, *q; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate p = ddi_binding_name(fn.dip); 11477c478bd9Sstevel@tonic-gate q = ddi_node_name(fn.dip); 11487c478bd9Sstevel@tonic-gate if (p && q && (strcmp(p, q) != 0)) { 11497c478bd9Sstevel@tonic-gate BMDPRINTF(("path_to_devinfo: %s bound to %s\n", 11507c478bd9Sstevel@tonic-gate path, p)); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate return (fn.dip); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate /* 11597c478bd9Sstevel@tonic-gate * This routine returns B_TRUE if the bootpath corresponds to 11607c478bd9Sstevel@tonic-gate * IP over IB driver. 11617c478bd9Sstevel@tonic-gate * 11627c478bd9Sstevel@tonic-gate * The format of the bootpath for the IP over IB looks like 11637c478bd9Sstevel@tonic-gate * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip 11647c478bd9Sstevel@tonic-gate * 11657c478bd9Sstevel@tonic-gate * The minor node portion "port=1,pkey=8001,protocol=ip" represents 11667c478bd9Sstevel@tonic-gate * IP over IB driver. 11677c478bd9Sstevel@tonic-gate */ 11687c478bd9Sstevel@tonic-gate static boolean_t 11697c478bd9Sstevel@tonic-gate netboot_over_ib(char *bootpath) 11707c478bd9Sstevel@tonic-gate { 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate char *temp; 11737c478bd9Sstevel@tonic-gate boolean_t ret = B_FALSE; 1174fa9e4066Sahrens pnode_t node = prom_finddevice(bootpath); 11757c478bd9Sstevel@tonic-gate int len; 11767c478bd9Sstevel@tonic-gate char devicetype[OBP_MAXDRVNAME]; 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate /* Is this IB node ? */ 1179dedec472SJack Meng if (node == OBP_BADNODE || node == OBP_NONODE) { 1180dedec472SJack Meng return (B_FALSE); 1181dedec472SJack Meng } 11827c478bd9Sstevel@tonic-gate len = prom_getproplen(node, OBP_DEVICETYPE); 11837c478bd9Sstevel@tonic-gate if (len <= 1 || len >= OBP_MAXDRVNAME) 11847c478bd9Sstevel@tonic-gate return (B_FALSE); 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype); 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate if (strncmp("ib", devicetype, 2) == 0) { 11897c478bd9Sstevel@tonic-gate /* Check for proper IP over IB string */ 11907c478bd9Sstevel@tonic-gate if ((temp = strstr(bootpath, ":port=")) != NULL) { 11917c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, ",pkey=")) != NULL) 11927c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, 11937c478bd9Sstevel@tonic-gate ",protocol=ip")) != NULL) { 11947c478bd9Sstevel@tonic-gate ret = B_TRUE; 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate return (ret); 11997c478bd9Sstevel@tonic-gate } 1200dedec472SJack Meng 1201dedec472SJack Meng static boolean_t 1202dedec472SJack Meng netboot_over_iscsi(void) 1203dedec472SJack Meng { 1204dedec472SJack Meng int proplen; 1205dedec472SJack Meng boolean_t ret = B_FALSE; 1206dedec472SJack Meng char bootpath[OBP_MAXPATHLEN]; 1207dedec472SJack Meng 1208dedec472SJack Meng proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH); 1209dedec472SJack Meng if (proplen > 0) { 1210dedec472SJack Meng if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) { 1211dedec472SJack Meng if (memcmp(bootpath, BP_ISCSI_DISK, 1212dedec472SJack Meng strlen(BP_ISCSI_DISK)) == 0) { 1213dedec472SJack Meng ret = B_TRUE; 1214dedec472SJack Meng } 1215dedec472SJack Meng } 1216dedec472SJack Meng } 1217dedec472SJack Meng return (ret); 1218dedec472SJack Meng } 1219