Index: head/sys/boot/i386/efi/bootinfo.c =================================================================== --- head/sys/boot/i386/efi/bootinfo.c (revision 263004) +++ head/sys/boot/i386/efi/bootinfo.c (revision 263005) @@ -1,297 +1,275 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 2006 Marcel Moolenaar * 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 "libi386.h" #include - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - { "boot_askname", RB_ASKNAME}, - { "boot_cdrom", RB_CDROM}, - { "boot_ddb", RB_KDB}, - { "boot_dfltroot", RB_DFLTROOT}, - { "boot_gdb", RB_GDB}, - { "boot_multicons", RB_MULTIPLE}, - { "boot_mute", RB_MUTE}, - { "boot_pause", RB_PAUSE}, - { "boot_serial", RB_SERIAL}, - { "boot_single", RB_SINGLE}, - { "boot_verbose", RB_VERBOSE}, - { NULL, 0} -}; static const char howto_switches[] = "aCdrgDmphsv"; static int howto_masks[] = { RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE, RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE }; int bi_getboothowto(char *kargs) { const char *sw; char *opts; int howto, i; howto = 0; /* Get the boot options from the environment first. */ for (i = 0; howto_names[i].ev != NULL; i++) { if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; } /* Parse kargs */ if (kargs == NULL) return (howto); opts = strchr(kargs, '-'); while (opts != NULL) { while (*(++opts) != '\0') { sw = strchr(howto_switches, *opts); if (sw == NULL) break; howto |= howto_masks[sw - howto_switches]; } opts = strchr(opts, '-'); } return (howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t start) { struct env_var *ep; vm_offset_t addr, last; size_t len; addr = last = start; /* Traverse the environment. */ for (ep = environ; ep != NULL; ep = ep->ev_next) { len = strlen(ep->ev_name); if (i386_copyin(ep->ev_name, addr, len) != len) break; addr += len; if (i386_copyin("=", addr, 1) != 1) break; addr++; if (ep->ev_value != NULL) { len = strlen(ep->ev_value); if (i386_copyin(ep->ev_value, addr, len) != len) break; addr += len; } if (i386_copyin("", addr, 1) != 1) break; last = ++addr; } if (i386_copyin("", last++, 1) != 1) last = start; return(last); } /* * 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) { \ u_int32_t x = (v); \ i386_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s) { \ COPY32(t, a); \ COPY32(strlen(s) + 1, a); \ i386_copyin(s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ } #define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s) #define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s) #define MOD_ARGS(a, s) MOD_STR(MODINFO_ARGS, a, s) #define MOD_VAR(t, a, s) { \ COPY32(t, a); \ COPY32(sizeof(s), a); \ i386_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_int64_t)); \ } #define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s) #define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s) #define MOD_METADATA(a, mm) { \ COPY32(MODINFO_METADATA | mm->md_type, a); \ COPY32(mm->md_size, a); \ i386_copyin(mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(u_int64_t));\ } #define MOD_END(a) { \ COPY32(MODINFO_END, a); \ COPY32(0, a); \ } vm_offset_t bi_copymodules(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; /* Start with the first module on the list, should be the kernel. */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { /* The name field must come first. */ MOD_NAME(addr, fp->f_name); MOD_TYPE(addr, fp->f_type); if (fp->f_args) MOD_ARGS(addr, fp->f_args); MOD_ADDR(addr, fp->f_addr); MOD_SIZE(addr, fp->f_size); for (md = fp->f_metadata; md != NULL; md = md->md_next) { if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md); } } MOD_END(addr); return(addr); } /* * Load the information expected by the kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load(struct preloaded_file *fp, uint64_t *bi_addr) { struct bootinfo bi; struct preloaded_file *xp; struct file_metadata *md; struct devdesc *rootdev; char *rootdevname; vm_offset_t addr, ssym, esym; bzero(&bi, sizeof(struct bootinfo)); bi.bi_version = 1; // bi.bi_boothowto = bi_getboothowto(fp->f_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"); i386_getdev((void**)&rootdev, rootdevname, NULL); if (rootdev != NULL) { /* Try reading /etc/fstab to select the root device. */ getrootmount(i386_fmtdev(rootdev)); free(rootdev); } md = file_findmetadata(fp, MODINFOMD_SSYM); ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; md = file_findmetadata(fp, MODINFOMD_ESYM); esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; if (ssym != 0 && esym != 0) { bi.bi_symtab = ssym; bi.bi_esymtab = esym; } /* 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; } addr = (addr + 15) & ~15; /* Copy module list and metadata. */ bi.bi_modulep = addr; addr = bi_copymodules(addr); if (addr <= bi.bi_modulep) { addr = bi.bi_modulep; bi.bi_modulep = 0; } addr = (addr + 15) & ~15; /* Copy our environment. */ bi.bi_envp = addr; addr = bi_copyenv(addr); if (addr <= bi.bi_envp) { addr = bi.bi_envp; bi.bi_envp = 0; } addr = (addr + PAGE_MASK) & ~PAGE_MASK; bi.bi_kernend = addr; return (ldr_bootinfo(&bi, bi_addr)); } Index: head/sys/boot/i386/libi386/bootinfo.c =================================================================== --- head/sys/boot/i386/libi386/bootinfo.c (revision 263004) +++ head/sys/boot/i386/libi386/bootinfo.c (revision 263005) @@ -1,192 +1,170 @@ /*- * 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 "libi386.h" #include "btxv86.h" - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; int bi_getboothowto(char *kargs) { char *cp; char *curpos, *next, *string; int howto; int active; int i; int vidconsole; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; /* Enable selected consoles */ string = next = strdup(getenv("console")); vidconsole = 0; while (next != NULL) { curpos = strsep(&next, " ,"); if (*curpos == '\0') continue; if (!strcmp(curpos, "vidconsole")) vidconsole = 1; else if (!strcmp(curpos, "comconsole")) howto |= RB_SERIAL; else if (!strcmp(curpos, "nullconsole")) howto |= RB_MUTE; } if (vidconsole && (howto & RB_SERIAL)) howto |= RB_MULTIPLE; /* * XXX: Note that until the kernel is ready to respect multiple consoles * for the boot messages, the first named console is the primary console */ if (!strcmp(string, "vidconsole")) howto &= ~RB_SERIAL; free(string); return(howto); } void bi_setboothowto(int howto) { int i; for (i = 0; howto_names[i].ev != NULL; i++) if (howto & howto_names[i].mask) setenv(howto_names[i].ev, "YES", 1); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { i386_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); i386_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { i386_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } i386_copyin("", addr, 1); addr++; } i386_copyin("", addr, 1); addr++; return(addr); } Index: head/sys/boot/ia64/common/bootinfo.c =================================================================== --- head/sys/boot/ia64/common/bootinfo.c (revision 263004) +++ head/sys/boot/ia64/common/bootinfo.c (revision 263005) @@ -1,318 +1,296 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 2006 Marcel Moolenaar * 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 "libia64.h" - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - { "boot_askname", RB_ASKNAME}, - { "boot_cdrom", RB_CDROM}, - { "boot_ddb", RB_KDB}, - { "boot_dfltroot", RB_DFLTROOT}, - { "boot_gdb", RB_GDB}, - { "boot_multicons", RB_MULTIPLE}, - { "boot_mute", RB_MUTE}, - { "boot_pause", RB_PAUSE}, - { "boot_serial", RB_SERIAL}, - { "boot_single", RB_SINGLE}, - { "boot_verbose", RB_VERBOSE}, - { NULL, 0} -}; static const char howto_switches[] = "aCdrgDmphsv"; static int howto_masks[] = { RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE, RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE }; int bi_getboothowto(char *kargs) { const char *sw; char *opts; int howto, i; howto = 0; /* Get the boot options from the environment first. */ for (i = 0; howto_names[i].ev != NULL; i++) { if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; } /* Parse kargs */ if (kargs == NULL) return (howto); opts = strchr(kargs, '-'); while (opts != NULL) { while (*(++opts) != '\0') { sw = strchr(howto_switches, *opts); if (sw == NULL) break; howto |= howto_masks[sw - howto_switches]; } opts = strchr(opts, '-'); } return (howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t start) { struct env_var *ep; vm_offset_t addr, last; size_t len; addr = last = start; /* Traverse the environment. */ for (ep = environ; ep != NULL; ep = ep->ev_next) { len = strlen(ep->ev_name); if (ia64_copyin(ep->ev_name, addr, len) != len) break; addr += len; if (ia64_copyin("=", addr, 1) != 1) break; addr++; if (ep->ev_value != NULL) { len = strlen(ep->ev_value); if (ia64_copyin(ep->ev_value, addr, len) != len) break; addr += len; } if (ia64_copyin("", addr, 1) != 1) break; last = ++addr; } if (ia64_copyin("", last++, 1) != 1) last = start; return(last); } /* * 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) { \ u_int32_t x = (v); \ ia64_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s) { \ COPY32(t, a); \ COPY32(strlen(s) + 1, a); \ ia64_copyin(s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ } #define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s) #define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s) #define MOD_ARGS(a, s) MOD_STR(MODINFO_ARGS, a, s) #define MOD_VAR(t, a, s) { \ COPY32(t, a); \ COPY32(sizeof(s), a); \ ia64_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_int64_t)); \ } #define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s) #define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s) #define MOD_METADATA(a, mm) { \ COPY32(MODINFO_METADATA | mm->md_type, a); \ COPY32(mm->md_size, a); \ ia64_copyin(mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(u_int64_t));\ } #define MOD_END(a) { \ COPY32(MODINFO_END, a); \ COPY32(0, a); \ } vm_offset_t bi_copymodules(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; /* Start with the first module on the list, should be the kernel. */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { /* The name field must come first. */ MOD_NAME(addr, fp->f_name); MOD_TYPE(addr, fp->f_type); if (fp->f_args) MOD_ARGS(addr, fp->f_args); MOD_ADDR(addr, fp->f_addr); MOD_SIZE(addr, fp->f_size); for (md = fp->f_metadata; md != NULL; md = md->md_next) { if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md); } } MOD_END(addr); return(addr); } /* * Load the information expected by the kernel. * * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int ia64_bootinfo(struct preloaded_file *fp, struct bootinfo **res) { struct bootinfo bi; struct preloaded_file *xp; struct file_metadata *md; struct devdesc *rootdev; char *rootdevname; vm_offset_t addr, ssym, esym; int error; *res = NULL; bzero(&bi, sizeof(struct bootinfo)); bi.bi_magic = BOOTINFO_MAGIC; bi.bi_version = 1; bi.bi_boothowto = bi_getboothowto(fp->f_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"); ia64_getdev((void**)&rootdev, rootdevname, NULL); if (rootdev != NULL) { /* Try reading /etc/fstab to select the root device. */ getrootmount(ia64_fmtdev(rootdev)); free(rootdev); } md = file_findmetadata(fp, MODINFOMD_SSYM); ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; md = file_findmetadata(fp, MODINFOMD_ESYM); esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; if (ssym != 0 && esym != 0) { bi.bi_symtab = ssym; bi.bi_esymtab = esym; } /* 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; } addr = (addr + 15) & ~15; /* Copy module list and metadata. */ bi.bi_modulep = addr; addr = bi_copymodules(addr); if (addr <= bi.bi_modulep) { addr = bi.bi_modulep; bi.bi_modulep = 0; } addr = (addr + 15) & ~15; /* Copy our environment. */ bi.bi_envp = addr; addr = bi_copyenv(addr); if (addr <= bi.bi_envp) { addr = bi.bi_envp; bi.bi_envp = 0; } addr = (addr + 15) & ~15; bi.bi_kernend = addr; error = ia64_platform_bootinfo(&bi, res); if (error) return (error); if (IS_LEGACY_KERNEL()) { if (*res == NULL) return (EDOOFUS); bcopy(&bi, *res, sizeof(bi)); return (0); } bi.bi_pbvm_pgtbl = (uintptr_t)ia64_pgtbl; bi.bi_pbvm_pgtblsz = ia64_pgtblsz; ia64_copyin((void *)bi.bi_memmap, addr, bi.bi_memmap_size); bi.bi_memmap = addr; addr = (addr + bi.bi_memmap_size + 15) & ~15; bi.bi_kernend = addr + sizeof(bi); ia64_copyin(&bi, addr, sizeof(bi)); *res = (void *)addr; return (0); } Index: head/sys/boot/powerpc/ofw/metadata.c =================================================================== --- head/sys/boot/powerpc/ofw/metadata.c (revision 263004) +++ head/sys/boot/powerpc/ofw/metadata.c (revision 263005) @@ -1,356 +1,334 @@ /*- * 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. * * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include +#include #include #include "bootstrap.h" #include "libofw.h" - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; int md_getboothowto(char *kargs) { char *cp; int howto; int active; int i; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; if (!strcmp(getenv("console"), "comconsole")) howto |= RB_SERIAL; if (!strcmp(getenv("console"), "nullconsole")) howto |= RB_MUTE; return(howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_copyin("", addr, 1); addr++; return(addr); } /* * 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 */ static int align; #define COPY32(v, a, c) { \ u_int32_t x = (v); \ if (c) \ archsw.arch_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) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, align); \ } #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) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), align); \ } #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) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, align); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } vm_offset_t md_copymodules(vm_offset_t addr, int kern64) { struct preloaded_file *fp; struct file_metadata *md; uint64_t scratch64; 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); if (kern64) { scratch64 = fp->f_addr; MOD_ADDR(addr, scratch64, c); scratch64 = fp->f_size; MOD_SIZE(addr, scratch64, c); } else { 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 a powerpc kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load_dual(char *args, vm_offset_t *modulep, int kern64) { struct preloaded_file *kfp; struct preloaded_file *xp; struct file_metadata *md; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; vm_offset_t size; uint64_t scratch64; char *rootdevname; int howto; align = kern64 ? 8 : 4; howto = md_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"); if (rootdevname == NULL) rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); /* 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 = md_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kernend = 0; kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); if (kern64) { scratch64 = envp; file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); scratch64 = kernend; file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); } else { file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); } *modulep = addr; size = md_copymodules(0, kern64); kernend = roundup(addr + size, PAGE_SIZE); md = file_findmetadata(kfp, MODINFOMD_KERNEND); if (kern64) { scratch64 = kernend; bcopy(&scratch64, md->md_data, sizeof scratch64); } else { bcopy(&kernend, md->md_data, sizeof kernend); } (void)md_copymodules(addr, kern64); return(0); } int md_load(char *args, vm_offset_t *modulep) { return (md_load_dual(args, modulep, 0)); } int md_load64(char *args, vm_offset_t *modulep) { return (md_load_dual(args, modulep, 1)); } Index: head/sys/boot/powerpc/ps3/metadata.c =================================================================== --- head/sys/boot/powerpc/ps3/metadata.c (revision 263004) +++ head/sys/boot/powerpc/ps3/metadata.c (revision 263005) @@ -1,355 +1,333 @@ /*- * 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. * * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include +#include #include #include "bootstrap.h" - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; int md_getboothowto(char *kargs) { char *cp; int howto; int active; int i; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; if (!strcmp(getenv("console"), "comconsole")) howto |= RB_SERIAL; if (!strcmp(getenv("console"), "nullconsole")) howto |= RB_MUTE; return(howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_copyin("", addr, 1); addr++; return(addr); } /* * 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 */ static int align; #define COPY32(v, a, c) { \ u_int32_t x = (v); \ if (c) \ archsw.arch_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) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, align); \ } #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) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), align); \ } #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) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, align); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } vm_offset_t md_copymodules(vm_offset_t addr, int kern64) { struct preloaded_file *fp; struct file_metadata *md; uint64_t scratch64; 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); if (kern64) { scratch64 = fp->f_addr; MOD_ADDR(addr, scratch64, c); scratch64 = fp->f_size; MOD_SIZE(addr, scratch64, c); } else { 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 a powerpc kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load_dual(char *args, vm_offset_t *modulep, int kern64) { struct preloaded_file *kfp; struct preloaded_file *xp; struct file_metadata *md; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; vm_offset_t size; uint64_t scratch64; char *rootdevname; int howto; align = kern64 ? 8 : 4; howto = md_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"); if (rootdevname == NULL) rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); /* 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 = md_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kernend = 0; kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); if (kern64) { scratch64 = envp; file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); scratch64 = kernend; file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); } else { file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); } *modulep = addr; size = md_copymodules(0, kern64); kernend = roundup(addr + size, PAGE_SIZE); md = file_findmetadata(kfp, MODINFOMD_KERNEND); if (kern64) { scratch64 = kernend; bcopy(&scratch64, md->md_data, sizeof scratch64); } else { bcopy(&kernend, md->md_data, sizeof kernend); } (void)md_copymodules(addr, kern64); return(0); } int md_load(char *args, vm_offset_t *modulep) { return (md_load_dual(args, modulep, 0)); } int md_load64(char *args, vm_offset_t *modulep) { return (md_load_dual(args, modulep, 1)); } Index: head/sys/boot/sparc64/loader/metadata.c =================================================================== --- head/sys/boot/sparc64/loader/metadata.c (revision 263004) +++ head/sys/boot/sparc64/loader/metadata.c (revision 263005) @@ -1,366 +1,344 @@ /*- * 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. * * from: FreeBSD: src/sys/boot/i386/libi386/bootinfo.c,v 1.29 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include +#include #include #include "bootstrap.h" #include "libofw.h" extern struct tlb_entry *dtlb_store; extern struct tlb_entry *itlb_store; extern int dtlb_slot; extern int itlb_slot; static int md_bootserial(void); - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; int md_getboothowto(char *kargs) { char *cp; int howto; int active; int i; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; if (md_bootserial() != -1) howto |= RB_SERIAL; return(howto); } static int md_bootserial(void) { char buf[64]; ihandle_t inst; phandle_t input; phandle_t node; phandle_t output; if ((node = OF_finddevice("/options")) == -1) return(-1); if (OF_getprop(node, "input-device", buf, sizeof(buf)) == -1) return(-1); input = OF_finddevice(buf); if (OF_getprop(node, "output-device", buf, sizeof(buf)) == -1) return(-1); output = OF_finddevice(buf); if (input == -1 || output == -1 || OF_getproplen(input, "keyboard") >= 0) { if ((node = OF_finddevice("/chosen")) == -1) return(-1); if (OF_getprop(node, "stdin", &inst, sizeof(inst)) == -1) return(-1); if ((input = OF_instance_to_package(inst)) == -1) return(-1); if (OF_getprop(node, "stdout", &inst, sizeof(inst)) == -1) return(-1); if ((output = OF_instance_to_package(inst)) == -1) return(-1); } if (input != output) return(-1); if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) return(-1); if (strcmp(buf, "serial") != 0) return(-1); return(0); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_copyin("", addr, 1); addr++; return(addr); } /* * 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) { \ u_int32_t x = (v); \ if (c) \ archsw.arch_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) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, sizeof(u_long));\ } #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) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_long)); \ } #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) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, sizeof(u_long)); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } vm_offset_t md_copymodules(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 a sparc64 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load(char *args, vm_offset_t *modulep) { struct preloaded_file *kfp; struct preloaded_file *xp; struct file_metadata *md; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; vm_offset_t size; char *rootdevname; int howto; howto = md_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. */ if ((rootdevname = getenv("rootdev")) == NULL) rootdevname = getenv("currdev"); getrootmount(rootdevname); /* 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 = md_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kernend = 0; kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); file_addmetadata(kfp, MODINFOMD_DTLB_SLOTS, sizeof dtlb_slot, &dtlb_slot); file_addmetadata(kfp, MODINFOMD_ITLB_SLOTS, sizeof itlb_slot, &itlb_slot); file_addmetadata(kfp, MODINFOMD_DTLB, dtlb_slot * sizeof(*dtlb_store), dtlb_store); file_addmetadata(kfp, MODINFOMD_ITLB, itlb_slot * sizeof(*itlb_store), itlb_store); *modulep = addr; size = md_copymodules(0); kernend = roundup(addr + size, PAGE_SIZE); md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); (void)md_copymodules(addr); return(0); } Index: head/sys/boot/uboot/common/metadata.c =================================================================== --- head/sys/boot/uboot/common/metadata.c (revision 263004) +++ head/sys/boot/uboot/common/metadata.c (revision 263005) @@ -1,388 +1,366 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (C) 2006 Semihalf, Piotr Kruszynski * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski * 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 "api_public.h" #include "bootstrap.h" #include "glue.h" #if defined(LOADER_FDT_SUPPORT) #include "libuboot.h" #endif - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; static int md_getboothowto(char *kargs) { char *cp; char *p; int howto; int active; int i; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) active = 1; else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) { if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; } if ((p = getenv("console"))) { if (!strcmp(p, "comconsole")) howto |= RB_SERIAL; if (!strcmp(p, "nullconsole")) howto |= RB_MUTE; } return(howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ static vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_copyin("", addr, 1); addr++; return(addr); } /* * 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) { \ u_int32_t x = (v); \ if (c) \ archsw.arch_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) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, sizeof(u_long));\ } #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) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_long)); \ } #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) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, sizeof(u_long)); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t md_copymodules(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; vm_offset_t a; 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 be first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); a = fp->f_addr - __elfN(relocation_offset); MOD_ADDR(addr, a, 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 a kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load(char *args, vm_offset_t *modulep) { struct preloaded_file *kfp, *bfp; struct preloaded_file *xp; struct file_metadata *md; struct bootinfo *bip; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; vm_offset_t size; vm_offset_t vaddr; #if defined(LOADER_FDT_SUPPORT) vm_offset_t dtbp; int dtb_size; #endif char *rootdevname; int howto; int i; /* * These metadata addreses must be converted for kernel after * relocation. */ uint32_t mdt[] = { MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND, MODINFOMD_ENVP, #if defined(LOADER_FDT_SUPPORT) MODINFOMD_DTBP #endif }; howto = md_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"); if (rootdevname == NULL) rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); /* 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 = md_copyenv(addr); /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); #if defined(LOADER_FDT_SUPPORT) /* Handle device tree blob */ dtbp = addr; dtb_size = fdt_copy(addr); /* Pad to a page boundary */ if (dtb_size) addr += roundup(dtb_size, PAGE_SIZE); #endif kernend = 0; kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); #if defined(LOADER_FDT_SUPPORT) if (dtb_size) file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp); else pager_output("WARNING! Trying to fire up the kernel, but no " "device tree blob found!\n"); #endif file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); /* Figure out the size and location of the metadata */ *modulep = addr; size = md_copymodules(0); kernend = roundup(addr + size, PAGE_SIZE); /* Provide MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* Convert addresses to the final VA */ *modulep -= __elfN(relocation_offset); /* Do relocation fixup on metadata of each module. */ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) { md = file_findmetadata(xp, mdt[i]); if (md) { bcopy(md->md_data, &vaddr, sizeof vaddr); vaddr -= __elfN(relocation_offset); bcopy(&vaddr, md->md_data, sizeof vaddr); } } } /* Only now copy actual modules and metadata */ (void)md_copymodules(addr); return (0); } Index: head/sys/boot/userboot/userboot/bootinfo.c =================================================================== --- head/sys/boot/userboot/userboot/bootinfo.c (revision 263004) +++ head/sys/boot/userboot/userboot/bootinfo.c (revision 263005) @@ -1,192 +1,170 @@ /*- * 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" - -/* - * Return a 'boothowto' value corresponding to the kernel arguments in - * (kargs) and any relevant environment variables. - */ -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_cdrom", RB_CDROM}, - {"boot_ddb", RB_KDB}, - {"boot_dfltroot", RB_DFLTROOT}, - {"boot_gdb", RB_GDB}, - {"boot_multicons", RB_MULTIPLE}, - {"boot_mute", RB_MUTE}, - {"boot_pause", RB_PAUSE}, - {"boot_serial", RB_SERIAL}, - {"boot_single", RB_SINGLE}, - {"boot_verbose", RB_VERBOSE}, - {NULL, 0} -}; int bi_getboothowto(char *kargs) { char *cp; char *curpos, *next, *string; int howto; int active; int i; int vidconsole; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; /* Enable selected consoles */ string = next = strdup(getenv("console")); vidconsole = 0; while (next != NULL) { curpos = strsep(&next, " ,"); if (*curpos == '\0') continue; if (!strcmp(curpos, "vidconsole")) vidconsole = 1; else if (!strcmp(curpos, "comconsole")) howto |= RB_SERIAL; else if (!strcmp(curpos, "nullconsole")) howto |= RB_MUTE; } if (vidconsole && (howto & RB_SERIAL)) howto |= RB_MULTIPLE; /* * XXX: Note that until the kernel is ready to respect multiple consoles * for the boot messages, the first named console is the primary console */ if (!strcmp(string, "vidconsole")) howto &= ~RB_SERIAL; free(string); return(howto); } void bi_setboothowto(int howto) { int i; for (i = 0; howto_names[i].ev != NULL; i++) if (howto & howto_names[i].mask) setenv(howto_names[i].ev, "YES", 1); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t bi_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { CALLBACK(copyin, ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); CALLBACK(copyin, "=", addr, 1); addr++; if (ep->ev_value != NULL) { CALLBACK(copyin, ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } CALLBACK(copyin, "", addr, 1); addr++; } CALLBACK(copyin, "", addr, 1); addr++; return(addr); } Index: head/sys/i386/xen/xen_machdep.c =================================================================== --- head/sys/i386/xen/xen_machdep.c (revision 263004) +++ head/sys/i386/xen/xen_machdep.c (revision 263005) @@ -1,1255 +1,1238 @@ /* * * Copyright (c) 2004 Christian Limpach. * Copyright (c) 2004-2006,2008 Kip Macy * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christian Limpach. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SMP #include #endif #include #define IDTVEC(name) __CONCAT(X,name) extern inthand_t IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(xmm), IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall); int xendebug_flags; start_info_t *xen_start_info; start_info_t *HYPERVISOR_start_info; shared_info_t *HYPERVISOR_shared_info; xen_pfn_t *xen_machine_phys = machine_to_phys_mapping; xen_pfn_t *xen_phys_machine; xen_pfn_t *xen_pfn_to_mfn_frame_list[16]; xen_pfn_t *xen_pfn_to_mfn_frame_list_list; int preemptable, init_first; extern unsigned int avail_space; int xen_vector_callback_enabled = 0; enum xen_domain_type xen_domain_type = XEN_PV_DOMAIN; void ni_cli(void); void ni_sti(void); void ni_cli(void) { CTR0(KTR_SPARE2, "ni_cli disabling interrupts"); __asm__("pushl %edx;" "pushl %eax;" ); __cli(); __asm__("popl %eax;" "popl %edx;" ); } void ni_sti(void) { __asm__("pushl %edx;" "pushl %esi;" "pushl %eax;" ); __sti(); __asm__("popl %eax;" "popl %esi;" "popl %edx;" ); } void force_evtchn_callback(void) { (void)HYPERVISOR_xen_version(0, NULL); } /* * Modify the cmd_line by converting ',' to NULLs so that it is in a format * suitable for the static env vars. */ char * xen_setbootenv(char *cmd_line) { char *cmd_line_next; /* Skip leading spaces */ for (; *cmd_line == ' '; cmd_line++); xc_printf("xen_setbootenv(): cmd_line='%s'\n", cmd_line); for (cmd_line_next = cmd_line; strsep(&cmd_line_next, ",") != NULL;); return cmd_line; } - -static struct -{ - const char *ev; - int mask; -} howto_names[] = { - {"boot_askname", RB_ASKNAME}, - {"boot_single", RB_SINGLE}, - {"boot_nosync", RB_NOSYNC}, - {"boot_halt", RB_ASKNAME}, - {"boot_serial", RB_SERIAL}, - {"boot_cdrom", RB_CDROM}, - {"boot_gdb", RB_GDB}, - {"boot_gdb_pause", RB_RESERVED1}, - {"boot_verbose", RB_VERBOSE}, - {"boot_multicons", RB_MULTIPLE}, - {NULL, 0} -}; int xen_boothowto(char *envp) { int i, howto = 0; /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; return howto; } #define XPQUEUE_SIZE 128 struct mmu_log { char *file; int line; }; #ifdef SMP /* per-cpu queues and indices */ #ifdef INVARIANTS static struct mmu_log xpq_queue_log[XEN_LEGACY_MAX_VCPUS][XPQUEUE_SIZE]; #endif static int xpq_idx[XEN_LEGACY_MAX_VCPUS]; static mmu_update_t xpq_queue[XEN_LEGACY_MAX_VCPUS][XPQUEUE_SIZE]; #define XPQ_QUEUE_LOG xpq_queue_log[vcpu] #define XPQ_QUEUE xpq_queue[vcpu] #define XPQ_IDX xpq_idx[vcpu] #define SET_VCPU() int vcpu = smp_processor_id() #else static mmu_update_t xpq_queue[XPQUEUE_SIZE]; #ifdef INVARIANTS static struct mmu_log xpq_queue_log[XPQUEUE_SIZE]; #endif static int xpq_idx = 0; #define XPQ_QUEUE_LOG xpq_queue_log #define XPQ_QUEUE xpq_queue #define XPQ_IDX xpq_idx #define SET_VCPU() #endif /* !SMP */ #define XPQ_IDX_INC atomic_add_int(&XPQ_IDX, 1); #if 0 static void xen_dump_queue(void) { int _xpq_idx = XPQ_IDX; int i; if (_xpq_idx <= 1) return; xc_printf("xen_dump_queue(): %u entries\n", _xpq_idx); for (i = 0; i < _xpq_idx; i++) { xc_printf(" val: %llx ptr: %llx\n", XPQ_QUEUE[i].val, XPQ_QUEUE[i].ptr); } } #endif static __inline void _xen_flush_queue(void) { SET_VCPU(); int _xpq_idx = XPQ_IDX; int error, i; #ifdef INVARIANTS if (__predict_true(gdtset)) CRITICAL_ASSERT(curthread); #endif XPQ_IDX = 0; /* Make sure index is cleared first to avoid double updates. */ error = HYPERVISOR_mmu_update((mmu_update_t *)&XPQ_QUEUE, _xpq_idx, NULL, DOMID_SELF); #if 0 if (__predict_true(gdtset)) for (i = _xpq_idx; i > 0;) { if (i >= 3) { CTR6(KTR_PMAP, "mmu:val: %lx ptr: %lx val: %lx " "ptr: %lx val: %lx ptr: %lx", (XPQ_QUEUE[i-1].val & 0xffffffff), (XPQ_QUEUE[i-1].ptr & 0xffffffff), (XPQ_QUEUE[i-2].val & 0xffffffff), (XPQ_QUEUE[i-2].ptr & 0xffffffff), (XPQ_QUEUE[i-3].val & 0xffffffff), (XPQ_QUEUE[i-3].ptr & 0xffffffff)); i -= 3; } else if (i == 2) { CTR4(KTR_PMAP, "mmu: val: %lx ptr: %lx val: %lx ptr: %lx", (XPQ_QUEUE[i-1].val & 0xffffffff), (XPQ_QUEUE[i-1].ptr & 0xffffffff), (XPQ_QUEUE[i-2].val & 0xffffffff), (XPQ_QUEUE[i-2].ptr & 0xffffffff)); i = 0; } else { CTR2(KTR_PMAP, "mmu: val: %lx ptr: %lx", (XPQ_QUEUE[i-1].val & 0xffffffff), (XPQ_QUEUE[i-1].ptr & 0xffffffff)); i = 0; } } #endif if (__predict_false(error < 0)) { for (i = 0; i < _xpq_idx; i++) printf("val: %llx ptr: %llx\n", XPQ_QUEUE[i].val, XPQ_QUEUE[i].ptr); panic("Failed to execute MMU updates: %d", error); } } void xen_flush_queue(void) { SET_VCPU(); if (__predict_true(gdtset)) critical_enter(); if (XPQ_IDX != 0) _xen_flush_queue(); if (__predict_true(gdtset)) critical_exit(); } static __inline void xen_increment_idx(void) { SET_VCPU(); XPQ_IDX++; if (__predict_false(XPQ_IDX == XPQUEUE_SIZE)) xen_flush_queue(); } void xen_check_queue(void) { #ifdef INVARIANTS SET_VCPU(); KASSERT(XPQ_IDX == 0, ("pending operations XPQ_IDX=%d", XPQ_IDX)); #endif } void xen_invlpg(vm_offset_t va) { struct mmuext_op op; op.cmd = MMUEXT_INVLPG_ALL; op.arg1.linear_addr = va & ~PAGE_MASK; PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_load_cr3(u_int val) { struct mmuext_op op; #ifdef INVARIANTS SET_VCPU(); KASSERT(XPQ_IDX == 0, ("pending operations XPQ_IDX=%d", XPQ_IDX)); #endif op.cmd = MMUEXT_NEW_BASEPTR; op.arg1.mfn = xpmap_ptom(val) >> PAGE_SHIFT; PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } #ifdef KTR static __inline u_int rebp(void) { u_int data; __asm __volatile("movl 4(%%ebp),%0" : "=r" (data)); return (data); } #endif u_int read_eflags(void) { vcpu_info_t *_vcpu; u_int eflags; eflags = _read_eflags(); _vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()]; if (_vcpu->evtchn_upcall_mask) eflags &= ~PSL_I; return (eflags); } void write_eflags(u_int eflags) { u_int intr; CTR2(KTR_SPARE2, "%x xen_restore_flags eflags %x", rebp(), eflags); intr = ((eflags & PSL_I) == 0); __restore_flags(intr); _write_eflags(eflags); } void xen_cli(void) { CTR1(KTR_SPARE2, "%x xen_cli disabling interrupts", rebp()); __cli(); } void xen_sti(void) { CTR1(KTR_SPARE2, "%x xen_sti enabling interrupts", rebp()); __sti(); } u_int xen_rcr2(void) { return (HYPERVISOR_shared_info->vcpu_info[curcpu].arch.cr2); } void _xen_machphys_update(vm_paddr_t mfn, vm_paddr_t pfn, char *file, int line) { SET_VCPU(); if (__predict_true(gdtset)) critical_enter(); XPQ_QUEUE[XPQ_IDX].ptr = (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; XPQ_QUEUE[XPQ_IDX].val = pfn; #ifdef INVARIANTS XPQ_QUEUE_LOG[XPQ_IDX].file = file; XPQ_QUEUE_LOG[XPQ_IDX].line = line; #endif xen_increment_idx(); if (__predict_true(gdtset)) critical_exit(); } extern struct rwlock pvh_global_lock; void _xen_queue_pt_update(vm_paddr_t ptr, vm_paddr_t val, char *file, int line) { SET_VCPU(); if (__predict_true(gdtset)) rw_assert(&pvh_global_lock, RA_WLOCKED); KASSERT((ptr & 7) == 0, ("misaligned update")); if (__predict_true(gdtset)) critical_enter(); XPQ_QUEUE[XPQ_IDX].ptr = ((uint64_t)ptr) | MMU_NORMAL_PT_UPDATE; XPQ_QUEUE[XPQ_IDX].val = (uint64_t)val; #ifdef INVARIANTS XPQ_QUEUE_LOG[XPQ_IDX].file = file; XPQ_QUEUE_LOG[XPQ_IDX].line = line; #endif xen_increment_idx(); if (__predict_true(gdtset)) critical_exit(); } void xen_pgdpt_pin(vm_paddr_t ma) { struct mmuext_op op; op.cmd = MMUEXT_PIN_L3_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_pgd_pin(vm_paddr_t ma) { struct mmuext_op op; op.cmd = MMUEXT_PIN_L2_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_pgd_unpin(vm_paddr_t ma) { struct mmuext_op op; op.cmd = MMUEXT_UNPIN_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_pt_pin(vm_paddr_t ma) { struct mmuext_op op; op.cmd = MMUEXT_PIN_L1_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_pt_unpin(vm_paddr_t ma) { struct mmuext_op op; op.cmd = MMUEXT_UNPIN_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_set_ldt(vm_paddr_t ptr, unsigned long len) { struct mmuext_op op; op.cmd = MMUEXT_SET_LDT; op.arg1.linear_addr = ptr; op.arg2.nr_ents = len; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_tlb_flush(void) { struct mmuext_op op; op.cmd = MMUEXT_TLB_FLUSH_LOCAL; xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } void xen_update_descriptor(union descriptor *table, union descriptor *entry) { vm_paddr_t pa; pt_entry_t *ptp; ptp = vtopte((vm_offset_t)table); pa = (*ptp & PG_FRAME) | ((vm_offset_t)table & PAGE_MASK); if (HYPERVISOR_update_descriptor(pa, *(uint64_t *)entry)) panic("HYPERVISOR_update_descriptor failed\n"); } #if 0 /* * Bitmap is indexed by page number. If bit is set, the page is part of a * xen_create_contiguous_region() area of memory. */ unsigned long *contiguous_bitmap; static void contiguous_bitmap_set(unsigned long first_page, unsigned long nr_pages) { unsigned long start_off, end_off, curr_idx, end_idx; curr_idx = first_page / BITS_PER_LONG; start_off = first_page & (BITS_PER_LONG-1); end_idx = (first_page + nr_pages) / BITS_PER_LONG; end_off = (first_page + nr_pages) & (BITS_PER_LONG-1); if (curr_idx == end_idx) { contiguous_bitmap[curr_idx] |= ((1UL<> PAGE_SHIFT; mfn = PFNTOMFN(pfn); PFNTOMFN(pfn) = INVALID_P2M_ENTRY; PANIC_IF(HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation) != 1); } /* 2. Get a new contiguous memory extent. */ reservation.extent_order = order; /* xenlinux hardcodes this because of aacraid - maybe set to 0 if we're not * running with a broxen driver XXXEN */ reservation.address_bits = 31; if (HYPERVISOR_memory_op(XENMEM_increase_reservation, &reservation) != 1) goto fail; /* 3. Map the new extent in place of old pages. */ for (i = 0; i < (1 << order); i++) { int pfn; pfn = VM_PAGE_TO_PHYS(&pages[i]) >> PAGE_SHIFT; xen_machphys_update(mfn+i, pfn); PFNTOMFN(pfn) = mfn+i; } xen_tlb_flush(); #if 0 contiguous_bitmap_set(VM_PAGE_TO_PHYS(&pages[0]) >> PAGE_SHIFT, 1UL << order); #endif balloon_unlock(flags); return 0; fail: reservation.extent_order = 0; reservation.address_bits = 0; for (i = 0; i < (1 << order); i++) { int pfn; pfn = VM_PAGE_TO_PHYS(&pages[i]) >> PAGE_SHIFT; PANIC_IF(HYPERVISOR_memory_op( XENMEM_increase_reservation, &reservation) != 1); xen_machphys_update(mfn, pfn); PFNTOMFN(pfn) = mfn; } xen_tlb_flush(); balloon_unlock(flags); return ENOMEM; } void xen_destroy_contiguous_region(void *addr, int npages) { unsigned long mfn, i, flags, order, pfn0; struct xen_memory_reservation reservation = { .nr_extents = 1, .extent_order = 0, .domid = DOMID_SELF }; set_xen_guest_handle(reservation.extent_start, &mfn); pfn0 = vtophys(addr) >> PAGE_SHIFT; #if 0 scrub_pages(vstart, 1 << order); #endif /* can currently only handle power of two allocation */ PANIC_IF(ffs(npages) != fls(npages)); /* 0. determine order */ order = (ffs(npages) == fls(npages)) ? fls(npages) - 1 : fls(npages); balloon_lock(flags); #if 0 contiguous_bitmap_clear(vtophys(addr) >> PAGE_SHIFT, 1UL << order); #endif /* 1. Zap current PTEs, giving away the underlying pages. */ for (i = 0; i < (1 << order); i++) { int pfn; uint64_t new_val = 0; pfn = vtomach((char *)addr + i*PAGE_SIZE) >> PAGE_SHIFT; PANIC_IF(HYPERVISOR_update_va_mapping((vm_offset_t)((char *)addr + (i * PAGE_SIZE)), new_val, 0)); PFNTOMFN(pfn) = INVALID_P2M_ENTRY; PANIC_IF(HYPERVISOR_memory_op( XENMEM_decrease_reservation, &reservation) != 1); } /* 2. Map new pages in place of old pages. */ for (i = 0; i < (1 << order); i++) { int pfn; uint64_t new_val; pfn = pfn0 + i; PANIC_IF(HYPERVISOR_memory_op(XENMEM_increase_reservation, &reservation) != 1); new_val = mfn << PAGE_SHIFT; PANIC_IF(HYPERVISOR_update_va_mapping((vm_offset_t)addr + (i * PAGE_SIZE), new_val, PG_KERNEL)); xen_machphys_update(mfn, pfn); PFNTOMFN(pfn) = mfn; } xen_tlb_flush(); balloon_unlock(flags); } extern vm_offset_t proc0kstack; extern int vm86paddr, vm86phystk; char *bootmem_start, *bootmem_current, *bootmem_end; pteinfo_t *pteinfo_list; void initvalues(start_info_t *startinfo); struct xenstore_domain_interface; extern struct xenstore_domain_interface *xen_store; void * bootmem_alloc(unsigned int size) { char *retptr; retptr = bootmem_current; PANIC_IF(retptr + size > bootmem_end); bootmem_current += size; return retptr; } void bootmem_free(void *ptr, unsigned int size) { char *tptr; tptr = ptr; PANIC_IF(tptr != bootmem_current - size || bootmem_current - size < bootmem_start); bootmem_current -= size; } #if 0 static vm_paddr_t xpmap_mtop2(vm_paddr_t mpa) { return ((machine_to_phys_mapping[mpa >> PAGE_SHIFT] << PAGE_SHIFT) ) | (mpa & ~PG_FRAME); } static pd_entry_t xpmap_get_bootpde(vm_paddr_t va) { return ((pd_entry_t *)xen_start_info->pt_base)[va >> 22]; } static pd_entry_t xpmap_get_vbootpde(vm_paddr_t va) { pd_entry_t pde; pde = xpmap_get_bootpde(va); if ((pde & PG_V) == 0) return (pde & ~PG_FRAME); return (pde & ~PG_FRAME) | (xpmap_mtop2(pde & PG_FRAME) + KERNBASE); } static pt_entry_t 8* xpmap_get_bootptep(vm_paddr_t va) { pd_entry_t pde; pde = xpmap_get_vbootpde(va); if ((pde & PG_V) == 0) return (void *)-1; #define PT_MASK 0x003ff000 /* page table address bits */ return &(((pt_entry_t *)(pde & PG_FRAME))[(va & PT_MASK) >> PAGE_SHIFT]); } static pt_entry_t xpmap_get_bootpte(vm_paddr_t va) { return xpmap_get_bootptep(va)[0]; } #endif #ifdef ADD_ISA_HOLE static void shift_phys_machine(unsigned long *phys_machine, int nr_pages) { unsigned long *tmp_page, *current_page, *next_page; int i; tmp_page = bootmem_alloc(PAGE_SIZE); current_page = phys_machine + nr_pages - (PAGE_SIZE/sizeof(unsigned long)); next_page = current_page - (PAGE_SIZE/sizeof(unsigned long)); bcopy(phys_machine, tmp_page, PAGE_SIZE); while (current_page > phys_machine) { /* save next page */ bcopy(next_page, tmp_page, PAGE_SIZE); /* shift down page */ bcopy(current_page, next_page, PAGE_SIZE); /* finish swap */ bcopy(tmp_page, current_page, PAGE_SIZE); current_page -= (PAGE_SIZE/sizeof(unsigned long)); next_page -= (PAGE_SIZE/sizeof(unsigned long)); } bootmem_free(tmp_page, PAGE_SIZE); for (i = 0; i < nr_pages; i++) { xen_machphys_update(phys_machine[i], i); } memset(phys_machine, INVALID_P2M_ENTRY, PAGE_SIZE); } #endif /* ADD_ISA_HOLE */ /* * Build a directory of the pages that make up our Physical to Machine * mapping table. The Xen suspend/restore code uses this to find our * mapping table. */ static void init_frame_list_list(void *arg) { unsigned long nr_pages = xen_start_info->nr_pages; #define FPP (PAGE_SIZE/sizeof(xen_pfn_t)) int i, j, k; xen_pfn_to_mfn_frame_list_list = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); for (i = 0, j = 0, k = -1; i < nr_pages; i += FPP, j++) { if ((j & (FPP - 1)) == 0) { k++; xen_pfn_to_mfn_frame_list[k] = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); xen_pfn_to_mfn_frame_list_list[k] = VTOMFN(xen_pfn_to_mfn_frame_list[k]); j = 0; } xen_pfn_to_mfn_frame_list[k][j] = VTOMFN(&xen_phys_machine[i]); } HYPERVISOR_shared_info->arch.max_pfn = nr_pages; HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = VTOMFN(xen_pfn_to_mfn_frame_list_list); } SYSINIT(init_fll, SI_SUB_DEVFS, SI_ORDER_ANY, init_frame_list_list, NULL); extern unsigned long physfree; int pdir, curoffset; extern int nkpt; extern uint32_t kernbase; void initvalues(start_info_t *startinfo) { vm_offset_t cur_space, cur_space_pt; struct physdev_set_iopl set_iopl; int l3_pages, l2_pages, l1_pages, offset; vm_paddr_t console_page_ma, xen_store_ma; vm_offset_t tmpva; vm_paddr_t shinfo; #ifdef PAE vm_paddr_t IdlePDPTma, IdlePDPTnewma; vm_paddr_t IdlePTDnewma[4]; pd_entry_t *IdlePDPTnew, *IdlePTDnew; vm_paddr_t IdlePTDma[4]; #else vm_paddr_t IdlePTDma[1]; #endif unsigned long i; int ncpus = MAXCPU; nkpt = min( min( max((startinfo->nr_pages >> NPGPTD_SHIFT), nkpt), NPGPTD*NPDEPG - KPTDI), (HYPERVISOR_VIRT_START - KERNBASE) >> PDRSHIFT); HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); #ifdef notyet /* * need to install handler */ HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments_notify); #endif xen_start_info = startinfo; HYPERVISOR_start_info = startinfo; xen_phys_machine = (xen_pfn_t *)startinfo->mfn_list; IdlePTD = (pd_entry_t *)((uint8_t *)startinfo->pt_base + PAGE_SIZE); l1_pages = 0; #ifdef PAE l3_pages = 1; l2_pages = 0; IdlePDPT = (pd_entry_t *)startinfo->pt_base; IdlePDPTma = VTOM(startinfo->pt_base); for (i = (KERNBASE >> 30); (i < 4) && (IdlePDPT[i] != 0); i++) l2_pages++; /* * Note that only one page directory has been allocated at this point. * Thus, if KERNBASE */ for (i = 0; i < l2_pages; i++) IdlePTDma[i] = VTOM(IdlePTD + i*PAGE_SIZE); l2_pages = (l2_pages == 0) ? 1 : l2_pages; #else l3_pages = 0; l2_pages = 1; #endif for (i = (((KERNBASE>>18) & PAGE_MASK)>>PAGE_SHIFT); (i>PDRSHIFT)); i++) { if (IdlePTD[i] == 0) break; l1_pages++; } /* number of pages allocated after the pts + 1*/; cur_space = xen_start_info->pt_base + (l3_pages + l2_pages + l1_pages + 1)*PAGE_SIZE; xc_printf("initvalues(): wooh - availmem=%x,%x\n", avail_space, cur_space); xc_printf("KERNBASE=%x,pt_base=%lx, VTOPFN(base)=%x, nr_pt_frames=%lx\n", KERNBASE,xen_start_info->pt_base, VTOPFN(xen_start_info->pt_base), xen_start_info->nr_pt_frames); xendebug_flags = 0; /* 0xffffffff; */ #ifdef ADD_ISA_HOLE shift_phys_machine(xen_phys_machine, xen_start_info->nr_pages); #endif XENPRINTF("IdlePTD %p\n", IdlePTD); XENPRINTF("nr_pages: %ld shared_info: 0x%lx flags: 0x%x pt_base: 0x%lx " "mod_start: 0x%lx mod_len: 0x%lx\n", xen_start_info->nr_pages, xen_start_info->shared_info, xen_start_info->flags, xen_start_info->pt_base, xen_start_info->mod_start, xen_start_info->mod_len); #ifdef PAE IdlePDPTnew = (pd_entry_t *)cur_space; cur_space += PAGE_SIZE; bzero(IdlePDPTnew, PAGE_SIZE); IdlePDPTnewma = VTOM(IdlePDPTnew); IdlePTDnew = (pd_entry_t *)cur_space; cur_space += 4*PAGE_SIZE; bzero(IdlePTDnew, 4*PAGE_SIZE); for (i = 0; i < 4; i++) IdlePTDnewma[i] = VTOM((uint8_t *)IdlePTDnew + i*PAGE_SIZE); /* * L3 * * Copy the 4 machine addresses of the new PTDs in to the PDPT * */ for (i = 0; i < 4; i++) IdlePDPTnew[i] = IdlePTDnewma[i] | PG_V; __asm__("nop;"); /* * * re-map the new PDPT read-only */ PT_SET_MA(IdlePDPTnew, IdlePDPTnewma | PG_V); /* * * Unpin the current PDPT */ xen_pt_unpin(IdlePDPTma); #endif /* PAE */ /* Map proc0's KSTACK */ proc0kstack = cur_space; cur_space += (KSTACK_PAGES * PAGE_SIZE); xc_printf("proc0kstack=%u\n", proc0kstack); /* vm86/bios stack */ cur_space += PAGE_SIZE; /* Map space for the vm86 region */ vm86paddr = (vm_offset_t)cur_space; cur_space += (PAGE_SIZE * 3); /* allocate 4 pages for bootmem allocator */ bootmem_start = bootmem_current = (char *)cur_space; cur_space += (4 * PAGE_SIZE); bootmem_end = (char *)cur_space; /* allocate pages for gdt */ gdt = (union descriptor *)cur_space; cur_space += PAGE_SIZE*ncpus; /* allocate page for ldt */ ldt = (union descriptor *)cur_space; cur_space += PAGE_SIZE; cur_space += PAGE_SIZE; /* unmap remaining pages from initial chunk * */ for (tmpva = cur_space; tmpva < (((uint32_t)&kernbase) + (l1_pages<> 18)), ((uint8_t *)IdlePTD) + ((KERNBASE >> 18) & PAGE_MASK), l1_pages*sizeof(pt_entry_t)); for (i = 0; i < 4; i++) { PT_SET_MA((uint8_t *)IdlePTDnew + i*PAGE_SIZE, IdlePTDnewma[i] | PG_V); } xen_load_cr3(VTOP(IdlePDPTnew)); xen_pgdpt_pin(VTOM(IdlePDPTnew)); /* allocate remainder of nkpt pages */ cur_space_pt = cur_space; for (offset = (KERNBASE >> PDRSHIFT), i = l1_pages; i < nkpt; i++, cur_space += PAGE_SIZE) { pdir = (offset + i) / NPDEPG; curoffset = ((offset + i) % NPDEPG); if (((offset + i) << PDRSHIFT) == VM_MAX_KERNEL_ADDRESS) break; /* * make sure that all the initial page table pages * have been zeroed */ PT_SET_MA(cur_space, VTOM(cur_space) | PG_V | PG_RW); bzero((char *)cur_space, PAGE_SIZE); PT_SET_MA(cur_space, (vm_paddr_t)0); xen_pt_pin(VTOM(cur_space)); xen_queue_pt_update((vm_paddr_t)(IdlePTDnewma[pdir] + curoffset*sizeof(vm_paddr_t)), VTOM(cur_space) | PG_KERNEL); PT_UPDATES_FLUSH(); } for (i = 0; i < 4; i++) { pdir = (PTDPTDI + i) / NPDEPG; curoffset = (PTDPTDI + i) % NPDEPG; xen_queue_pt_update((vm_paddr_t)(IdlePTDnewma[pdir] + curoffset*sizeof(vm_paddr_t)), IdlePTDnewma[i] | PG_V); } PT_UPDATES_FLUSH(); IdlePTD = IdlePTDnew; IdlePDPT = IdlePDPTnew; IdlePDPTma = IdlePDPTnewma; HYPERVISOR_shared_info = (shared_info_t *)cur_space; cur_space += PAGE_SIZE; xen_store = (struct xenstore_domain_interface *)cur_space; cur_space += PAGE_SIZE; console_page = (char *)cur_space; cur_space += PAGE_SIZE; /* * shared_info is an unsigned long so this will randomly break if * it is allocated above 4GB - I guess people are used to that * sort of thing with Xen ... sigh */ shinfo = xen_start_info->shared_info; PT_SET_MA(HYPERVISOR_shared_info, shinfo | PG_KERNEL); xc_printf("#4\n"); xen_store_ma = (((vm_paddr_t)xen_start_info->store_mfn) << PAGE_SHIFT); PT_SET_MA(xen_store, xen_store_ma | PG_KERNEL); console_page_ma = (((vm_paddr_t)xen_start_info->console.domU.mfn) << PAGE_SHIFT); PT_SET_MA(console_page, console_page_ma | PG_KERNEL); xc_printf("#5\n"); set_iopl.iopl = 1; PANIC_IF(HYPERVISOR_physdev_op(PHYSDEVOP_SET_IOPL, &set_iopl)); xc_printf("#6\n"); #if 0 /* add page table for KERNBASE */ xen_queue_pt_update(IdlePTDma + KPTDI*sizeof(vm_paddr_t), VTOM(cur_space) | PG_KERNEL); xen_flush_queue(); #ifdef PAE xen_queue_pt_update(pdir_shadow_ma[3] + KPTDI*sizeof(vm_paddr_t), VTOM(cur_space) | PG_V | PG_A); #else xen_queue_pt_update(pdir_shadow_ma + KPTDI*sizeof(vm_paddr_t), VTOM(cur_space) | PG_V | PG_A); #endif xen_flush_queue(); cur_space += PAGE_SIZE; xc_printf("#6\n"); #endif /* 0 */ #ifdef notyet if (xen_start_info->flags & SIF_INITDOMAIN) { /* Map first megabyte */ for (i = 0; i < (256 << PAGE_SHIFT); i += PAGE_SIZE) PT_SET_MA(KERNBASE + i, i | PG_KERNEL | PG_NC_PCD); xen_flush_queue(); } #endif /* * re-map kernel text read-only * */ for (i = (((vm_offset_t)&btext) & ~PAGE_MASK); i < (((vm_offset_t)&etext) & ~PAGE_MASK); i += PAGE_SIZE) PT_SET_MA(i, VTOM(i) | PG_V | PG_A); xc_printf("#7\n"); physfree = VTOP(cur_space); init_first = physfree >> PAGE_SHIFT; IdlePTD = (pd_entry_t *)VTOP(IdlePTD); IdlePDPT = (pd_entry_t *)VTOP(IdlePDPT); setup_xen_features(); xc_printf("#8, proc0kstack=%u\n", proc0kstack); } trap_info_t trap_table[] = { { 0, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(div)}, { 1, 0|4, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(dbg)}, { 3, 3|4, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(bpt)}, { 4, 3, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(ofl)}, /* This is UPL on Linux and KPL on BSD */ { 5, 3, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(bnd)}, { 6, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(ill)}, { 7, 0|4, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(dna)}, /* * { 8, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(XXX)}, * no handler for double fault */ { 9, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(fpusegm)}, {10, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(tss)}, {11, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(missing)}, {12, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(stk)}, {13, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(prot)}, {14, 0|4, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(page)}, {15, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(rsvd)}, {16, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(fpu)}, {17, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(align)}, {18, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(mchk)}, {19, 0, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(xmm)}, {0x80, 3, GSEL(GCODE_SEL, SEL_KPL), (unsigned long) &IDTVEC(int0x80_syscall)}, { 0, 0, 0, 0 } }; /* Perform a multicall and check that individual calls succeeded. */ int HYPERVISOR_multicall(struct multicall_entry * call_list, int nr_calls) { int ret = 0; int i; /* Perform the multicall. */ PANIC_IF(_HYPERVISOR_multicall(call_list, nr_calls)); /* Check the results of individual hypercalls. */ for (i = 0; i < nr_calls; i++) if (__predict_false(call_list[i].result < 0)) ret++; if (__predict_false(ret > 0)) panic("%d multicall(s) failed: cpu %d\n", ret, smp_processor_id()); /* If we didn't panic already, everything succeeded. */ return (0); } /********** CODE WORTH KEEPING ABOVE HERE *****************/ void xen_failsafe_handler(void); void xen_failsafe_handler(void) { panic("xen_failsafe_handler called!\n"); } void xen_handle_thread_switch(struct pcb *pcb); /* This is called by cpu_switch() when switching threads. */ /* The pcb arg refers to the process control block of the */ /* next thread which is to run */ void xen_handle_thread_switch(struct pcb *pcb) { uint32_t *a = (uint32_t *)&PCPU_GET(fsgs_gdt)[0]; uint32_t *b = (uint32_t *)&pcb->pcb_fsd; multicall_entry_t mcl[3]; int i = 0; /* Notify Xen of task switch */ mcl[i].op = __HYPERVISOR_stack_switch; mcl[i].args[0] = GSEL(GDATA_SEL, SEL_KPL); mcl[i++].args[1] = (unsigned long)pcb; /* Check for update of fsd */ if (*a != *b || *(a+1) != *(b+1)) { mcl[i].op = __HYPERVISOR_update_descriptor; *(uint64_t *)&mcl[i].args[0] = vtomach((vm_offset_t)a); *(uint64_t *)&mcl[i++].args[2] = *(uint64_t *)b; } a += 2; b += 2; /* Check for update of gsd */ if (*a != *b || *(a+1) != *(b+1)) { mcl[i].op = __HYPERVISOR_update_descriptor; *(uint64_t *)&mcl[i].args[0] = vtomach((vm_offset_t)a); *(uint64_t *)&mcl[i++].args[2] = *(uint64_t *)b; } (void)HYPERVISOR_multicall(mcl, i); } Index: head/sys/sys/boot.h =================================================================== --- head/sys/sys/boot.h (nonexistent) +++ head/sys/sys/boot.h (revision 263005) @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2014 Roger Pau Monné + * 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$ + */ + +#ifndef _SYS_BOOT_H_ +#define _SYS_BOOT_H_ + +/* + * Return a 'boothowto' value corresponding to the kernel arguments in + * (kargs) and any relevant environment variables. + */ +static struct +{ + const char *ev; + int mask; +} howto_names[] = { + { "boot_askname", RB_ASKNAME}, + { "boot_cdrom", RB_CDROM}, + { "boot_ddb", RB_KDB}, + { "boot_dfltroot", RB_DFLTROOT}, + { "boot_gdb", RB_GDB}, + { "boot_multicons", RB_MULTIPLE}, + { "boot_mute", RB_MUTE}, + { "boot_pause", RB_PAUSE}, + { "boot_serial", RB_SERIAL}, + { "boot_single", RB_SINGLE}, + { "boot_verbose", RB_VERBOSE}, + { NULL, 0} +}; + +#endif /* !_SYS_BOOT_H_ */ Property changes on: head/sys/sys/boot.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/x86/xen/pv.c =================================================================== --- head/sys/x86/xen/pv.c (revision 263004) +++ head/sys/x86/xen/pv.c (revision 263005) @@ -1,123 +1,124 @@ /* * Copyright (c) 2004 Christian Limpach. * Copyright (c) 2004-2006,2008 Kip Macy * Copyright (c) 2013 Roger Pau Monné * 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 #include #include #include #include #include #include #include #include #include /* Native initial function */ extern u_int64_t hammer_time(u_int64_t, u_int64_t); /* Xen initial function */ uint64_t hammer_time_xen(start_info_t *, uint64_t); /* * First function called by the Xen PVH boot sequence. * * Set some Xen global variables and prepare the environment so it is * as similar as possible to what native FreeBSD init function expects. */ uint64_t hammer_time_xen(start_info_t *si, uint64_t xenstack) { uint64_t physfree; uint64_t *PT4 = (u_int64_t *)xenstack; uint64_t *PT3 = (u_int64_t *)(xenstack + PAGE_SIZE); uint64_t *PT2 = (u_int64_t *)(xenstack + 2 * PAGE_SIZE); int i; xen_domain_type = XEN_PV_DOMAIN; vm_guest = VM_GUEST_XEN; if ((si == NULL) || (xenstack == 0)) { xc_printf("ERROR: invalid start_info or xen stack, halting\n"); HYPERVISOR_shutdown(SHUTDOWN_crash); } xc_printf("FreeBSD PVH running on %s\n", si->magic); /* We use 3 pages of xen stack for the boot pagetables */ physfree = xenstack + 3 * PAGE_SIZE - KERNBASE; /* Setup Xen global variables */ HYPERVISOR_start_info = si; HYPERVISOR_shared_info = (shared_info_t *)(si->shared_info + KERNBASE); /* * Setup some misc global variables for Xen devices * * XXX: Devices that need these specific variables should * be rewritten to fetch this info by themselves from the * start_info page. */ xen_store = (struct xenstore_domain_interface *) (ptoa(si->store_mfn) + KERNBASE); console_page = (char *)(ptoa(si->console.domU.mfn) + KERNBASE); /* * Use the stack Xen gives us to build the page tables * as native FreeBSD expects to find them (created * by the boot trampoline). */ for (i = 0; i < (PAGE_SIZE / sizeof(uint64_t)); i++) { /* Each slot of the level 4 pages points to the same level 3 page */ PT4[i] = ((uint64_t)&PT3[0]) - KERNBASE; PT4[i] |= PG_V | PG_RW | PG_U; /* Each slot of the level 3 pages points to the same level 2 page */ PT3[i] = ((uint64_t)&PT2[0]) - KERNBASE; PT3[i] |= PG_V | PG_RW | PG_U; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ PT2[i] = i * (2 * 1024 * 1024); PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; } load_cr3(((uint64_t)&PT4[0]) - KERNBASE); /* Now we can jump into the native init function */ return (hammer_time(0, physfree)); }