diff --git a/stand/powerpc/ofw/metadata.c b/stand/common/metadata.c similarity index 75% rename from stand/powerpc/ofw/metadata.c rename to stand/common/metadata.c index 25d51f8251ce..df45d40a3d17 100644 --- a/stand/powerpc/ofw/metadata.c +++ b/stand/common/metadata.c @@ -34,12 +34,63 @@ __FBSDID("$FreeBSD$"); #include #include #include +#if defined(LOADER_FDT_SUPPORT) #include +#endif #include #include "bootstrap.h" +#if defined(__sparc64__) +#include + +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) +{ + 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); +} +#endif + int md_getboothowto(char *kargs) { @@ -47,7 +98,7 @@ md_getboothowto(char *kargs) int howto; int active; int i; - + /* Parse kargs */ howto = 0; if (kargs != NULL) { @@ -98,14 +149,20 @@ md_getboothowto(char *kargs) 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 defined(__sparc64__) + if (md_bootserial() != -1) + howto |= RB_SERIAL; +#else if (!strcmp(getenv("console"), "comconsole")) howto |= RB_SERIAL; if (!strcmp(getenv("console"), "nullconsole")) howto |= RB_MUTE; +#endif return(howto); } @@ -114,11 +171,11 @@ md_getboothowto(char *kargs) * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ -vm_offset_t +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)); @@ -199,7 +256,7 @@ static int align; COPY32(0, a, c); \ } -vm_offset_t +static vm_offset_t md_copymodules(vm_offset_t addr, int kern64) { struct preloaded_file *fp; @@ -235,7 +292,7 @@ md_copymodules(vm_offset_t addr, int kern64) } /* - * Load the information expected by a powerpc kernel. + * Load the information expected by a kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed @@ -251,7 +308,9 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; +#if defined(LOADER_FDT_SUPPORT) vm_offset_t fdtp; +#endif vm_offset_t size; uint64_t scratch64; char *rootdevname; @@ -260,40 +319,45 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) 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. + /* + * 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"); + rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); - /* find the last module in the chain */ + /* 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 */ + /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); - /* copy our environment */ + /* Copy our environment */ envp = addr; addr = md_copyenv(addr); - /* pad to a page boundary */ + /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); +#if defined(LOADER_FDT_SUPPORT) /* Copy out FDT */ - *dtb = fdtp = 0; - if (getenv("usefdt") != NULL) { - size = fdt_copy(addr); - *dtb = fdtp = addr; - addr = roundup(addr + size, PAGE_SIZE); + fdtp = 0; +#if defined(__powerpc__) + if (getenv("usefdt") != NULL) +#endif + { + size = fdt_copy(addr); + fdtp = addr; + addr = roundup(addr + size, PAGE_SIZE); } +#endif kernend = 0; kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel"); @@ -305,19 +369,35 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) if (kern64) { scratch64 = envp; file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); - if (fdtp != 0) { +#if defined(LOADER_FDT_SUPPORT) + if (fdtp != 0) { scratch64 = fdtp; file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64); - } + } +#endif scratch64 = kernend; - file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); + file_addmetadata(kfp, MODINFOMD_KERNEND, + sizeof scratch64, &scratch64); } else { file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); - if (fdtp != 0) +#if defined(LOADER_FDT_SUPPORT) + if (fdtp != 0) file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp); +#endif file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); } +#if defined(__sparc64__) + 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); +#endif + *modulep = addr; size = md_copymodules(0, kern64); kernend = roundup(addr + size, PAGE_SIZE); @@ -329,8 +409,12 @@ md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) } else { bcopy(&kernend, md->md_data, sizeof kernend); } - + (void)md_copymodules(addr, kern64); +#if defined(LOADER_FDT_SUPPORT) + if (dtb != NULL) + *dtb = fdtp; +#endif return(0); } @@ -341,9 +425,10 @@ md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb) return (md_load_dual(args, modulep, dtb, 0)); } +#if defined(__mips__) || defined(__powerpc__) int md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb) { return (md_load_dual(args, modulep, dtb, 1)); } - +#endif diff --git a/stand/loader.mk b/stand/loader.mk index fdb0b6f51830..5a69da5499d1 100644 --- a/stand/loader.mk +++ b/stand/loader.mk @@ -20,12 +20,16 @@ SRCS+= load_elf32.c reloc_elf32.c .elif ${MACHINE_CPUARCH} == "powerpc" SRCS+= load_elf32.c reloc_elf32.c SRCS+= load_elf64.c reloc_elf64.c +SRCS+= metadata.c .elif ${MACHINE_CPUARCH} == "sparc64" SRCS+= load_elf64.c reloc_elf64.c +SRCS+= metadata.c .elif ${MACHINE_ARCH:Mmips64*} != "" SRCS+= load_elf64.c reloc_elf64.c +SRCS+= metadata.c .elif ${MACHINE} == "mips" SRCS+= load_elf32.c reloc_elf32.c +SRCS+= metadata.c .endif .if ${LOADER_DISK_SUPPORT:Uyes} == "yes" diff --git a/stand/mips/beri/loader/Makefile b/stand/mips/beri/loader/Makefile index f8c1bd9fba8e..8e554b4b95b9 100644 --- a/stand/mips/beri/loader/Makefile +++ b/stand/mips/beri/loader/Makefile @@ -47,7 +47,6 @@ SRCS= start.S \ main.c \ devicename.c \ exec.c \ - metadata.c \ vers.c \ arch.c diff --git a/stand/mips/beri/loader/exec.c b/stand/mips/beri/loader/exec.c index 3c1b7a6a3cee..5399e8acc359 100644 --- a/stand/mips/beri/loader/exec.c +++ b/stand/mips/beri/loader/exec.c @@ -85,7 +85,7 @@ beri_elf64_exec(struct preloaded_file *fp) } ehdr = (Elf_Ehdr *)md->md_data; - error = md_load64(fp->f_args, &mdp); + error = md_load64(fp->f_args, &mdp, NULL); if (error) { printf("%s: md_load64 failed\n", fp->f_name); return (error); diff --git a/stand/mips/beri/loader/loader.h b/stand/mips/beri/loader/loader.h index 4005caa0eebc..d73a7f8e284e 100644 --- a/stand/mips/beri/loader/loader.h +++ b/stand/mips/beri/loader/loader.h @@ -56,7 +56,7 @@ extern char **boot2_envv; extern struct bootinfo boot2_bootinfo; /* metadata.c */ -int md_load64(char *args, vm_offset_t *modulep); +int md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtbp); /* vers.c */ extern char bootprog_info[]; diff --git a/stand/mips/beri/loader/metadata.c b/stand/mips/beri/loader/metadata.c deleted file mode 100644 index 0698cd19c651..000000000000 --- a/stand/mips/beri/loader/metadata.c +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * 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 "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)); -} - diff --git a/stand/powerpc/kboot/Makefile b/stand/powerpc/kboot/Makefile index d5b202550206..8a6a0dee6544 100644 --- a/stand/powerpc/kboot/Makefile +++ b/stand/powerpc/kboot/Makefile @@ -17,7 +17,7 @@ NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH} INSTALLFLAGS= -b # Architecture-specific loader code -SRCS= conf.c metadata.c vers.c main.c ppc64_elf_freebsd.c +SRCS= conf.c vers.c main.c ppc64_elf_freebsd.c SRCS+= host_syscall.S hostcons.c hostdisk.c kerneltramp.S kbootfdt.c SRCS+= ucmpdi2.c diff --git a/stand/powerpc/kboot/main.c b/stand/powerpc/kboot/main.c index d4f59ab1bcac..587968f88dab 100644 --- a/stand/powerpc/kboot/main.c +++ b/stand/powerpc/kboot/main.c @@ -291,6 +291,7 @@ main(int argc, const char **argv) setenv("currdev", bootdev, 1); setenv("loaddev", bootdev, 1); setenv("LINES", "24", 1); + setenv("usefdt", "1", 1); interact(); /* doesn't return */ diff --git a/stand/powerpc/kboot/metadata.c b/stand/powerpc/kboot/metadata.c deleted file mode 100644 index 2892ce506590..000000000000 --- a/stand/powerpc/kboot/metadata.c +++ /dev/null @@ -1,348 +0,0 @@ -/*- - * 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 - -#include - -#include "bootstrap.h" - -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 = htobe32(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, vm_offset_t *dtb, 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 fdtp; - vm_offset_t size; - uint64_t scratch64; - uint32_t scratch32; - char *rootdevname; - int howto; - - align = kern64 ? 8 : 4; - howto = htobe32(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); - - /* Copy out FDT */ - size = fdt_copy(addr); - *dtb = fdtp = addr; - addr = roundup(addr + size, 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 = htobe64(envp); - file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); - scratch64 = htobe64(fdtp); - file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64); - scratch64 = htobe64(kernend); - file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); - } else { - scratch32 = htobe32(envp); - file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch32, &scratch32); - scratch32 = htobe32(fdtp); - file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch32, &scratch32); - scratch32 = htobe32(kernend); - file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch32, &scratch32); - } - - *modulep = addr; - size = md_copymodules(0, kern64); - kernend = roundup(addr + size, PAGE_SIZE); - - md = file_findmetadata(kfp, MODINFOMD_KERNEND); - if (kern64) { - scratch64 = htobe64(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, vm_offset_t *dtb) -{ - return (md_load_dual(args, modulep, dtb, 0)); -} - -int -md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb) -{ - return (md_load_dual(args, modulep, dtb, 1)); -} - diff --git a/stand/powerpc/ofw/Makefile b/stand/powerpc/ofw/Makefile index ce24844114e1..b1f413526000 100644 --- a/stand/powerpc/ofw/Makefile +++ b/stand/powerpc/ofw/Makefile @@ -17,7 +17,7 @@ NEWVERSWHAT= "Open Firmware loader" ${MACHINE_ARCH} INSTALLFLAGS= -b # Architecture-specific loader code -SRCS= conf.c metadata.c vers.c start.c +SRCS= conf.c vers.c start.c SRCS+= ucmpdi2.c .include "${BOOTSRC}/fdt.mk" diff --git a/stand/sparc64/loader/Makefile b/stand/sparc64/loader/Makefile index 7f57409203a7..79edaed2fbd4 100644 --- a/stand/sparc64/loader/Makefile +++ b/stand/sparc64/loader/Makefile @@ -21,7 +21,7 @@ INSTALLFLAGS= -b # Architecture-specific loader code .PATH: ${BOOTSRC}/sparc64/loader -SRCS= locore.S main.c metadata.c vers.c +SRCS= locore.S main.c vers.c .if ${LOADER_DEBUG} == "yes" CFLAGS+= -DLOADER_DEBUG diff --git a/stand/sparc64/loader/metadata.c b/stand/sparc64/loader/metadata.c deleted file mode 100644 index 51b3d7e13997..000000000000 --- a/stand/sparc64/loader/metadata.c +++ /dev/null @@ -1,345 +0,0 @@ -/*- - * 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); - -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. - */ -vm_offset_t -md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtbp) -{ - 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); - *dtbp = 0; - - /* - * 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); -} diff --git a/stand/uboot.mk b/stand/uboot.mk index d120481a4b96..0ff7fb32b07c 100644 --- a/stand/uboot.mk +++ b/stand/uboot.mk @@ -1,6 +1,6 @@ # $FreeBSD$ -SRCS+= main.c metadata.c +SRCS+= main.c .PATH: ${UBOOTSRC}/common @@ -10,6 +10,9 @@ CFLAGS+= -I${UBOOTSRC}/common LIBUBOOT= ${BOOTOBJ}/uboot/lib/libuboot.a CFLAGS+= -I${UBOOTSRC}/lib CFLAGS+= -I${BOOTOBJ}/uboot/lib +.if ${MACHINE_CPUARCH} == "arm" +SRCS+= metadata.c +.endif .include "${BOOTSRC}/fdt.mk" diff --git a/stand/uboot/common/metadata.c b/stand/uboot/common/metadata.c deleted file mode 100644 index 38db4bca44b5..000000000000 --- a/stand/uboot/common/metadata.c +++ /dev/null @@ -1,366 +0,0 @@ -/*- - * 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 -#endif - -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 < nitems(mdt); 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); -} diff --git a/stand/uboot/lib/elf_freebsd.c b/stand/uboot/lib/elf_freebsd.c index a65fa26aa722..8ce3702f81f0 100644 --- a/stand/uboot/lib/elf_freebsd.c +++ b/stand/uboot/lib/elf_freebsd.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "libuboot.h" -extern vm_offset_t md_load(char *, vm_offset_t *); +extern vm_offset_t md_load(char *, vm_offset_t *, vm_offset_t *); int __elfN(uboot_load)(char *filename, u_int64_t dest, @@ -81,7 +81,7 @@ __elfN(uboot_exec)(struct preloaded_file *fp) e = (Elf_Ehdr *)&fmp->md_data; - if ((error = md_load(fp->f_args, &mdp)) != 0) + if ((error = md_load(fp->f_args, &mdp, NULL)) != 0) return (error); entry = (void *)e->e_entry;