Beispiel #1
0
int
kobj_boot_mountroot()
{
	int i;

	if (BOP_GETPROPLEN(ops, "ramdisk_start") != 8 ||
	    BOP_GETPROP(ops, "ramdisk_start", (void *)&rd_start) != 0 ||
	    BOP_GETPROPLEN(ops, "ramdisk_end") != 8 ||
	    BOP_GETPROP(ops, "ramdisk_end", (void *)&rd_end) != 0) {
		_kobj_printf(ops,
		    "failed to get ramdisk from boot\n");
		return (-1);
	}
#ifdef KOBJ_DEBUG
	_kobj_printf(ops,
	    "ramdisk range: 0x%llx-%llx\n", rd_start, rd_end);
#endif

	for (i = 0; bfs_tab[i] != NULL; i++) {
		bfs_ops = bfs_tab[i];
		if (BRD_MOUNTROOT(bfs_ops, "dummy") == 0)
			return (0);
	}
	_kobj_printf(ops, "failed to mount ramdisk from boot\n");
	return (-1);
}
Beispiel #2
0
int
loadrootmodules(void)
{
	struct vfssw	*vsw;
	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());

	BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
	BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
	BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));

	/*
	 * 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
	 * change rootfs with /etc/system AND with tunetool.
	 */
	if (root_is_svm) {
		/* user replaced rootdev, record obp_bootpath */
		obp_bootpath[0] = '\0';
		(void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME);
		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
	} else {
		/*
		 * Get the root fstype and root device path from boot.
		 */
		rootfs.bo_fstype[0] = '\0';
		rootfs.bo_name[0] = '\0';
	}

	/*
	 * This lookup will result in modloadonly-ing the root
	 * filesystem module - it gets _init-ed in rootconf()
	 */
	if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
		return (ENXIO);	/* in case we have no file system types */

	(void) strcpy(rootfs.bo_fstype, vsw->vsw_name);

	vfs_unrefvfssw(vsw);

	/*
	 * 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"));
	for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
		if ((err = load_boot_driver(this)) != 0) {
			cmn_err(CE_WARN, "Cannot load drv/%s", this);
			return (err);
			/* NOTREACHED */
		}
	}
	/*
	 * Now load the platform modules (if any)
	 */
	BMDPRINTF(("loadrootmodules: platform_module_list\n"));
	for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
		if ((err = load_boot_platform_modules(this)) != 0) {
			cmn_err(CE_WARN, "Cannot load drv/%s", this);
			return (err);
			/* NOTREACHED */
		}
	}

loop:
	(void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);

	/*
	 * 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;
	BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
	if (root_is_svm == 0) {
		BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
		name = rootfs.bo_name;
		err = load_bootpath_drivers(rootfs.bo_name);
	}

	/*
	 * Load driver modules in obp_bootpath, this is always
	 * required for mountroot to succeed. obp_bootpath is
	 * is set if rootdev is set via /etc/system, which is
	 * the case if booting of a SVM/VxVM mirror.
	 */
	if ((err == 0) && obp_bootpath[0] != '\0') {
		BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
		name = obp_bootpath;
		err = load_bootpath_drivers(obp_bootpath);
	}

	if (err != 0) {
		cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
		goto out;
		/* NOTREACHED */
	}

	/*
	 * 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.
	 */
	proplen = BOP_GETPROPLEN(bootops, "bootp-response");
	if (proplen > 0) {
		dhcack = kmem_zalloc(proplen, KM_SLEEP);
		if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) {
			cmn_err(CE_WARN, "BOP_GETPROP of  "
			    "\"bootp-response\" failed\n");
			kmem_free(dhcack, dhcacklen);
			dhcack = NULL;
			goto out;
		}
		dhcacklen = proplen;

		/*
		 * Fetch the "netdev-path" boot property (if it exists), and
		 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
		 */
		proplen = BOP_GETPROPLEN(bootops, "netdev-path");
		if (proplen > 0) {
			netdev_path = kmem_zalloc(proplen, KM_SLEEP);
			if (BOP_GETPROP(bootops, "netdev-path",
			    (uchar_t *)netdev_path) == -1) {
				cmn_err(CE_WARN, "BOP_GETPROP of  "
				    "\"netdev-path\" failed\n");
				kmem_free(netdev_path, proplen);
				goto out;
			}
		}
	}

	/*
	 * Preload (load-only, no init) all modules which
	 * were added to the /etc/system file with the
	 * FORCELOAD keyword.
	 */
	BMDPRINTF(("loadrootmodules: preload_module\n"));
	(void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);

