swapgeneric.c revision 56c0b1dab35897a2c09f93b2a70746ba47df7523
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* ONC_PLUS EXTRACT START */
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* ONC_PLUS EXTRACT END */
/*
* Configure root, swap and dump devices.
*/
#include <sys/sysmacros.h>
#include <sys/bootconf.h>
#include <sys/autoconf.h>
/*
* Local routines
*/
static int preload_module(struct sysparam *, void *);
static int getphysdev(char *, char *, size_t);
static int load_bootpath_drivers(char *bootpath);
static int load_boot_driver(char *drv);
static int load_boot_platform_modules(char *drv);
/*
* Module linkage information for the kernel.
*/
&mod_miscops, "root and swap configuration"
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
/*
* Configure root file system.
*/
int
rootconf(void)
{
int error;
extern void pm_init(void);
/*
* Install cluster modules that were only loaded during
* loadrootmodules().
*/
if (error = clboot_rootconf())
return (error);
if (root_is_svm) {
}
/*
* Run _init on the root filesystem (we already loaded it
* but we've been waiting until now to _init it) which will
* have the side-effect of running vsw_init() on this vfs.
* Because all the nfs filesystems are lumped into one
* module we need to special case it.
*/
return (ENXIO);
}
} else {
return (ENXIO);
}
}
RLOCK_VFSSW();
return (ENXIO);
}
if (root_is_svm) {
}
/*
* This pm-releated call has to occur before root is mounted since we
* need to power up all devices. It is placed after VFS_INIT() such
* that opening a device via ddi_lyr_ interface just before root has
* been mounted would work.
*/
pm_init();
if (netboot) {
return (error);
}
}
/*
* ufs_mountroot() ends up calling getrootdev()
* (below) which actually triggers the _init, identify,
* probe and attach of the drivers that make up root device
* bush; these are also quietly waiting in memory.
*/
if (error)
else
return (error);
}
/*
* Remount root on an SVM mirror root device
* Only supported on UFS filesystems at present
*/
int
svm_rootconf(void)
{
int error;
"type %s is not supported\n",
return (EINVAL);
}
if (error) {
} else {
}
return (error);
}
/*
* Under the assumption that our root file system is on a
* disk partition, get the dev_t of the partition in question.
*
* By now, boot has faithfully loaded all our modules into memory, and
* we've taken over resource management. Before we go any further, we
* have to fire up the device drivers and stuff we need to mount the
* root filesystem. That's what we do here. Fingers crossed.
*/
getrootdev(void)
{
dev_t d;
return (d);
}
/*
* If booted with ASKNAME, prompt on the console for a filesystem
* name and return it.
*/
void
{
if (boothowto & RB_ASKNAME) {
}
}
/*ARGSUSED1*/
static int
{
static char *wmesg = "forceload of %s failed";
char *name;
return (0);
}
/* ONC_PLUS EXTRACT START */
/*
* We want to load all the modules needed to mount the root filesystem,
* so that when we start the ball rolling in 'getrootdev', every module
* should already be in memory, just waiting to be init-ed.
*/
int
loadrootmodules(void)
{
char *this;
char *name;
int err;
/* ONC_PLUS EXTRACT END */
int i, proplen;
extern char *impl_module_list[];
extern char *platform_module_list[];
/* Make sure that the PROM's devinfo tree has been created */
ASSERT(ddi_root_node());
/*
* zzz We need to honor what's in rootfs if it's not null.
* non-null means use what's there. This way we can
*/
if (root_is_svm) {
/* user replaced rootdev, record obp_bootpath */
obp_bootpath[0] = '\0';
} else {
/*
* Get the root fstype and root device path from boot.
*/
}
/*
* This lookup will result in modloadonly-ing the root
* filesystem module - it gets _init-ed in rootconf()
*/
return (ENXIO); /* in case we have no file system types */
/*
* Load the favored drivers of the implementation.
* e.g. 'sbus' and possibly 'zs' (even).
*
* Called whilst boot is still loaded (because boot does
* the i/o for us), and DDI services are unavailable.
*/
BMDPRINTF(("loadrootmodules: impl_module_list\n"));
return (err);
}
}
/*
* Now load the platform modules (if any)
*/
BMDPRINTF(("loadrootmodules: platform_module_list\n"));
return (err);
}
}
loop:
/*
* Given a physical pathname, load the correct set of driver
* modules into memory, including all possible parents.
*
* NB: The code sets the variable 'name' for error reporting.
*/
err = 0;
if (root_is_svm == 0) {
}
/*
* Load driver modules in obp_bootpath, this is always
* required for mountroot to succeed. obp_bootpath is
*/
name = obp_bootpath;
}
if (err != 0) {
goto out;
}
/*
* Check to see if the booter performed DHCP configuration
* ("bootp-response" boot property exists). If so, then before
* bootops disappears we need to save the value of this property
* such that the userland dhcpagent can adopt the DHCP management
* of our primary network interface.
*/
if (proplen > 0) {
"\"bootp-response\" failed\n");
goto out;
}
/*
* Fetch the "netdev-path" boot property (if it exists), and
* stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
*/
if (proplen > 0) {
"\"netdev-path\" failed\n");
goto out;
}
}
}
/*
* Preload (load-only, no init) all modules which
* FORCELOAD keyword.
*/
BMDPRINTF(("loadrootmodules: preload_module\n"));
/* ONC_PLUS EXTRACT START */
/*
* If we booted otw then load in the plumbing
* routine now while we still can. If we didn't
* boot otw then we will load strplumb in main().
*
* NFS is actually a set of modules, the core routines,
* a diskless helper module, rpcmod, and the tli interface. Load
* them now while we still can.
*
* Because we glomb all versions of nfs into a single module
* we check based on the initial string "nfs".
*
* XXX: A better test for this is to see if device_type
* XXX: from the PROM is "network".
*/
++netboot;
/*
* Preload (load-only, no init) the dacf module. We cannot
* init the module because one of its requisite modules is
* dld whose _init function will call taskq_create(), which
* will panic the system at this point.
*/
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
if ((err = strplumb_load()) < 0) {
goto out;
}
}
/*
* Preload modules needed for booting as a cluster.
*/
out:
goto loop;
return (err);
}
/* ONC_PLUS EXTRACT END */
static int
get_bootpath_prop(char *bootpath)
{
if (root_is_ramdisk) {
return (-1);
} else {
/*
* Look for the 1275 compliant name 'bootpath' first,
* but make certain it has a non-NULL value as well.
*/
if (BOP_GETPROP(bootops,
return (-1);
}
}
return (0);
}
static int
get_fstype_prop(char *fstype)
{
}
/*
* Get the name of the root or swap filesystem type, and return
* the corresponding entry in the vfs switch.
*
* If we're not asking the user, and we're trying to find the
* root filesystem type, we ask boot for the filesystem
* type that it came from and use that. Similarly, if we're
* trying to find the swap filesystem, we try and derive it from
* the root filesystem type.
*
* If we are booting via NFS we currently have these options:
* nfs - dynamically choose NFS V2. V3, or V4 (default)
* nfs2 - force NFS V2
* nfs3 - force NFS V3
* nfs4 - force NFS V4
* Because we need to maintain backward compatibility with the naming
* convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
* we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic
* nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
* This is only for root filesystems, all other uses such as cachefs
* will expect that "nfs" == NFS V2.
*
* If the filesystem isn't already loaded, vfs_getvfssw() will load
* it for us, but if (at the time we call it) modrootloaded is
* still not set, it won't run the filesystems _init routine (and
* implicitly it won't run the filesystems vsw_init() entry either).
* We do that explicitly in rootconf().
*/
static struct vfssw *
{
static char defaultfs[BO_MAXFSNAME];
int root = 0;
(void) get_fstype_prop(defaultfs);
root++;
} else {
}
if (boothowto & RB_ASKNAME) {
if (*fsname == '\0')
if (root) {
}
return (vsw);
}
} else if (*fsname == '\0') {
}
if (*fsname == '\0') {
return (NULL);
}
if (root) {
}
return (vfs_getvfssw(fsname));
}
/*
* Get a physical device name, and maybe load and attach
* the driver.
*
* XXX Need better checking of whether or not a device
* actually exists if the user typed in a pathname.
*
* XXX Are we sure we want to expose users to this sort
* of physical namespace gobbledygook (now there's
* a word to conjure with..)
*
* XXX Note that on an OBP machine, we can easily ask the
* prom and pretty-print some plausible set of bootable
* devices. We can also user the prom to verify any
* such device. Later tim.. later.
*/
static int
{
static char fmt[] = "Enter physical name of %s device\n[%s]: ";
static char defaultpath[BO_MAXOBJNAME];
/*
* Establish 'default' values - we get the root device from
* boot, and we infer the swap device is the same but with
* a 'b' on the end instead of an 'a'. A first stab at
* ease-of-use ..
*/
} else {
}
if (boothowto & RB_ASKNAME) {
}
if (*name == '\0')
/*
* Try to load and install the swap device driver.
*/
printf("Not a supported device for swap.\n");
goto retry;
}
/*
* Ensure that we're not trying to swap on the floppy.
*/
printf("Too dangerous to swap on the floppy\n");
if (boothowto & RB_ASKNAME)
goto retry;
return (-1);
}
}
return (0);
}
/*
* Load a driver needed to boot.
*/
static int
load_boot_driver(char *drv)
{
char *drvname;
#ifdef sparc
char *module;
int plen;
int mlen;
#endif /* sparc */
return (-1);
}
/*
* resolve aliases
*/
#ifdef DEBUG
} else {
}
#endif /* DEBUG */
return (-1);
}
#ifdef sparc
/*
* NOTE: this can be removed when newboot-sparc is delivered.
*
* Check to see if the driver had a 'ddi-forceload' global driver.conf
* property to identify additional modules that need to be loaded.
* The driver still needs to use ddi_modopen() to open these modules,
* but the 'ddi-forceload' property allows the modules to be loaded
* into memory prior to lights-out, so that driver ddi_modopen()
* calls during lights-out (when mounting root) will work correctly.
* Use of 'ddi-forceload' is only required for drivers involved in
* getting root mounted.
*/
"ddi-forceload", DDI_PROP_TYPE_STRING,
while (plen > 0) {
if (mf) {
} else {
dir = "misc";
}
"misc/%s: can't load module\n", mf);
}
}
#endif /* sparc */
return (0);
}
/*
* For a given instance, load that driver and its parents
*/
static int
{
int rval = 0;
char *drv;
char *p;
while (dip) {
/* check for path-oriented alias */
if (path)
else
if (major != DDI_MAJOR_T_NONE)
else
if (load_boot_driver(drv) != 0)
rval = -1;
if (path) {
if (p)
*p = 0;
}
}
return (rval);
}
/*
* For a given path to a boot device,
* load that driver and all its parents.
*/
static int
load_bootpath_drivers(char *bootpath)
{
char *pathcopy;
int pathcopy_len;
int rval;
char *p;
return (-1);
/*
* i386 does not provide stub nodes for all boot devices,
* but we should be able to find the node for the parent,
* and the leaf of the boot path should be the driver name,
* which we go ahead and load here.
*/
char *leaf;
/*
* Find last slash to build the full path to the
* parent of the leaf boot device
*/
*p++ = 0;
/*
* Now isolate the driver name of the leaf device
*/
leaf = p;
*p = 0;
BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
if (leaf) {
if (rval == -1) {
return (NULL);
}
}
}
#endif
bootpath);
return (NULL);
}
/*
* Load IP over IB driver when netbooting over IB.
* As per IB 1275 binding, IP over IB is represented as
* service on the top of the HCA node. So, there is no
* PROM node and generic framework cannot pre-load
* IP over IB driver based on the bootpath. The following
* code preloads IP over IB driver when doing netboot over
* InfiniBand.
*/
if (netboot_over_ib(bootpath) &&
return (NULL);
}
/*
* The PROM node for hubs have incomplete compatible
* properties and therefore do not bind to the hubd driver.
* As a result load_bootpath_drivers() loads the usb_mid driver
* for hub nodes rather than the hubd driver. This causes
* mountroot failures when booting off USB storage. To prevent
* this, if we are booting via USB hubs, we preload the hubd driver.
*/
"but cannot load hubd driver");
}
/* get rid of minor node at end of copy (if not already done above) */
if (p) {
p = strchr(p, ':');
if (p)
*p = 0;
}
return (rval);
}
/*
* Load drivers required for a platform
* Since all hardware nodes should be available in the device
* tree, walk the per-driver list and load the parents of
* each node found. If not a hardware node, try to load it.
* Pseudo nexus is already loaded.
*/
static int
load_boot_platform_modules(char *drv)
{
char *drvname;
int rval = 0;
return (-1);
}
/*
* resolve aliases
*/
return (-1);
#ifdef DEBUG
} else {
BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
}
#endif /* DEBUG */
/* pseudo node, not-enumerated, needs to be loaded */
drvname);
rval = -1;
}
} else {
while (dip) {
rval = -1;
}
}
return (rval);
}
/*
* i_find_node: Internal routine used by path_to_devinfo
* to locate a given nodeid in the device tree.
*/
struct i_path_findnode {
};
static int
{
return (DDI_WALK_TERMINATE);
}
return (DDI_WALK_CONTINUE);
}
/*
* Return the devinfo node to a boot device
*/
static dev_info_t *
path_to_devinfo(char *path)
{
struct i_path_findnode fn;
extern dev_info_t *top_devinfo;
/*
* Get the nodeid of the given pathname, if such a mapping exists.
*/
/*
* Find the nodeid in our copy of the device tree and return
* whatever name we used to bind this node to a driver.
*/
}
#ifdef DEBUG
/*
* If we're bound to something other than the nodename,
* note that in the message buffer and system log.
*/
char *p, *q;
if (p && q && (strcmp(p, q) != 0)) {
BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
path, p));
}
}
#endif /* DEBUG */
}
/*
* This routine returns B_TRUE if the bootpath corresponds to
* IP over IB driver.
*
* The format of the bootpath for the IP over IB looks like
* /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
*
* The minor node portion "port=1,pkey=8001,protocol=ip" represents
* IP over IB driver.
*/
static boolean_t
netboot_over_ib(char *bootpath)
{
char *temp;
int len;
char devicetype[OBP_MAXDRVNAME];
/* Is this IB node ? */
return (B_FALSE);
/* Check for proper IP over IB string */
",protocol=ip")) != NULL) {
}
}
}
return (ret);
}