diff --git a/stand/userboot/userboot/bootinfo32.c b/stand/userboot/userboot/bootinfo32.c index ecd4ccf2edd8..b830b767906d 100644 --- a/stand/userboot/userboot/bootinfo32.c +++ b/stand/userboot/userboot/bootinfo32.c @@ -1,269 +1,269 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "bootstrap.h" #include "libuserboot.h" #ifdef LOADER_GELI_SUPPORT #include "geliboot.h" #endif static struct bootinfo bi; /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ uint32_t x = (v); \ if (c) \ CALLBACK(copyin, &x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ CALLBACK(copyin, s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(uint32_t));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ CALLBACK(copyin, &s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(uint32_t)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ CALLBACK(copyin, mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(uint32_t));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules32(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); MOD_ADDR(addr, fp->f_addr, c); MOD_SIZE(addr, fp->f_size, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Load the information expected by an i386 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; - struct i386_devdesc *rootdev; + struct devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; vm_offset_t kernend; vm_offset_t envp; vm_offset_t size; vm_offset_t ssym, esym; char *rootdevname; int bootdevnr, howto; char *kernelname; const char *kernelpath; uint64_t lowmem, highmem; howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); userboot_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ - getrootmount(userboot_fmtdev((void *)rootdev)); + getrootmount(devformat(rootdev)); bootdevnr = 0; #if 0 if (bootdevnr == -1) { - printf("root device %s invalid\n", i386_fmtdev(rootdev)); + printf("root device %s invalid\n", devformat(rootdev)); return (EINVAL); } #endif free(rootdev); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); #ifdef LOADER_GELI_SUPPORT geli_export_key_metadata(kfp); #endif /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules32(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules32(addr); ssym = esym = 0; md = file_findmetadata(kfp, MODINFOMD_SSYM); if (md != NULL) ssym = *((vm_offset_t *)&(md->md_data)); md = file_findmetadata(kfp, MODINFOMD_ESYM); if (md != NULL) esym = *((vm_offset_t *)&(md->md_data)); if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ /* legacy bootinfo structure */ kernelname = getenv("kernelname"); userboot_getdev(NULL, kernelname, &kernelpath); bi.bi_version = BOOTINFO_VERSION; bi.bi_kernelname = 0; /* XXX char * -> kernel name */ bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */ bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */ #if 0 for (i = 0; i < N_BIOS_GEOM; i++) bi.bi_bios_geom[i] = bd_getbigeom(i); #endif bi.bi_size = sizeof(bi); CALLBACK(getmem, &lowmem, &highmem); bi.bi_memsizes_valid = 1; bi.bi_basemem = 640; bi.bi_extmem = (lowmem - 0x100000) / 1024; bi.bi_envp = envp; bi.bi_modulep = *modulep; bi.bi_kernend = kernend; bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */ bi.bi_esymtab = esym; /* * Copy the legacy bootinfo and kernel name to the guest at 0x2000 */ bi.bi_kernelname = 0x2000 + sizeof(bi); CALLBACK(copyin, &bi, 0x2000, sizeof(bi)); CALLBACK(copyin, kernelname, 0x2000 + sizeof(bi), strlen(kernelname) + 1); /* legacy boot arguments */ *howtop = howto | RB_BOOTINFO; *bootdevp = bootdevnr; *bip = 0x2000; return(0); } diff --git a/stand/userboot/userboot/bootinfo64.c b/stand/userboot/userboot/bootinfo64.c index 60887413e0ec..0086ef21b60a 100644 --- a/stand/userboot/userboot/bootinfo64.c +++ b/stand/userboot/userboot/bootinfo64.c @@ -1,257 +1,257 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "libuserboot.h" /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ uint32_t x = (v); \ if (c) \ CALLBACK(copyin, &x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ CALLBACK(copyin, s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(uint64_t));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ CALLBACK(copyin, &s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(uint64_t)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ CALLBACK(copyin, mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(uint64_t));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules64(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; uint64_t v; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); v = fp->f_addr; MOD_ADDR(addr, v, c); v = fp->f_size; MOD_SIZE(addr, v, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Check to see if this CPU supports long mode. */ static int bi_checkcpu(void) { #if 0 char *cpu_vendor; int vendor[3]; int eflags, regs[4]; /* Check for presence of "cpuid". */ eflags = read_eflags(); write_eflags(eflags ^ PSL_ID); if (!((eflags ^ read_eflags()) & PSL_ID)) return (0); /* Fetch the vendor string. */ do_cpuid(0, regs); vendor[0] = regs[1]; vendor[1] = regs[3]; vendor[2] = regs[2]; cpu_vendor = (char *)vendor; /* Check for vendors that support AMD features. */ if (strncmp(cpu_vendor, INTEL_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, AMD_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, CENTAUR_VENDOR_ID, 12) != 0) return (0); /* Has to support AMD features. */ do_cpuid(0x80000000, regs); if (!(regs[0] >= 0x80000001)) return (0); /* Check for long mode. */ do_cpuid(0x80000001, regs); return (regs[3] & AMDID_LM); #else return (1); #endif } /* * Load the information expected by an amd64 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; - struct userboot_devdesc *rootdev; + struct devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; uint64_t kernend; uint64_t envp; vm_offset_t size; char *rootdevname; int howto; if (!bi_checkcpu()) { printf("CPU doesn't support long mode\n"); return (EINVAL); } howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); userboot_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ - getrootmount(userboot_fmtdev((void *)rootdev)); + getrootmount(devformat(rootdev)); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules64(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules64(addr); return(0); } diff --git a/stand/userboot/userboot/devicename.c b/stand/userboot/userboot/devicename.c index e770e6bf4bb1..45bf9bc6ebd8 100644 --- a/stand/userboot/userboot/devicename.c +++ b/stand/userboot/userboot/devicename.c @@ -1,227 +1,193 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include "bootstrap.h" #include "disk.h" #include "libuserboot.h" #if defined(USERBOOT_ZFS_SUPPORT) #include "libzfs.h" #endif static int userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path); /* * Point (dev) at an allocated device specifier for the device matching the * path in (devspec). If it contains an explicit device specification, * use that. If not, use the default device. */ int userboot_getdev(void **vdev, const char *devspec, const char **path) { struct disk_devdesc **dev = (struct disk_devdesc **)vdev; int rv; /* * If it looks like this is just a path and no * device, go with the current device. */ if ((devspec == NULL) || (devspec[0] == '/') || (strchr(devspec, ':') == NULL)) { rv = userboot_parsedev(dev, getenv("currdev"), NULL); if (rv == 0 && path != NULL) *path = devspec; return (rv); } /* * Try to parse the device name off the beginning of the devspec */ return (userboot_parsedev(dev, devspec, path)); } /* * Point (dev) at an allocated device specifier matching the string version * at the beginning of (devspec). Return a pointer to the remaining * text in (path). * * In all cases, the beginning of (devspec) is compared to the names * of known devices in the device switch, and then any following text * is parsed according to the rules applied to the device type. * * For disk-type devices, the syntax is: * * disk[s][]: * */ static int userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path) { struct disk_devdesc *idev; struct devsw *dv; int i, unit, err; const char *cp; const char *np; /* minimum length check */ if (strlen(devspec) < 2) return (EINVAL); /* look for a device that matches */ for (i = 0, dv = NULL; devsw[i] != NULL; i++) { if (strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name)) == 0) { dv = devsw[i]; break; } } if (dv == NULL) return (ENOENT); idev = malloc(sizeof(struct disk_devdesc)); err = 0; np = (devspec + strlen(dv->dv_name)); switch (dv->dv_type) { case DEVT_NONE: /* XXX what to do here? Do we care? */ break; case DEVT_DISK: err = disk_parsedev(idev, np, path); if (err != 0) goto fail; break; case DEVT_CD: case DEVT_NET: unit = 0; if (*np && (*np != ':')) { /* get unit number if present */ unit = strtol(np, (char **)&cp, 0); if (cp == np) { err = EUNIT; goto fail; } } else { cp = np; } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->dd.d_unit = unit; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_ZFS: #if defined(USERBOOT_ZFS_SUPPORT) err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); if (err != 0) goto fail; break; #else /* FALLTHROUGH */ #endif default: err = EINVAL; goto fail; } idev->dd.d_dev = dv; if (dev == NULL) { free(idev); } else { *dev = idev; } return (0); fail: free(idev); return (err); } -char * -userboot_fmtdev(void *vdev) -{ - struct devdesc *dev = (struct devdesc *)vdev; - static char buf[128]; /* XXX device length constant? */ - - switch(dev->d_dev->dv_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - case DEVT_CD: - sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); - break; - - case DEVT_DISK: - return (disk_fmtdev(vdev)); - - case DEVT_NET: - sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); - break; - - case DEVT_ZFS: -#if defined(USERBOOT_ZFS_SUPPORT) - return (zfs_fmtdev(vdev)); -#else - sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); -#endif - break; - } - return (buf); -} - - /* * Set currdev to suit the value being supplied in (value) */ int userboot_setcurrdev(struct env_var *ev, int flags, const void *value) { struct disk_devdesc *ncurr; int rv; if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0) return (rv); free(ncurr); return (mount_currdev(ev, flags, value)); } diff --git a/stand/userboot/userboot/libuserboot.h b/stand/userboot/userboot/libuserboot.h index 75732c6c0e38..eb3bada097e4 100644 --- a/stand/userboot/userboot/libuserboot.h +++ b/stand/userboot/userboot/libuserboot.h @@ -1,69 +1,68 @@ /*- * Copyright (c) 2011 Google, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include "userboot.h" #include extern struct loader_callbacks *callbacks; extern void *callbacks_arg; #define CALLBACK(fn, args...) (callbacks->fn(callbacks_arg , ##args)) #define MAXDEV 31 /* maximum number of distinct devices */ typedef unsigned long physaddr_t; /* exported devices */ extern struct devsw userboot_disk; extern int userboot_disk_maxunit; extern struct devsw host_dev; /* access to host filesystem */ extern struct fs_ops host_fsops; struct bootinfo; struct preloaded_file; extern int bi_load(struct bootinfo *, struct preloaded_file *); extern void delay(int); extern int userboot_autoload(void); extern ssize_t userboot_copyin(const void *, vm_offset_t, size_t); extern ssize_t userboot_copyout(vm_offset_t, void *, size_t); extern ssize_t userboot_readin(readin_handle_t, vm_offset_t, size_t); extern int userboot_getdev(void **, const char *, const char **); -char *userboot_fmtdev(void *vdev); int userboot_setcurrdev(struct env_var *ev, int flags, const void *value); int bi_getboothowto(char *kargs); void bi_setboothowto(int howto); vm_offset_t bi_copyenv(vm_offset_t addr); int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernend); int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend); void bios_addsmapdata(struct preloaded_file *kfp); diff --git a/stand/userboot/userboot/main.c b/stand/userboot/userboot/main.c index d323d1f9789b..9ede0cd360e9 100644 --- a/stand/userboot/userboot/main.c +++ b/stand/userboot/userboot/main.c @@ -1,347 +1,347 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 1998,2000 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "bootstrap.h" #include "disk.h" #include "libuserboot.h" #if defined(USERBOOT_ZFS_SUPPORT) #include "libzfs.h" static void userboot_zfs_probe(void); static int userboot_zfs_found; #endif /* Minimum version required */ #define USERBOOT_VERSION USERBOOT_VERSION_3 #define LOADER_PATH "/boot/loader" #define INTERP_MARKER "$Interpreter:" #define MALLOCSZ (64*1024*1024) struct loader_callbacks *callbacks; void *callbacks_arg; static jmp_buf jb; struct arch_switch archsw; /* MI/MD interface boundary */ static void extract_currdev(void); static void check_interpreter(void); void delay(int usec) { CALLBACK(delay, usec); } time_t getsecs(void) { /* * userboot can't do netboot, so this implementation isn't strictly * required. Defining it avoids issues with BIND_NOW, and it doesn't * hurt to do it. */ return (time(NULL)); } void exit(int v) { CALLBACK(exit, v); longjmp(jb, 1); } static void check_interpreter(void) { struct stat st; size_t marklen, rdsize; const char *guest_interp, *my_interp; char *buf; int fd; /* * If we can't stat(2) or open(2) LOADER_PATH, then we'll fail by * simply letting us roll on with whatever interpreter we were compiled * with. This is likely not going to be an issue in reality. */ buf = NULL; if (stat(LOADER_PATH, &st) != 0) return; if ((fd = open(LOADER_PATH, O_RDONLY)) < 0) return; rdsize = st.st_size; buf = malloc(rdsize); if (buf == NULL) goto out; if (read(fd, buf, rdsize) < rdsize) goto out; marklen = strlen(INTERP_MARKER); my_interp = bootprog_interp + marklen; /* * Here we make the assumption that a loader binary without the * interpreter marker is a 4th one. All loader binaries going forward * should have this properly specified, so our assumption should always * be a good one. */ if ((guest_interp = memmem(buf, rdsize, INTERP_MARKER, marklen)) != NULL) guest_interp += marklen; else guest_interp = "4th"; /* * The guest interpreter may not have a version of loader that * specifies the interpreter installed. If that's the case, we'll * assume it's legacy (4th) and request a swap to that if we're * a Lua-userboot. */ if (strcmp(my_interp, guest_interp) != 0) CALLBACK(swap_interpreter, guest_interp); out: free(buf); close(fd); return; } void loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks) { static char mallocbuf[MALLOCSZ]; char *var; int i; if (version < USERBOOT_VERSION) abort(); callbacks = cb; callbacks_arg = arg; userboot_disk_maxunit = ndisks; /* * initialise the heap as early as possible. Once this is done, * alloc() is usable. */ setheap((void *)mallocbuf, (void *)(mallocbuf + sizeof(mallocbuf))); /* * Hook up the console */ cons_probe(); /* Set up currdev variable to have hooks in place. */ env_setenv("currdev", EV_VOLATILE, "", userboot_setcurrdev, env_nounset); printf("\n%s", bootprog_info); #if 0 printf("Memory: %ld k\n", memsize() / 1024); #endif setenv("LINES", "24", 1); /* optional */ /* * Set custom environment variables */ i = 0; while (1) { var = CALLBACK(getenv, i++); if (var == NULL) break; putenv(var); } archsw.arch_autoload = userboot_autoload; archsw.arch_getdev = userboot_getdev; archsw.arch_copyin = userboot_copyin; archsw.arch_copyout = userboot_copyout; archsw.arch_readin = userboot_readin; #if defined(USERBOOT_ZFS_SUPPORT) archsw.arch_zfs_probe = userboot_zfs_probe; #endif /* * Initialise the block cache. Set the upper limit. */ bcache_init(32768, 512); /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) if (devsw[i]->dv_init != NULL) (devsw[i]->dv_init)(); extract_currdev(); /* * Checking the interpreter isn't worth the overhead unless we * actually have the swap_interpreter callback, so we actually version * check here rather than later on. */ if (version >= USERBOOT_VERSION_5) check_interpreter(); if (setjmp(jb)) return; interact(); /* doesn't return */ exit(0); } static void set_currdev(const char *devname) { env_setenv("currdev", EV_VOLATILE, devname, userboot_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset); } /* * Set the 'current device' by (if possible) recovering the boot device as * supplied by the initial bootstrap. */ static void extract_currdev(void) { struct disk_devdesc dev; struct devdesc *dd; #if defined(USERBOOT_ZFS_SUPPORT) struct zfs_devdesc zdev; char *buf = NULL; if (userboot_zfs_found) { /* Leave the pool/root guid's unassigned */ bzero(&zdev, sizeof(zdev)); zdev.dd.d_dev = &zfs_dev; init_zfs_boot_options(devformat(&zdev.dd)); dd = &zdev.dd; } else #endif if (userboot_disk_maxunit > 0) { dev.dd.d_dev = &userboot_disk; dev.dd.d_unit = 0; dev.d_slice = D_SLICEWILD; dev.d_partition = D_PARTWILD; /* * If we cannot auto-detect the partition type then * access the disk as a raw device. */ if (dev.dd.d_dev->dv_open(NULL, &dev)) { dev.d_slice = D_SLICENONE; dev.d_partition = D_PARTNONE; } dd = &dev.dd; } else { dev.dd.d_dev = &host_dev; dev.dd.d_unit = 0; dd = &dev.dd; } - set_currdev(userboot_fmtdev(dd)); + set_currdev(devformat(dd)); #if defined(USERBOOT_ZFS_SUPPORT) if (userboot_zfs_found) { buf = malloc(VDEV_PAD_SIZE); if (buf != NULL) { if (zfs_get_bootonce(&zdev, OS_BOOTONCE, buf, VDEV_PAD_SIZE) == 0) { printf("zfs bootonce: %s\n", buf); set_currdev(buf); setenv("zfs-bootonce", buf, 1); } free(buf); (void) zfs_attach_nvstore(&zdev); } } #endif } #if defined(USERBOOT_ZFS_SUPPORT) static void userboot_zfs_probe(void) { char devname[32]; uint64_t pool_guid; int unit; /* * Open all the disks we can find and see if we can reconstruct * ZFS pools from them. Record if any were found. */ for (unit = 0; unit < userboot_disk_maxunit; unit++) { sprintf(devname, "disk%d:", unit); pool_guid = 0; zfs_probe_dev(devname, &pool_guid); if (pool_guid != 0) userboot_zfs_found = 1; } } #endif COMMAND_SET(quit, "quit", "exit the loader", command_quit); static int command_quit(int argc, char *argv[]) { exit(USERBOOT_EXIT_QUIT); return (CMD_OK); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { exit(USERBOOT_EXIT_REBOOT); return (CMD_OK); }