summaryrefslogtreecommitdiffstats
path: root/sys/boot/alpha
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-10-14 09:53:25 +0000
committerpeter <peter@FreeBSD.org>1998-10-14 09:53:25 +0000
commita6df719969080a17590736b9c2f77271ce3858af (patch)
tree1199302047db29bdcf50591f02e624914c016458 /sys/boot/alpha
parent7bbde981a39055313c1d18fcc4318f4389f752ad (diff)
downloadFreeBSD-src-a6df719969080a17590736b9c2f77271ce3858af.zip
FreeBSD-src-a6df719969080a17590736b9c2f77271ce3858af.tar.gz
Initial attempt to update the Alpha loader and kernel to use the machine
independent elf loader and have access to kld modules. Jordan and I were not sure how to create boot floppies, and the things we tried just made SRM laugh in our faces - but it was upset at boot1 which was not touched by these changes. Essentially this has been untested. :-( What this does is to steal the last three slots from the nine spare longs in the bootinfo_v1 struct to pass the module base pointer through. The startup code now to set up and fills in the module and environment structures, hopefully close enough to the i386 layout to be able to use the same kernel code. We now pass though the updated end of the kernel space used, rather than _end. (like the i386). If this does not work, it needs to be beaten into shape pronto. Otherwise it should be backed out before 3.0. Pre-approved in principle by: dfr
Diffstat (limited to 'sys/boot/alpha')
-rw-r--r--sys/boot/alpha/boot2/Makefile8
-rw-r--r--sys/boot/alpha/libalpha/Makefile12
-rw-r--r--sys/boot/alpha/libalpha/bootinfo.c199
-rw-r--r--sys/boot/alpha/libalpha/elf_freebsd.c192
4 files changed, 224 insertions, 187 deletions
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.
*/
OpenPOWER on IntegriCloud