/* 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".
	 */

	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
		++netboot;

		if ((err = modload("misc", "tlimod")) < 0)  {
			cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
			goto out;
			/* NOTREACHED */
		}
		if ((err = modload("strmod", "rpcmod")) < 0)  {
			cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
			goto out;
			/* NOTREACHED */
		}
		if ((err = modload("misc", "nfs_dlboot")) < 0)  {
			cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
			goto out;
			/* NOTREACHED */
		}
		if ((err = modload("mac", "mac_ether")) < 0)  {
			cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
			goto out;
			/* NOTREACHED */
		}
		if ((err = modload("misc", "strplumb")) < 0)  {
			cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
			goto out;
			/* NOTREACHED */
		}
		if ((err = strplumb_load()) < 0) {
			goto out;
			/* NOTREACHED */
		}
	}

	/*
	 * Preload modules needed for booting as a cluster.
	 */
	err = clboot_loadrootmodules();

out:
	if (err != 0 && (boothowto & RB_ASKNAME))
		goto loop;

	return (err);
}
Beispiel #3
0
/*
 * Create classes and major number bindings for the name of my root.
 * Called immediately before 'loadrootmodules'
 */
static void
impl_create_root_class(void)
{
	major_t major;
	size_t size;
	char *cp;

	/*
	 * The name for the root nexus is exactly as the manufacturer
	 * placed it in the prom name property.  No translation.
	 */
	if ((major = ddi_name_to_major("rootnex")) == DDI_MAJOR_T_NONE)
		panic("Couldn't find major number for 'rootnex'");

	/*
	 * C OBP (Serengeti) does not include the NULL when returning
	 * the length of the name property, while this violates 1275,
	 * Solaris needs to work around this by allocating space for
	 * an extra character.
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "mfg-name") + 1;
	rootname = kmem_zalloc(size, KM_SLEEP);
	(void) BOP_GETPROP(bootops, "mfg-name", rootname);

	/*
	 * Fix conflict between OBP names and filesystem names.
	 * Substitute '_' for '/' in the name.  Ick.  This is only
	 * needed for the root node since '/' is not a legal name
	 * character in an OBP device name.
	 */
	for (cp = rootname; *cp; cp++)
		if (*cp == '/')
			*cp = '_';

	/*
	 * Bind rootname to rootnex driver
	 */
	if (make_mbind(rootname, major, NULL, mb_hashtab) != 0) {
		cmn_err(CE_WARN, "A driver or driver alias has already "
		    "registered the name \"%s\".  The root nexus needs to "
		    "use this name, and will override the existing entry. "
		    "Please correct /etc/name_to_major and/or "
		    "/etc/driver_aliases and reboot.", rootname);

		/*
		 * Resort to the emergency measure of blowing away the
		 * existing hash entry and replacing it with rootname's.
		 */
		delete_mbind(rootname, mb_hashtab);
		if (make_mbind(rootname, major, NULL, mb_hashtab) != 0)
			panic("mb_hashtab: inconsistent state.");
	}

	/*
	 * The `platform' or `implementation architecture' name has been
	 * translated by boot to be proper for file system use.  It is
	 * the `name' of the platform actually booted.  Note the assumption
	 * is that the name will `fit' in the buffer platform (which is
	 * of size SYS_NMLN, which is far bigger than will actually ever
	 * be needed).
	 */
	(void) BOP_GETPROP(bootops, "impl-arch-name", platform);

	/*
	 * If boot-aoepath is defined, assume it's AoE boot and set bootpath to
	 * aoeblk/blkdev device corresponding to specified shelf.slot numbers.
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "boot-aoepath");
	if (size != -1) {
		char	aoedev[MAXPATHLEN];
		char	*delim;
		int	shelf, slot;

		aoepath_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "boot-aoepath", aoepath_prop);
		/*
		 * If boot-aoepath is set to "auto", device will be
		 * configured later during AoE autoconfiguration.
		 */
		if (strcmp(aoepath_prop, "auto") != 0) {
			if ((delim = strchr(aoepath_prop, '.')) != NULL)
				*delim++ = '\0';
			if (ddi_strtol(aoepath_prop, (char **)NULL, 10,
			    (long *)&shelf) != 0)
				shelf = 0;
			if (delim == NULL ||
			    ddi_strtol(delim, (char **)NULL, 10,
			    (long *)&slot) != 0)
				slot = 0;
			/* FIXME aoeblk@0,0 ?! */
			(void) snprintf(aoedev, MAXPATHLEN,
			    "/aoe/aoeblk@0,0/blkdev@%d,%d",
			    shelf, slot);
			setbootpath(aoedev);
		}
	}

