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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Configure root, swap and dump devices. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/param.h> 377c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 387c478bd9Sstevel@tonic-gate #include <sys/signal.h> 397c478bd9Sstevel@tonic-gate #include <sys/cred.h> 407c478bd9Sstevel@tonic-gate #include <sys/proc.h> 417c478bd9Sstevel@tonic-gate #include <sys/user.h> 427c478bd9Sstevel@tonic-gate #include <sys/conf.h> 437c478bd9Sstevel@tonic-gate #include <sys/buf.h> 447c478bd9Sstevel@tonic-gate #include <sys/systm.h> 457c478bd9Sstevel@tonic-gate #include <sys/vm.h> 467c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 477c478bd9Sstevel@tonic-gate #include <sys/file.h> 487c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 497c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 507c478bd9Sstevel@tonic-gate #include <sys/errno.h> 517c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 527c478bd9Sstevel@tonic-gate #include <sys/uio.h> 537c478bd9Sstevel@tonic-gate #include <sys/open.h> 547c478bd9Sstevel@tonic-gate #include <sys/mount.h> 557c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 567c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 577c478bd9Sstevel@tonic-gate #include <sys/sysconf.h> 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 607c478bd9Sstevel@tonic-gate #include <sys/debug.h> 617c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h> 627c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 637c478bd9Sstevel@tonic-gate #include <sys/socket.h> 647c478bd9Sstevel@tonic-gate #include <net/if.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 677c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 687c478bd9Sstevel@tonic-gate #include <sys/console.h> 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #include <sys/conf.h> 717c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 727c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 737c478bd9Sstevel@tonic-gate #include <sys/hwconf.h> 747c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h> 757c478bd9Sstevel@tonic-gate #include <sys/promif.h> 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Local routines 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate static int preload_module(struct sysparam *, void *); 827c478bd9Sstevel@tonic-gate static struct vfssw *getfstype(char *, char *, size_t); 837c478bd9Sstevel@tonic-gate static int getphysdev(char *, char *, size_t); 847c478bd9Sstevel@tonic-gate static int load_bootpath_drivers(char *bootpath); 857c478bd9Sstevel@tonic-gate static int load_boot_driver(char *drv); 867c478bd9Sstevel@tonic-gate static int load_boot_platform_modules(char *drv); 877c478bd9Sstevel@tonic-gate static dev_info_t *path_to_devinfo(char *path); 887c478bd9Sstevel@tonic-gate static boolean_t netboot_over_ib(char *bootpath); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 957c478bd9Sstevel@tonic-gate &mod_miscops, "root and swap configuration %I%" 967c478bd9Sstevel@tonic-gate }; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 997c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 1007c478bd9Sstevel@tonic-gate }; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate int 1037c478bd9Sstevel@tonic-gate _init(void) 1047c478bd9Sstevel@tonic-gate { 1057c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate int 1097c478bd9Sstevel@tonic-gate _fini(void) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate int 1157c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * Configure root file system. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate int 1247c478bd9Sstevel@tonic-gate rootconf(void) 1257c478bd9Sstevel@tonic-gate { 1267c478bd9Sstevel@tonic-gate int error; 1277c478bd9Sstevel@tonic-gate struct vfssw *vsw; 1287c478bd9Sstevel@tonic-gate extern void pm_init(void); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype)); 1317c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name)); 1327c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags)); 1337c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath)); 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Install cluster modules that were only loaded during 1377c478bd9Sstevel@tonic-gate * loadrootmodules(). 1387c478bd9Sstevel@tonic-gate */ 1397c478bd9Sstevel@tonic-gate if (error = clboot_rootconf()) 1407c478bd9Sstevel@tonic-gate return (error); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (root_is_svm) { 1437c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name)); 1467c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath)); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * Run _init on the root filesystem (we already loaded it 1517c478bd9Sstevel@tonic-gate * but we've been waiting until now to _init it) which will 1527c478bd9Sstevel@tonic-gate * have the side-effect of running vsw_init() on this vfs. 1537c478bd9Sstevel@tonic-gate * Because all the nfs filesystems are lumped into one 1547c478bd9Sstevel@tonic-gate * module we need to special case it. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 1577c478bd9Sstevel@tonic-gate if (modload("fs", "nfs") == -1) { 1587c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 1597c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 1607c478bd9Sstevel@tonic-gate return (ENXIO); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate } else { 1637c478bd9Sstevel@tonic-gate if (modload("fs", rootfs.bo_fstype) == -1) { 1647c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot initialize %s filesystem\n", 1657c478bd9Sstevel@tonic-gate rootfs.bo_fstype); 1667c478bd9Sstevel@tonic-gate return (ENXIO); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate RLOCK_VFSSW(); 1707c478bd9Sstevel@tonic-gate vsw = vfs_getvfsswbyname(rootfs.bo_fstype); 1717c478bd9Sstevel@tonic-gate RUNLOCK_VFSSW(); 1727c478bd9Sstevel@tonic-gate VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0); 1737c478bd9Sstevel@tonic-gate VFS_HOLD(rootvfs); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate if (root_is_svm) { 1767c478bd9Sstevel@tonic-gate rootvfs->vfs_flag |= VFS_RDONLY; 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * This pm-releated call has to occur before root is mounted since we 1817c478bd9Sstevel@tonic-gate * need to power up all devices. It is placed after VFS_INIT() such 1827c478bd9Sstevel@tonic-gate * that opening a device via ddi_lyr_ interface just before root has 1837c478bd9Sstevel@tonic-gate * been mounted would work. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate pm_init(); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (netboot) { 1887c478bd9Sstevel@tonic-gate if ((error = strplumb()) != 0) { 1897c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot plumb network device\n"); 1907c478bd9Sstevel@tonic-gate return (error); 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * ufs_mountroot() ends up calling getrootdev() 1967c478bd9Sstevel@tonic-gate * (below) which actually triggers the _init, identify, 1977c478bd9Sstevel@tonic-gate * probe and attach of the drivers that make up root device 1987c478bd9Sstevel@tonic-gate * bush; these are also quietly waiting in memory. 1997c478bd9Sstevel@tonic-gate */ 2007c478bd9Sstevel@tonic-gate BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype)); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate error = VFS_MOUNTROOT(rootvfs, ROOT_INIT); 2037c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 2047c478bd9Sstevel@tonic-gate rootdev = rootvfs->vfs_dev; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (error) 2077c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n", 2087c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2097c478bd9Sstevel@tonic-gate else 2107c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root on %s fstype %s\n", 2117c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2127c478bd9Sstevel@tonic-gate return (error); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Remount root on an SVM mirror root device 2177c478bd9Sstevel@tonic-gate * Only supported on UFS filesystems at present 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate int 2207c478bd9Sstevel@tonic-gate svm_rootconf(void) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate int error; 2237c478bd9Sstevel@tonic-gate extern int ufs_remountroot(struct vfs *vfsp); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate ASSERT(root_is_svm == 1); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (strcmp(rootfs.bo_fstype, "ufs") != 0) { 2287c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Mounting root on %s with filesystem " 2297c478bd9Sstevel@tonic-gate "type %s is not supported\n", 2307c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2317c478bd9Sstevel@tonic-gate return (EINVAL); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate (void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME); 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name)); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate error = ufs_remountroot(rootvfs); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (error) { 2417c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n", 2427c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2437c478bd9Sstevel@tonic-gate } else { 2447c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?root remounted on %s fstype %s\n", 2457c478bd9Sstevel@tonic-gate rootfs.bo_name, rootfs.bo_fstype); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate return (error); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Under the assumption that our root file system is on a 2527c478bd9Sstevel@tonic-gate * disk partition, get the dev_t of the partition in question. 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * By now, boot has faithfully loaded all our modules into memory, and 2557c478bd9Sstevel@tonic-gate * we've taken over resource management. Before we go any further, we 2567c478bd9Sstevel@tonic-gate * have to fire up the device drivers and stuff we need to mount the 2577c478bd9Sstevel@tonic-gate * root filesystem. That's what we do here. Fingers crossed. 2587c478bd9Sstevel@tonic-gate */ 2597c478bd9Sstevel@tonic-gate dev_t 2607c478bd9Sstevel@tonic-gate getrootdev(void) 2617c478bd9Sstevel@tonic-gate { 2627c478bd9Sstevel@tonic-gate dev_t d; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if ((d = ddi_pathname_to_dev_t(rootfs.bo_name)) == NODEV) 2657c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n", 2667c478bd9Sstevel@tonic-gate rootfs.bo_name); 2677c478bd9Sstevel@tonic-gate return (d); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * If booted with ASKNAME, prompt on the console for a filesystem 2727c478bd9Sstevel@tonic-gate * name and return it. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate void 2757c478bd9Sstevel@tonic-gate getfsname(char *askfor, char *name, size_t namelen) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 2787c478bd9Sstevel@tonic-gate printf("%s name: ", askfor); 2797c478bd9Sstevel@tonic-gate console_gets(name, namelen); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 2847c478bd9Sstevel@tonic-gate static int 2857c478bd9Sstevel@tonic-gate preload_module(struct sysparam *sysp, void *p) 2867c478bd9Sstevel@tonic-gate { 2877c478bd9Sstevel@tonic-gate static char *wmesg = "forceload of %s failed"; 2887c478bd9Sstevel@tonic-gate char *name; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate name = sysp->sys_ptr; 2917c478bd9Sstevel@tonic-gate BMDPRINTF(("preload_module: %s\n", name)); 2927c478bd9Sstevel@tonic-gate if (modloadonly(NULL, name) < 0) 2937c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, wmesg, name); 2947c478bd9Sstevel@tonic-gate return (0); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2987c478bd9Sstevel@tonic-gate /* 2997c478bd9Sstevel@tonic-gate * We want to load all the modules needed to mount the root filesystem, 3007c478bd9Sstevel@tonic-gate * so that when we start the ball rolling in 'getrootdev', every module 3017c478bd9Sstevel@tonic-gate * should already be in memory, just waiting to be init-ed. 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate int 3057c478bd9Sstevel@tonic-gate loadrootmodules(void) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate struct vfssw *vsw; 3087c478bd9Sstevel@tonic-gate char *this; 3097c478bd9Sstevel@tonic-gate char *name; 3107c478bd9Sstevel@tonic-gate int err; 3117c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 3127c478bd9Sstevel@tonic-gate int i, proplen, dhcacklen; 3137c478bd9Sstevel@tonic-gate extern char *impl_module_list[]; 3147c478bd9Sstevel@tonic-gate extern char *platform_module_list[]; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* Make sure that the PROM's devinfo tree has been created */ 3177c478bd9Sstevel@tonic-gate ASSERT(ddi_root_node()); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype)); 3207c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name)); 3217c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags)); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * zzz We need to honor what's in rootfs if it's not null. 3257c478bd9Sstevel@tonic-gate * non-null means use what's there. This way we can 3267c478bd9Sstevel@tonic-gate * change rootfs with /etc/system AND with tunetool. 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate if (root_is_svm) { 3297c478bd9Sstevel@tonic-gate /* user replaced rootdev, record obp_bootpath */ 3307c478bd9Sstevel@tonic-gate obp_bootpath[0] = '\0'; 3317c478bd9Sstevel@tonic-gate (void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME); 3327c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 3337c478bd9Sstevel@tonic-gate } else { 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * Get the root fstype and root device path from boot. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate rootfs.bo_fstype[0] = '\0'; 3387c478bd9Sstevel@tonic-gate rootfs.bo_name[0] = '\0'; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /* 3427c478bd9Sstevel@tonic-gate * This lookup will result in modloadonly-ing the root 3437c478bd9Sstevel@tonic-gate * filesystem module - it gets _init-ed in rootconf() 3447c478bd9Sstevel@tonic-gate */ 3457c478bd9Sstevel@tonic-gate if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL) 3467c478bd9Sstevel@tonic-gate return (ENXIO); /* in case we have no file system types */ 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate (void) strcpy(rootfs.bo_fstype, vsw->vsw_name); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate vfs_unrefvfssw(vsw); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * Load the favored drivers of the implementation. 3547c478bd9Sstevel@tonic-gate * e.g. 'sbus' and possibly 'zs' (even). 3557c478bd9Sstevel@tonic-gate * 3567c478bd9Sstevel@tonic-gate * Called whilst boot is still loaded (because boot does 3577c478bd9Sstevel@tonic-gate * the i/o for us), and DDI services are unavailable. 3587c478bd9Sstevel@tonic-gate */ 3597c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: impl_module_list\n")); 3607c478bd9Sstevel@tonic-gate for (i = 0; (this = impl_module_list[i]) != NULL; i++) { 3617c478bd9Sstevel@tonic-gate if ((err = load_boot_driver(this)) != 0) { 3627c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 3637c478bd9Sstevel@tonic-gate return (err); 3647c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Now load the platform modules (if any) 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: platform_module_list\n")); 3717c478bd9Sstevel@tonic-gate for (i = 0; (this = platform_module_list[i]) != NULL; i++) { 3727c478bd9Sstevel@tonic-gate if ((err = load_boot_platform_modules(this)) != 0) { 3737c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Cannot load drv/%s", this); 3747c478bd9Sstevel@tonic-gate return (err); 3757c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate loop: 3807c478bd9Sstevel@tonic-gate (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate /* 3837c478bd9Sstevel@tonic-gate * Given a physical pathname, load the correct set of driver 3847c478bd9Sstevel@tonic-gate * modules into memory, including all possible parents. 3857c478bd9Sstevel@tonic-gate * 3867c478bd9Sstevel@tonic-gate * NB: The code sets the variable 'name' for error reporting. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate err = 0; 3897c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 3907c478bd9Sstevel@tonic-gate if (root_is_svm == 0) { 3917c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name)); 3927c478bd9Sstevel@tonic-gate name = rootfs.bo_name; 3937c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(rootfs.bo_name); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * Load driver modules in obp_bootpath, this is always 3987c478bd9Sstevel@tonic-gate * required for mountroot to succeed. obp_bootpath is 3997c478bd9Sstevel@tonic-gate * is set if rootdev is set via /etc/system, which is 4007c478bd9Sstevel@tonic-gate * the case if booting of a SVM/VxVM mirror. 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate if ((err == 0) && obp_bootpath[0] != '\0') { 4037c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath)); 4047c478bd9Sstevel@tonic-gate name = obp_bootpath; 4057c478bd9Sstevel@tonic-gate err = load_bootpath_drivers(obp_bootpath); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if (err != 0) { 4097c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load drivers for %s\n", name); 4107c478bd9Sstevel@tonic-gate goto out; 4117c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * Check to see if the booter performed DHCP configuration 4167c478bd9Sstevel@tonic-gate * ("bootp-response" boot property exists). If so, then before 4177c478bd9Sstevel@tonic-gate * bootops disappears we need to save the value of this property 4187c478bd9Sstevel@tonic-gate * such that the userland dhcpagent can adopt the DHCP management 4197c478bd9Sstevel@tonic-gate * of our primary network interface. We leave room at the beginning of 4207c478bd9Sstevel@tonic-gate * saved property to cache the interface name we used to boot the 4217c478bd9Sstevel@tonic-gate * client. This context is necessary for the user land dhcpagent 4227c478bd9Sstevel@tonic-gate * to do its job properly on a multi-homed system. 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "bootp-response"); 4257c478bd9Sstevel@tonic-gate if (proplen > 0) { 4267c478bd9Sstevel@tonic-gate dhcacklen = proplen + IFNAMSIZ; 4277c478bd9Sstevel@tonic-gate dhcack = kmem_zalloc(dhcacklen, KM_SLEEP); 4287c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "bootp-response", 4297c478bd9Sstevel@tonic-gate (uchar_t *)&dhcack[IFNAMSIZ]) == -1) { 4307c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 4317c478bd9Sstevel@tonic-gate "\"bootp-response\" failed\n"); 4327c478bd9Sstevel@tonic-gate kmem_free(dhcack, dhcacklen); 4337c478bd9Sstevel@tonic-gate dhcack = NULL; 4347c478bd9Sstevel@tonic-gate goto out; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Fetch the "netdev-path" boot property (if it exists), and 4397c478bd9Sstevel@tonic-gate * stash it for later use by sysinfo(SI_DHCP_CACHE, ...). 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate proplen = BOP_GETPROPLEN(bootops, "netdev-path"); 4427c478bd9Sstevel@tonic-gate if (proplen > 0) { 4437c478bd9Sstevel@tonic-gate netdev_path = kmem_zalloc(proplen, KM_SLEEP); 4447c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, "netdev-path", 4457c478bd9Sstevel@tonic-gate (uchar_t *)netdev_path) == -1) { 4467c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "BOP_GETPROP of " 4477c478bd9Sstevel@tonic-gate "\"netdev-path\" failed\n"); 4487c478bd9Sstevel@tonic-gate kmem_free(netdev_path, proplen); 4497c478bd9Sstevel@tonic-gate goto out; 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* 4557c478bd9Sstevel@tonic-gate * Preload (load-only, no init) all modules which 4567c478bd9Sstevel@tonic-gate * were added to the /etc/system file with the 4577c478bd9Sstevel@tonic-gate * FORCELOAD keyword. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate BMDPRINTF(("loadrootmodules: preload_module\n")); 4607c478bd9Sstevel@tonic-gate (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * If we booted otw then load in the plumbing 4657c478bd9Sstevel@tonic-gate * routine now while we still can. If we didn't 4667c478bd9Sstevel@tonic-gate * boot otw then we will load strplumb in main(). 4677c478bd9Sstevel@tonic-gate * 4687c478bd9Sstevel@tonic-gate * NFS is actually a set of modules, the core routines, 4697c478bd9Sstevel@tonic-gate * a diskless helper module, rpcmod, and the tli interface. Load 4707c478bd9Sstevel@tonic-gate * them now while we still can. 4717c478bd9Sstevel@tonic-gate * 4727c478bd9Sstevel@tonic-gate * Because we glomb all versions of nfs into a single module 4737c478bd9Sstevel@tonic-gate * we check based on the initial string "nfs". 4747c478bd9Sstevel@tonic-gate * 4757c478bd9Sstevel@tonic-gate * XXX: A better test for this is to see if device_type 4767c478bd9Sstevel@tonic-gate * XXX: from the PROM is "network". 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) { 4807c478bd9Sstevel@tonic-gate ++netboot; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if ((err = modload("misc", "tlimod")) < 0) { 4837c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/tlimod\n"); 4847c478bd9Sstevel@tonic-gate goto out; 4857c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate if ((err = modload("strmod", "rpcmod")) < 0) { 4887c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n"); 4897c478bd9Sstevel@tonic-gate goto out; 4907c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate if ((err = modload("misc", "nfs_dlboot")) < 0) { 4937c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n"); 4947c478bd9Sstevel@tonic-gate goto out; 4957c478bd9Sstevel@tonic-gate /* NOTREACHED */ 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate if ((err = modload("misc", "strplumb")) < 0) { 4987c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "Cannot load misc/strplumb\n"); 4997c478bd9Sstevel@tonic-gate goto out; 5007c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate if ((err = strplumb_load()) < 0) { 5037c478bd9Sstevel@tonic-gate goto out; 5047c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * Preload modules needed for booting as a cluster. 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate err = clboot_loadrootmodules(); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate out: 5147c478bd9Sstevel@tonic-gate if (err != 0 && (boothowto & RB_ASKNAME)) 5157c478bd9Sstevel@tonic-gate goto loop; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate return (err); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Get the name of the root or swap filesystem type, and return 5237c478bd9Sstevel@tonic-gate * the corresponding entry in the vfs switch. 5247c478bd9Sstevel@tonic-gate * 5257c478bd9Sstevel@tonic-gate * If we're not asking the user, and we're trying to find the 5267c478bd9Sstevel@tonic-gate * root filesystem type, we ask boot for the filesystem 5277c478bd9Sstevel@tonic-gate * type that it came from and use that. Similarly, if we're 5287c478bd9Sstevel@tonic-gate * trying to find the swap filesystem, we try and derive it from 5297c478bd9Sstevel@tonic-gate * the root filesystem type. 5307c478bd9Sstevel@tonic-gate * 5317c478bd9Sstevel@tonic-gate * If we are booting via NFS we currently have these options: 5327c478bd9Sstevel@tonic-gate * nfs - dynamically choose NFS V2. V3, or V4 (default) 5337c478bd9Sstevel@tonic-gate * nfs2 - force NFS V2 5347c478bd9Sstevel@tonic-gate * nfs3 - force NFS V3 5357c478bd9Sstevel@tonic-gate * nfs4 - force NFS V4 5367c478bd9Sstevel@tonic-gate * Because we need to maintain backward compatibility with the naming 5377c478bd9Sstevel@tonic-gate * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c) 5387c478bd9Sstevel@tonic-gate * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic 5397c478bd9Sstevel@tonic-gate * nfs module will map the type back to either "nfs", "nfs3", or "nfs4". 5407c478bd9Sstevel@tonic-gate * This is only for root filesystems, all other uses such as cachefs 5417c478bd9Sstevel@tonic-gate * will expect that "nfs" == NFS V2. 5427c478bd9Sstevel@tonic-gate * 5437c478bd9Sstevel@tonic-gate * If the filesystem isn't already loaded, vfs_getvfssw() will load 5447c478bd9Sstevel@tonic-gate * it for us, but if (at the time we call it) modrootloaded is 5457c478bd9Sstevel@tonic-gate * still not set, it won't run the filesystems _init routine (and 5467c478bd9Sstevel@tonic-gate * implicitly it won't run the filesystems vsw_init() entry either). 5477c478bd9Sstevel@tonic-gate * We do that explicitly in rootconf(). 5487c478bd9Sstevel@tonic-gate */ 5497c478bd9Sstevel@tonic-gate static struct vfssw * 5507c478bd9Sstevel@tonic-gate getfstype(char *askfor, char *fsname, size_t fsnamelen) 5517c478bd9Sstevel@tonic-gate { 5527c478bd9Sstevel@tonic-gate struct vfssw *vsw; 5537c478bd9Sstevel@tonic-gate static char defaultfs[BO_MAXFSNAME]; 5547c478bd9Sstevel@tonic-gate int root = 0; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 5577c478bd9Sstevel@tonic-gate (void) BOP_GETPROP(bootops, "fstype", defaultfs); 5587c478bd9Sstevel@tonic-gate root++; 5597c478bd9Sstevel@tonic-gate } else { 5607c478bd9Sstevel@tonic-gate (void) strcpy(defaultfs, "swapfs"); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 5647c478bd9Sstevel@tonic-gate for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') { 5657c478bd9Sstevel@tonic-gate printf("%s filesystem type [%s]: ", askfor, defaultfs); 5667c478bd9Sstevel@tonic-gate console_gets(fsname, fsnamelen); 5677c478bd9Sstevel@tonic-gate if (*fsname == '\0') 5687c478bd9Sstevel@tonic-gate (void) strcpy(fsname, defaultfs); 5697c478bd9Sstevel@tonic-gate if (root) { 5707c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 5717c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 5727c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 5737c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate if ((vsw = vfs_getvfssw(fsname)) != NULL) 5767c478bd9Sstevel@tonic-gate return (vsw); 5777c478bd9Sstevel@tonic-gate printf("Unknown filesystem type '%s'\n", fsname); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate } else if (*fsname == '\0') { 5807c478bd9Sstevel@tonic-gate fsname = defaultfs; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate if (*fsname == '\0') { 5837c478bd9Sstevel@tonic-gate return (NULL); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (root) { 5877c478bd9Sstevel@tonic-gate if (strcmp(fsname, "nfs2") == 0) 5887c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfs"); 5897c478bd9Sstevel@tonic-gate else if (strcmp(fsname, "nfs") == 0) 5907c478bd9Sstevel@tonic-gate (void) strcpy(fsname, "nfsdyn"); 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate return (vfs_getvfssw(fsname)); 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * Get a physical device name, and maybe load and attach 5997c478bd9Sstevel@tonic-gate * the driver. 6007c478bd9Sstevel@tonic-gate * 6017c478bd9Sstevel@tonic-gate * XXX Need better checking of whether or not a device 6027c478bd9Sstevel@tonic-gate * actually exists if the user typed in a pathname. 6037c478bd9Sstevel@tonic-gate * 6047c478bd9Sstevel@tonic-gate * XXX Are we sure we want to expose users to this sort 6057c478bd9Sstevel@tonic-gate * of physical namespace gobbledygook (now there's 6067c478bd9Sstevel@tonic-gate * a word to conjure with..) 6077c478bd9Sstevel@tonic-gate * 6087c478bd9Sstevel@tonic-gate * XXX Note that on an OBP machine, we can easily ask the 6097c478bd9Sstevel@tonic-gate * prom and pretty-print some plausible set of bootable 6107c478bd9Sstevel@tonic-gate * devices. We can also user the prom to verify any 6117c478bd9Sstevel@tonic-gate * such device. Later tim.. later. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate static int 6147c478bd9Sstevel@tonic-gate getphysdev(char *askfor, char *name, size_t namelen) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate static char fmt[] = "Enter physical name of %s device\n[%s]: "; 6177c478bd9Sstevel@tonic-gate dev_t dev; 6187c478bd9Sstevel@tonic-gate static char defaultpath[BO_MAXOBJNAME]; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate /* 6217c478bd9Sstevel@tonic-gate * Establish 'default' values - we get the root device from 6227c478bd9Sstevel@tonic-gate * boot, and we infer the swap device is the same but with 6237c478bd9Sstevel@tonic-gate * a 'b' on the end instead of an 'a'. A first stab at 6247c478bd9Sstevel@tonic-gate * ease-of-use .. 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate if (strcmp(askfor, "root") == 0) { 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * Look for the 1275 compliant name 'bootpath' first, 6297c478bd9Sstevel@tonic-gate * but make certain it has a non-NULL value as well. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate if ((BOP_GETPROP(bootops, "bootpath", defaultpath) == -1) || 6327c478bd9Sstevel@tonic-gate strlen(defaultpath) == 0) { 6337c478bd9Sstevel@tonic-gate if (BOP_GETPROP(bootops, 6347c478bd9Sstevel@tonic-gate "boot-path", defaultpath) == -1) 6357c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate } else { 6387c478bd9Sstevel@tonic-gate (void) strcpy(defaultpath, rootfs.bo_name); 6397c478bd9Sstevel@tonic-gate defaultpath[strlen(defaultpath) - 1] = 'b'; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate retry: 6437c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) { 6447c478bd9Sstevel@tonic-gate printf(fmt, askfor, defaultpath); 6457c478bd9Sstevel@tonic-gate console_gets(name, namelen); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate if (*name == '\0') 6487c478bd9Sstevel@tonic-gate (void) strcpy(name, defaultpath); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate if (strcmp(askfor, "swap") == 0) { 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * Try to load and install the swap device driver. 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate dev = ddi_pathname_to_dev_t(name); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if (dev == (dev_t)-1) { 6587c478bd9Sstevel@tonic-gate printf("Not a supported device for swap.\n"); 6597c478bd9Sstevel@tonic-gate boothowto |= RB_ASKNAME | RB_VERBOSE; 6607c478bd9Sstevel@tonic-gate goto retry; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * Ensure that we're not trying to swap on the floppy. 6657c478bd9Sstevel@tonic-gate */ 6667c478bd9Sstevel@tonic-gate if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) { 6677c478bd9Sstevel@tonic-gate printf("Too dangerous to swap on the floppy\n"); 6687c478bd9Sstevel@tonic-gate if (boothowto & RB_ASKNAME) 6697c478bd9Sstevel@tonic-gate goto retry; 6707c478bd9Sstevel@tonic-gate return (-1); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate return (0); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* 6797c478bd9Sstevel@tonic-gate * Load a driver needed to boot. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate static int 6827c478bd9Sstevel@tonic-gate load_boot_driver(char *drv) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate char *drvname; 6857c478bd9Sstevel@tonic-gate major_t major; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 6887c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 6897c478bd9Sstevel@tonic-gate return (-1); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate /* 6927c478bd9Sstevel@tonic-gate * resolve aliases 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate #ifdef DEBUG 6977c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 6987c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s\n", drv)); 6997c478bd9Sstevel@tonic-gate } else { 7007c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname)); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 7057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load driver\n", drvname); 7067c478bd9Sstevel@tonic-gate return (-1); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate return (0); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * For a given instance, load that driver and its parents 7157c478bd9Sstevel@tonic-gate */ 7167c478bd9Sstevel@tonic-gate static int 7177c478bd9Sstevel@tonic-gate load_parent_drivers(dev_info_t *dip) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate int rval = 0; 7207c478bd9Sstevel@tonic-gate char *drv; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate while (dip) { 7237c478bd9Sstevel@tonic-gate drv = ddi_get_name(dip); 7247c478bd9Sstevel@tonic-gate if (load_boot_driver(drv) != 0) 7257c478bd9Sstevel@tonic-gate rval = -1; 7267c478bd9Sstevel@tonic-gate dip = ddi_get_parent(dip); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate return (rval); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate /* 7347c478bd9Sstevel@tonic-gate * For a given path to a boot device, 7357c478bd9Sstevel@tonic-gate * load that driver and all its parents. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate static int 7387c478bd9Sstevel@tonic-gate load_bootpath_drivers(char *bootpath) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate dev_info_t *dip; 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate if (bootpath == NULL || *bootpath == 0) 7437c478bd9Sstevel@tonic-gate return (-1); 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath)); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate dip = path_to_devinfo(bootpath); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * i386 does not provide stub nodes for all boot devices, 7527c478bd9Sstevel@tonic-gate * but we should be able to find the node for the parent, 7537c478bd9Sstevel@tonic-gate * and the leaf of the boot path should be the driver name, 7547c478bd9Sstevel@tonic-gate * which we go ahead and load here. 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate if (dip == NULL) { 7577c478bd9Sstevel@tonic-gate char *pathcopy, *leaf, *p; 7587c478bd9Sstevel@tonic-gate int len, rval; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate len = strlen(bootpath) + 1; 7617c478bd9Sstevel@tonic-gate pathcopy = kmem_zalloc(len, KM_SLEEP); 7627c478bd9Sstevel@tonic-gate (void) strcpy(pathcopy, bootpath); 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate /* 7657c478bd9Sstevel@tonic-gate * Work backward to the last slash to build the 7667c478bd9Sstevel@tonic-gate * full path of the parent of the boot device 7677c478bd9Sstevel@tonic-gate */ 7687c478bd9Sstevel@tonic-gate for (p = pathcopy + len - 2; *p != '/'; p--) 7697c478bd9Sstevel@tonic-gate ; 7707c478bd9Sstevel@tonic-gate *p++ = 0; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * Now isolate the driver name of the leaf device 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate for (leaf = p; *p && *p != '@'; p++) 7767c478bd9Sstevel@tonic-gate ; 7777c478bd9Sstevel@tonic-gate *p = 0; 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n", 7807c478bd9Sstevel@tonic-gate pathcopy, leaf)); 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate dip = path_to_devinfo(pathcopy); 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate rval = load_boot_driver(leaf); 7857c478bd9Sstevel@tonic-gate kmem_free(pathcopy, len); 7867c478bd9Sstevel@tonic-gate if (rval == -1) 7877c478bd9Sstevel@tonic-gate return (NULL); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate #endif 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (dip == NULL) { 7937c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "can't bind driver for boot path <%s>", 7947c478bd9Sstevel@tonic-gate bootpath); 7957c478bd9Sstevel@tonic-gate return (NULL); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * Load IP over IB driver when netbooting over IB. 8007c478bd9Sstevel@tonic-gate * As per IB 1275 binding, IP over IB is represented as 8017c478bd9Sstevel@tonic-gate * service on the top of the HCA node. So, there is no 8027c478bd9Sstevel@tonic-gate * PROM node and generic framework cannot pre-load 8037c478bd9Sstevel@tonic-gate * IP over IB driver based on the bootpath. The following 8047c478bd9Sstevel@tonic-gate * code preloads IP over IB driver when doing netboot over 8057c478bd9Sstevel@tonic-gate * InfiniBand. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate if (netboot_over_ib(bootpath) && 8087c478bd9Sstevel@tonic-gate modloadonly("drv", "ibd") == -1) { 8097c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ibd: cannot load platform driver\n"); 8107c478bd9Sstevel@tonic-gate return (NULL); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate return (load_parent_drivers(dip)); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * Load drivers required for a platform 8217c478bd9Sstevel@tonic-gate * Since all hardware nodes should be available in the device 8227c478bd9Sstevel@tonic-gate * tree, walk the per-driver list and load the parents of 8237c478bd9Sstevel@tonic-gate * each node found. If not a hardware node, try to load it. 8247c478bd9Sstevel@tonic-gate * Pseudo nexus is already loaded. 8257c478bd9Sstevel@tonic-gate */ 8267c478bd9Sstevel@tonic-gate static int 8277c478bd9Sstevel@tonic-gate load_boot_platform_modules(char *drv) 8287c478bd9Sstevel@tonic-gate { 8297c478bd9Sstevel@tonic-gate major_t major; 8307c478bd9Sstevel@tonic-gate dev_info_t *dip; 8317c478bd9Sstevel@tonic-gate char *drvname; 8327c478bd9Sstevel@tonic-gate int rval = 0; 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drv)) == (major_t)-1) { 8357c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: no major number\n", drv); 8367c478bd9Sstevel@tonic-gate return (-1); 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate /* 8407c478bd9Sstevel@tonic-gate * resolve aliases 8417c478bd9Sstevel@tonic-gate */ 8427c478bd9Sstevel@tonic-gate drvname = ddi_major_to_name(major); 8437c478bd9Sstevel@tonic-gate if ((major = ddi_name_to_major(drvname)) == (major_t)-1) 8447c478bd9Sstevel@tonic-gate return (-1); 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate #ifdef DEBUG 8477c478bd9Sstevel@tonic-gate if (strcmp(drv, drvname) == 0) { 8487c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s\n", drv)); 8497c478bd9Sstevel@tonic-gate } else { 8507c478bd9Sstevel@tonic-gate BMDPRINTF(("load_boot_platform_modules: %s -> %s\n", 8517c478bd9Sstevel@tonic-gate drv, drvname)); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate dip = devnamesp[major].dn_head; 8567c478bd9Sstevel@tonic-gate if (dip == NULL) { 8577c478bd9Sstevel@tonic-gate /* pseudo node, not-enumerated, needs to be loaded */ 8587c478bd9Sstevel@tonic-gate if (modloadonly("drv", drvname) == -1) { 8597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "%s: cannot load platform driver\n", 8607c478bd9Sstevel@tonic-gate drvname); 8617c478bd9Sstevel@tonic-gate rval = -1; 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate } else { 8647c478bd9Sstevel@tonic-gate while (dip) { 8657c478bd9Sstevel@tonic-gate if (load_parent_drivers(dip) != 0) 8667c478bd9Sstevel@tonic-gate rval = -1; 8677c478bd9Sstevel@tonic-gate dip = ddi_get_next(dip); 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate return (rval); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate /* 8767c478bd9Sstevel@tonic-gate * i_find_node: Internal routine used by path_to_devinfo 8777c478bd9Sstevel@tonic-gate * to locate a given nodeid in the device tree. 8787c478bd9Sstevel@tonic-gate */ 8797c478bd9Sstevel@tonic-gate struct i_path_findnode { 880*fa9e4066Sahrens pnode_t nodeid; 8817c478bd9Sstevel@tonic-gate dev_info_t *dip; 8827c478bd9Sstevel@tonic-gate }; 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate static int 8857c478bd9Sstevel@tonic-gate i_path_find_node(dev_info_t *dev, void *arg) 8867c478bd9Sstevel@tonic-gate { 8877c478bd9Sstevel@tonic-gate struct i_path_findnode *f = (struct i_path_findnode *)arg; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate if (ddi_get_nodeid(dev) == (int)f->nodeid) { 8917c478bd9Sstevel@tonic-gate f->dip = dev; 8927c478bd9Sstevel@tonic-gate return (DDI_WALK_TERMINATE); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate return (DDI_WALK_CONTINUE); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* 8987c478bd9Sstevel@tonic-gate * Return the devinfo node to a boot device 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate static dev_info_t * 9017c478bd9Sstevel@tonic-gate path_to_devinfo(char *path) 9027c478bd9Sstevel@tonic-gate { 9037c478bd9Sstevel@tonic-gate struct i_path_findnode fn; 9047c478bd9Sstevel@tonic-gate extern dev_info_t *top_devinfo; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* 9077c478bd9Sstevel@tonic-gate * Get the nodeid of the given pathname, if such a mapping exists. 9087c478bd9Sstevel@tonic-gate */ 9097c478bd9Sstevel@tonic-gate fn.dip = NULL; 9107c478bd9Sstevel@tonic-gate fn.nodeid = prom_finddevice(path); 9117c478bd9Sstevel@tonic-gate if (fn.nodeid != OBP_BADNODE) { 9127c478bd9Sstevel@tonic-gate /* 9137c478bd9Sstevel@tonic-gate * Find the nodeid in our copy of the device tree and return 9147c478bd9Sstevel@tonic-gate * whatever name we used to bind this node to a driver. 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn)); 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate #ifdef DEBUG 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * If we're bound to something other than the nodename, 9227c478bd9Sstevel@tonic-gate * note that in the message buffer and system log. 9237c478bd9Sstevel@tonic-gate */ 9247c478bd9Sstevel@tonic-gate if (fn.dip) { 9257c478bd9Sstevel@tonic-gate char *p, *q; 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate p = ddi_binding_name(fn.dip); 9287c478bd9Sstevel@tonic-gate q = ddi_node_name(fn.dip); 9297c478bd9Sstevel@tonic-gate if (p && q && (strcmp(p, q) != 0)) { 9307c478bd9Sstevel@tonic-gate BMDPRINTF(("path_to_devinfo: %s bound to %s\n", 9317c478bd9Sstevel@tonic-gate path, p)); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate return (fn.dip); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * This routine returns B_TRUE if the bootpath corresponds to 9417c478bd9Sstevel@tonic-gate * IP over IB driver. 9427c478bd9Sstevel@tonic-gate * 9437c478bd9Sstevel@tonic-gate * The format of the bootpath for the IP over IB looks like 9447c478bd9Sstevel@tonic-gate * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip 9457c478bd9Sstevel@tonic-gate * 9467c478bd9Sstevel@tonic-gate * The minor node portion "port=1,pkey=8001,protocol=ip" represents 9477c478bd9Sstevel@tonic-gate * IP over IB driver. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate static boolean_t 9507c478bd9Sstevel@tonic-gate netboot_over_ib(char *bootpath) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate char *temp; 9547c478bd9Sstevel@tonic-gate boolean_t ret = B_FALSE; 955*fa9e4066Sahrens pnode_t node = prom_finddevice(bootpath); 9567c478bd9Sstevel@tonic-gate int len; 9577c478bd9Sstevel@tonic-gate char devicetype[OBP_MAXDRVNAME]; 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* Is this IB node ? */ 9607c478bd9Sstevel@tonic-gate len = prom_getproplen(node, OBP_DEVICETYPE); 9617c478bd9Sstevel@tonic-gate if (len <= 1 || len >= OBP_MAXDRVNAME) 9627c478bd9Sstevel@tonic-gate return (B_FALSE); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype); 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate if (strncmp("ib", devicetype, 2) == 0) { 9677c478bd9Sstevel@tonic-gate /* Check for proper IP over IB string */ 9687c478bd9Sstevel@tonic-gate if ((temp = strstr(bootpath, ":port=")) != NULL) { 9697c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, ",pkey=")) != NULL) 9707c478bd9Sstevel@tonic-gate if ((temp = strstr(temp, 9717c478bd9Sstevel@tonic-gate ",protocol=ip")) != NULL) { 9727c478bd9Sstevel@tonic-gate ret = B_TRUE; 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate return (ret); 9777c478bd9Sstevel@tonic-gate } 978