diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/alpha/alpha/machdep.c | 10 | ||||
-rw-r--r-- | sys/alpha/include/bootinfo.h | 10 | ||||
-rw-r--r-- | sys/boot/alpha/boot2/Makefile | 8 | ||||
-rw-r--r-- | sys/boot/alpha/libalpha/Makefile | 12 | ||||
-rw-r--r-- | sys/boot/alpha/libalpha/bootinfo.c | 199 | ||||
-rw-r--r-- | sys/boot/alpha/libalpha/elf_freebsd.c | 192 | ||||
-rw-r--r-- | sys/powerpc/include/bootinfo.h | 10 |
7 files changed, 249 insertions, 192 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 5816af8..6b011f5 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: machdep.c,v 1.14 1998/09/17 09:35:31 dfr Exp $ + * $Id: machdep.c,v 1.15 1998/10/06 08:40:18 dfr Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -109,6 +109,7 @@ #include <sys/exec.h> #include <sys/sysctl.h> #include <sys/uio.h> +#include <sys/linker.h> #include <net/netisr.h> #include <vm/vm.h> #include <vm/vm_kern.h> @@ -542,6 +543,8 @@ alpha_init(pfn, ptb, bim, bip, biv) bootinfo.ssym = v1p->ssym; bootinfo.esym = v1p->esym; + bootinfo.kernend = v1p->kernend; + bootinfo.modptr = v1p->modptr; /* hwrpb may not be provided by boot block in v1 */ if (v1p->hwrpb != NULL) { bootinfo.hwrpb_phys = @@ -695,6 +698,11 @@ alpha_init(pfn, ptb, bim, bip, biv) #else kernend = (vm_offset_t)round_page(_end); #endif + /* But if the bootstrap tells us otherwise, believe it! */ + if (bootinfo.kernend) + kernend = (vm_offset_t)round_page(kernend); + preload_metadata = bootinfo.modptr; + kern_envp = bootinfo.envp; kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart)); kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend)); diff --git a/sys/alpha/include/bootinfo.h b/sys/alpha/include/bootinfo.h index 970987d..f9b2560 100644 --- a/sys/alpha/include/bootinfo.h +++ b/sys/alpha/include/bootinfo.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: bootinfo.h,v 1.2 1998/07/05 12:13:18 dfr Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. @@ -53,7 +53,10 @@ struct bootinfo_v1 { int (*cngetc) __P((void)); /* 160: console getc pointer */ void (*cnputc) __P((int)); /* 168: console putc pointer */ void (*cnpollc) __P((int)); /* 176: console pollc pointer */ - u_long pad[9]; /* 184: rsvd for future use */ + u_long pad[6]; /* 184: rsvd for future use */ + char *envp; /* 232: start of environment */ + u_long kernend; /* 240: end of kernel */ + u_long modbase; /* 248: FreeBSD module base */ /* 256: total size */ }; @@ -70,6 +73,9 @@ struct bootinfo_v1 { struct bootinfo_kernel { u_long ssym; /* start of syms */ u_long esym; /* end of syms */ + u_long modptr; /* FreeBSD module pointer */ + u_long kernend; /* "end of kernel" from boot code */ + char *envp; /* "end of kernel" from boot code */ u_long hwrpb_phys; /* hwrpb physical address */ u_long hwrpb_size; /* size of hwrpb data */ char boot_flags[64]; /* boot flags */ diff --git a/sys/boot/alpha/boot2/Makefile b/sys/boot/alpha/boot2/Makefile index f76c8db..dfc8e58 100644 --- a/sys/boot/alpha/boot2/Makefile +++ b/sys/boot/alpha/boot2/Makefile @@ -15,7 +15,7 @@ SRCS+= main.c conf.c .include <${.CURDIR}/../../common/Makefile.inc> CFLAGS+= -mno-fp-regs CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR} -CFLAGS+= -I${.OBJDIR} +CFLAGS+= -I${.CURDIR}/../../.. -I. CLEANFILES+= vers.c vers.o gensetdefs.o gensetdefs setdef0.o setdef1.o \ setdefs.h start.o @@ -50,6 +50,11 @@ setdef0.o: setdefs.h setdef1.o: setdefs.h +machine: + ln -sf ${.CURDIR}/../../../alpha/include machine + +CLEANFILES+= machine + .include <bsd.prog.mk> setdefs.h: gensetdefs ${OBJS} @@ -62,3 +67,4 @@ gensetdefs: gensetdefs.o gensetdefs.o: gensetdefs.c ${CC} -c $< +beforedepend ${OBJS}: machine diff --git a/sys/boot/alpha/libalpha/Makefile b/sys/boot/alpha/libalpha/Makefile index 1478b74..a82febf 100644 --- a/sys/boot/alpha/libalpha/Makefile +++ b/sys/boot/alpha/libalpha/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 1998/08/31 21:10:40 msmith Exp $ +# $Id: Makefile,v 1.4 1998/09/26 10:51:37 dfr Exp $ LIB= alpha NOPIC= true @@ -11,7 +11,8 @@ CFLAGS= -I${LIBSTANDDIR} CFLAGS+= -DDEBUG # Pick up the bootstrap header for some interface items -CFLAGS+= -I${.CURDIR}/../../common -mno-fp-regs +CFLAGS+= -I${.CURDIR}/../../common -mno-fp-regs \ + -I${.CURDIR}/../../.. -I. CFLAGS+= -DDISK_DEBUG #CPPFLAGS+= -DNO_DISKLABEL @@ -19,8 +20,13 @@ CFLAGS+= -DDISK_DEBUG SRCS= OSFpal.c elf_freebsd.c prom.c prom_disp.S prom_swpal.S start.S \ pal.S reboot.c delay.c time.c alpha_module.c devicename.c \ - srmdisk.c srmnet.c getsecs.c alpha_copy.c + srmdisk.c srmnet.c getsecs.c alpha_copy.c bootinfo.c all: libalpha.a +machine: + ln -sf ${.CURDIR}/../../../alpha/include machine + .include <bsd.lib.mk> + +beforedepend ${OBJS}: machine diff --git a/sys/boot/alpha/libalpha/bootinfo.c b/sys/boot/alpha/libalpha/bootinfo.c new file mode 100644 index 0000000..d8a01af --- /dev/null +++ b/sys/boot/alpha/libalpha/bootinfo.c @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * + * $Id: bootinfo.c,v 1.12 1998/10/09 23:24:55 peter Exp $ + */ + +#include <stand.h> +#include <string.h> +#include <sys/param.h> +#include <sys/reboot.h> +#include <sys/linker.h> +#include <machine/elf.h> +#include <machine/prom.h> +#include <machine/rpb.h> +#include <machine/bootinfo.h> +#include "bootstrap.h" + +/* + * Copy the environment into the load area starting at (addr). + * Each variable is formatted as <name>=<value>, 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) { + alpha_copyin(ep->ev_name, addr, strlen(ep->ev_name)); + addr += strlen(ep->ev_name); + alpha_copyin("=", addr, 1); + addr++; + if (ep->ev_value != NULL) { + alpha_copyin(ep->ev_value, addr, strlen(ep->ev_value)); + addr += strlen(ep->ev_value); + } + alpha_copyin("", addr, 1); + addr++; + } + alpha_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 preceeded 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_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); \ + alpha_copyin(&x, a, sizeof(x)); \ + a += sizeof(x); \ +} + +#define MOD_STR(t, a, s) { \ + COPY32(t, a); \ + COPY32(strlen(s) + 1, a); \ + alpha_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_VAR(t, a, s) { \ + COPY32(t, a); \ + COPY32(sizeof(s), a); \ + alpha_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); \ + alpha_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 loaded_module *mp; + struct module_metadata *md; + + /* start with the first module on the list, should be the kernel */ + for (mp = mod_findmodule(NULL, NULL); mp != NULL; mp = mp->m_next) { + + MOD_NAME(addr, mp->m_name); /* this field must come first */ + MOD_TYPE(addr, mp->m_type); + MOD_ADDR(addr, mp->m_addr); + MOD_SIZE(addr, mp->m_size); + for (md = mp->m_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 an alpha kernel. + * + * - The kernel environment is copied into kernel space. + * - Module metadata are formatted and placed in kernel space. + */ +int +bi_load(struct bootinfo_v1 *bi, vm_offset_t *ffp_save) +{ + struct loaded_module *xp; + vm_offset_t addr, bootinfo_addr; + u_int pad; + vm_offset_t ssym, esym; + struct loaded_module *mp; + struct module_metadata *md; + + ssym = esym = 0; + if ((md = mod_findmetadata(mp, MODINFOMD_SSYM)) != NULL) + ssym = *((vm_offset_t *)&(md->md_data)); + if ((md = mod_findmetadata(mp, MODINFOMD_ESYM)) != NULL) + esym = *((vm_offset_t *)&(md->md_data)); + if (ssym == 0 || esym == 0) + ssym = esym = 0; /* sanity */ + + /* find the last module in the chain */ + for (xp = mod_findmodule(NULL, NULL); xp->m_next != NULL; xp = xp->m_next) + ; + addr = xp->m_addr + xp->m_size; + /* pad to a page boundary */ + pad = (u_int)addr & PAGE_MASK; + if (pad != 0) { + pad = PAGE_SIZE - pad; + addr += pad; + } + + /* copy our environment */ + bi->envp = (char *)addr; + addr = bi_copyenv(addr); + + /* pad to a page boundary */ + pad = (u_int)addr & PAGE_MASK; + if (pad != 0) { + pad = PAGE_SIZE - pad; + addr += pad; + } + /* copy module list and metadata */ + bi->modptr = addr; + addr = bi_copymodules(addr); + + /* all done copying stuff in, save end of loaded object space */ + bi->kernend = addr; + + *ffp_save = ALPHA_K0SEG_TO_PHYS((addr + PAGE_MASK) & ~PAGE_MASK) + >> PAGE_SHIFT; + *ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ + + return(0); +} diff --git a/sys/boot/alpha/libalpha/elf_freebsd.c b/sys/boot/alpha/libalpha/elf_freebsd.c index 7199763..edb0c21 100644 --- a/sys/boot/alpha/libalpha/elf_freebsd.c +++ b/sys/boot/alpha/libalpha/elf_freebsd.c @@ -1,4 +1,4 @@ -/* $Id: elf_freebsd.c,v 1.3 1998/09/14 18:27:00 msmith Exp $ */ +/* $Id: elf_freebsd.c,v 1.4 1998/10/11 03:53:35 dima Exp $ */ /* $NetBSD: loadfile.c,v 1.10 1998/06/25 06:45:46 ross Exp $ */ /*- @@ -90,193 +90,12 @@ #define _KERNEL -static int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); static int elf_exec(struct loaded_module *amp); -static int elf_load(int fd, Elf_Ehdr *elf, vm_offset_t dest); +int bi_load(struct bootinfo_v1 *, vm_offset_t *); struct module_format alpha_elf = { elf_loadmodule, elf_exec }; vm_offset_t ffp_save, ptbr_save; -vm_offset_t ssym, esym; - -static int -elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) -{ - struct loaded_module *mp; - Elf_Ehdr hdr; - ssize_t nr; - int fd, rval; - - /* Open the file. */ - rval = 1; - if ((fd = open(filename, 0)) < 0) { - (void)printf("open %s: %s\n", filename, strerror(errno)); - goto err; - } - - /* Read the exec header. */ - if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) { - (void)printf("read header: %s\n", strerror(errno)); - goto err; - } - - if (!(hdr.e_ident[0] == ELFMAG0 - && hdr.e_ident[1] == ELFMAG1 - && hdr.e_ident[2] == ELFMAG2 - && hdr.e_ident[3] == ELFMAG3)) { - (void)printf("%s: unknown executable format\n", filename); - goto err; - } - - /* - * Ok, we think this is for us. - */ - mp = mod_allocmodule(); - mp->m_name = strdup(filename); /* XXX should we prune the name? */ - mp->m_type = strdup("elf kernel"); /* XXX only if that's what we really are */ - - dest = (vm_offset_t) hdr.e_entry; - mp->m_addr = dest; - if (mod_findmodule(NULL, NULL) != NULL) { - printf("elf_loadmodule: kernel already loaded\n"); - rval = EPERM; - goto err; - } - rval = elf_load(fd, &hdr, (vm_offset_t) dest); - - /* save ELF header as metadata */ - mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(Elf_Ehdr), &hdr); - - *result = (struct loaded_module *)mp; - - err: - if (fd >= 0) - (void)close(fd); - return (rval); -} - -static int -elf_load(int fd, Elf_Ehdr *elf, vm_offset_t dest) -{ - Elf_Shdr *shp; - Elf_Off off; - int i; - int first = 1; - int havesyms; - - for (i = 0; i < elf->e_phnum; i++) { - Elf_Phdr phdr; - if (lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET) - == -1) { - (void)printf("lseek phdr: %s\n", strerror(errno)); - return (1); - } - if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { - (void)printf("read phdr: %s\n", strerror(errno)); - return (1); - } - if (phdr.p_type != PT_LOAD || - (phdr.p_flags & (PF_W|PF_X)) == 0) - continue; - - /* Read in segment. */ - (void)printf("%s%lu", first ? "" : "+", phdr.p_filesz); - if (lseek(fd, phdr.p_offset, SEEK_SET) == -1) { - (void)printf("lseek text: %s\n", strerror(errno)); - return (1); - } - if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) != - phdr.p_filesz) { - (void)printf("read text: %s\n", strerror(errno)); - return (1); - } - if (first || ffp_save < phdr.p_vaddr + phdr.p_memsz) - ffp_save = phdr.p_vaddr + phdr.p_memsz; - - /* Zero out bss. */ - if (phdr.p_filesz < phdr.p_memsz) { - (void)printf("+%lu", phdr.p_memsz - phdr.p_filesz); - bzero((void *)(phdr.p_vaddr + phdr.p_filesz), - phdr.p_memsz - phdr.p_filesz); - } - first = 0; - } - /* - * Copy the ELF and section headers. - */ - ffp_save = roundup(ffp_save, sizeof(long)); - ssym = ffp_save; - bcopy(elf, (void *)ffp_save, sizeof(Elf_Ehdr)); - ffp_save += sizeof(Elf_Ehdr); - if (lseek(fd, elf->e_shoff, SEEK_SET) == -1) { - printf("lseek section headers: %s\n", strerror(errno)); - return (1); - } - if (read(fd, (void *)ffp_save, elf->e_shnum * sizeof(Elf_Shdr)) != - elf->e_shnum * sizeof(Elf_Shdr)) { - printf("read section headers: %s\n", strerror(errno)); - return (1); - } - shp = (Elf_Shdr *)ffp_save; - ffp_save += roundup((elf->e_shnum * sizeof(Elf_Shdr)), sizeof(long)); - - /* - * Now load the symbol sections themselves. Make sure the - * sections are aligned. Don't bother with string tables if - * there are no symbol sections. - */ - off = roundup((sizeof(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf_Shdr))), - sizeof(long)); - for (havesyms = i = 0; i < elf->e_shnum; i++) - if (shp[i].sh_type == SHT_SYMTAB) - havesyms = 1; - for (first = 1, i = 0; i < elf->e_shnum; i++) { - if (shp[i].sh_type == SHT_SYMTAB || - shp[i].sh_type == SHT_STRTAB) { - printf("%s%ld", first ? " [" : "+", shp[i].sh_size); - if (havesyms) { - if (lseek(fd, shp[i].sh_offset, SEEK_SET) - == -1) { - printf("\nlseek symbols: %s\n", - strerror(errno)); - return (1); - } - if (read(fd, (void *)ffp_save, shp[i].sh_size) - != shp[i].sh_size) { - printf("\nread symbols: %s\n", - strerror(errno)); - return (1); - } - } - ffp_save += roundup(shp[i].sh_size, sizeof(long)); - shp[i].sh_offset = off; - off += roundup(shp[i].sh_size, sizeof(long)); - first = 0; - } - } - esym = ffp_save; - - if (first == 0) - printf("]"); - - ffp_save = ALPHA_K0SEG_TO_PHYS((ffp_save + PAGE_MASK) & ~PAGE_MASK) - >> PAGE_SHIFT; - ffp_save += 2; /* XXX OSF/1 does this, no idea why. */ - - (void)printf("\n"); - - /* - * Frob the copied ELF header to give information relative - * to ssym. - */ - elf = (Elf_Ehdr *)ssym; - elf->e_phoff = 0; - elf->e_shoff = sizeof(Elf_Ehdr); - elf->e_phentsize = 0; - elf->e_phnum = 0; - - return (0); -} static int elf_exec(struct loaded_module *mp) @@ -284,11 +103,18 @@ elf_exec(struct loaded_module *mp) static struct bootinfo_v1 bootinfo_v1; struct module_metadata *md; Elf_Ehdr *hdr; + int err; + vm_offset_t ssym, esym; if ((md = mod_findmetadata(mp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); /* XXX actually EFUCKUP */ hdr = (Elf_Ehdr *)&(md->md_data); + /* XXX ffp_save does not appear to be used in the kernel.. */ + err = bi_load(&bootinfo_v1, &ffp_save); + if (err) + return(err); + /* * Fill in the bootinfo for the kernel. */ diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h index 970987d..f9b2560 100644 --- a/sys/powerpc/include/bootinfo.h +++ b/sys/powerpc/include/bootinfo.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: bootinfo.h,v 1.2 1998/07/05 12:13:18 dfr Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. @@ -53,7 +53,10 @@ struct bootinfo_v1 { int (*cngetc) __P((void)); /* 160: console getc pointer */ void (*cnputc) __P((int)); /* 168: console putc pointer */ void (*cnpollc) __P((int)); /* 176: console pollc pointer */ - u_long pad[9]; /* 184: rsvd for future use */ + u_long pad[6]; /* 184: rsvd for future use */ + char *envp; /* 232: start of environment */ + u_long kernend; /* 240: end of kernel */ + u_long modbase; /* 248: FreeBSD module base */ /* 256: total size */ }; @@ -70,6 +73,9 @@ struct bootinfo_v1 { struct bootinfo_kernel { u_long ssym; /* start of syms */ u_long esym; /* end of syms */ + u_long modptr; /* FreeBSD module pointer */ + u_long kernend; /* "end of kernel" from boot code */ + char *envp; /* "end of kernel" from boot code */ u_long hwrpb_phys; /* hwrpb physical address */ u_long hwrpb_size; /* size of hwrpb data */ char boot_flags[64]; /* boot flags */ |