#if defined(__x86)
	/*
	 * Retrieve and honor the bootpath and optional fstype properties
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "bootpath");
	if (size != -1) {
		bootpath_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "bootpath", bootpath_prop);
		setbootpath(bootpath_prop);
	}

	size = (size_t)BOP_GETPROPLEN(bootops, "fstype");
	if (size != -1) {
		fstype_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "fstype", fstype_prop);
		setbootfstype(fstype_prop);
	}
#endif
}
Beispiel #4
0
/*
 * Copy the memlist from boot to kernel, each list is an {addr, size} array
 * with addr and size of 64-bit (u_longlong_t). The returned length for each
 * array is 2*the number of array elements.
 *
 */
void
copy_boot_memlists(u_longlong_t **physinstalled, size_t *physinstalled_len,
    u_longlong_t **physavail, size_t *physavail_len,
    u_longlong_t **virtavail, size_t *virtavail_len)
{
	int	align = BO_ALIGN_L3;
	size_t	len;
	struct bootmem_props *tmp = bootmem_props;

tryagain:
	for (tmp = bootmem_props; tmp->name != NULL; tmp++) {
		len = BOP_GETPROPLEN(bootops, tmp->name);
		if (len == 0) {
			panic("cannot get length of \"%s\" property",
			    tmp->name);
		}
		tmp->nelems = len / sizeof (u_longlong_t);
		len = roundup(len, PAGESIZE);
		if (len <= tmp->bufsize)
			continue;
		/* need to allocate more */
		if (tmp->ptr) {
			BOP_FREE(bootops, (caddr_t)tmp->ptr, tmp->bufsize);
			tmp->ptr = NULL;
			tmp->bufsize = 0;
		}
		tmp->bufsize = len;
		tmp->ptr = (void *)BOP_ALLOC(bootops, 0, tmp->bufsize, align);
		if (tmp->ptr == NULL)
			panic("cannot allocate %lu bytes for \"%s\" property",
			    tmp->bufsize, tmp->name);

	}
	/*
	 * take the most current snapshot we can by calling mem-update
	 */
	if (BOP_GETPROPLEN(bootops, "memory-update") == 0)
		(void) BOP_GETPROP(bootops, "memory-update", NULL);

	/* did the sizes change? */
	for (tmp = bootmem_props; tmp->name != NULL; tmp++) {
		len = BOP_GETPROPLEN(bootops, tmp->name);
		tmp->nelems = len / sizeof (u_longlong_t);
		len = roundup(len, PAGESIZE);
		if (len > tmp->bufsize) {
			/* ick. Free them all and try again */
			for (tmp = bootmem_props; tmp->name != NULL; tmp++) {
				BOP_FREE(bootops, (caddr_t)tmp->ptr,
				    tmp->bufsize);
				tmp->ptr = NULL;
				tmp->bufsize = 0;
			}
			goto tryagain;
		}
	}

	/* now we can retrieve the properties */
	for (tmp = bootmem_props; tmp->name != NULL; tmp++) {
		if (BOP_GETPROP(bootops, tmp->name, tmp->ptr) == -1) {
			panic("cannot retrieve \"%s\" property",
			    tmp->name);
		}
	}
	*physinstalled = bootmem_props[PHYSINSTALLED].ptr;
	*physinstalled_len = bootmem_props[PHYSINSTALLED].nelems;

	*physavail = bootmem_props[PHYSAVAIL].ptr;
	*physavail_len = bootmem_props[PHYSAVAIL].nelems;

	*virtavail = bootmem_props[VIRTAVAIL].ptr;
	*virtavail_len = bootmem_props[VIRTAVAIL].nelems;
}
Beispiel #5
0
/*
 * Create classes and major number bindings for the name of my root.
 * Called immediately before 'loadrootmodules'
 */
