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); }
static int get_fstype_prop(char *fstype) { char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype"; return (BOP_GETPROP(bootops, prop, fstype)); }
static int get_bootpath_prop(char *bootpath) { if (root_is_ramdisk) { if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1) return (-1); (void) strlcat(bootpath, ":a", BO_MAXOBJNAME); } else { /* * Look for the 1275 compliant name 'bootpath' first, * but make certain it has a non-NULL value as well. */ if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) || strlen(bootpath) == 0) { if (BOP_GETPROP(bootops, "boot-path", bootpath) == -1) return (-1); } } return (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); }
/* * 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; }
/* * 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 }
/* * 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 }