static void
impl_create_root_class(void)
{
	major_t major;
	size_t size;
	char *cp;
	extern struct bootops *bootops;

	/*
	 * The name for the root nexus is exactly as the manufacturer
	 * placed it in the prom name property.  No translation.
	 */
	if ((major = ddi_name_to_major("rootnex")) == (major_t)-1)
		panic("Couldn't find major number for 'rootnex'");

	size = (size_t)BOP_GETPROPLEN(bootops, "mfg-name");
	rootname = kmem_zalloc(size, KM_SLEEP);
	(void) BOP_GETPROP(bootops, "mfg-name", rootname);

	/*
	 * Fix conflict between OBP names and filesystem names.
	 * Substitute '_' for '/' in the name.  Ick.  This is only
	 * needed for the root node since '/' is not a legal name
	 * character in an OBP device name.
	 */
	for (cp = rootname; *cp; cp++)
		if (*cp == '/')
			*cp = '_';

	/*
	 * Bind rootname to rootnex driver
	 */
	if (make_mbind(rootname, major, NULL, mb_hashtab) != 0) {
		cmn_err(CE_WARN, "A driver or driver alias has already "
		    "registered the name \"%s\".  The root nexus needs to "
		    "use this name, and will override the existing entry. "
		    "Please correct /etc/name_to_major and/or "
		    "/etc/driver_aliases and reboot.", rootname);

		/*
		 * Resort to the emergency measure of blowing away the
		 * existing hash entry and replacing it with rootname's.
		 */
		delete_mbind(rootname, mb_hashtab);
		if (make_mbind(rootname, major, NULL, mb_hashtab) != 0)
			panic("mb_hashtab: inconsistent state.");
	}

	/*
	 * The `platform' or `implementation architecture' name has been
	 * translated by boot to be proper for file system use.  It is
	 * the `name' of the platform actually booted.  Note the assumption
	 * is that the name will `fit' in the buffer platform (which is
	 * of size SYS_NMLN, which is far bigger than will actually ever
	 * be needed).
	 */
	(void) BOP_GETPROP(bootops, "impl-arch-name", platform);

#if defined(__x86)
	/*
	 * Retrieve and honor the bootpath and optional fstype properties
	 */
	size = (size_t)BOP_GETPROPLEN(bootops, "bootpath");
	if (size != -1) {
		bootpath_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "bootpath", bootpath_prop);
		setbootpath(bootpath_prop);
	}

	size = (size_t)BOP_GETPROPLEN(bootops, "fstype");
	if (size != -1) {
		fstype_prop = kmem_zalloc(size, KM_SLEEP);
		(void) BOP_GETPROP(bootops, "fstype", fstype_prop);
		setbootfstype(fstype_prop);
	}
#endif
}