aboutsummaryrefslogtreecommitdiff
path: root/sys/boot
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2003-05-01 03:56:30 +0000
committerPeter Wemm <peter@FreeBSD.org>2003-05-01 03:56:30 +0000
commit48a0b96a508aece7c0260b0ba4e98b47c206af44 (patch)
tree3ceb596207b6bc027473320fe17af905c4acd162 /sys/boot
parentab7b0ae578c4ced40414f23fa55badeea27a350d (diff)
Notes
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/alpha/libalpha/elf_freebsd.c6
-rw-r--r--sys/boot/arc/lib/elf_freebsd.c6
-rw-r--r--sys/boot/common/Makefile.inc15
-rw-r--r--sys/boot/common/bootstrap.h6
-rw-r--r--sys/boot/common/load_elf.c117
-rw-r--r--sys/boot/common/load_elf32.c3
-rw-r--r--sys/boot/common/load_elf64.c3
-rw-r--r--sys/boot/efi/libefi/elf_freebsd.c6
-rw-r--r--sys/boot/i386/libi386/Makefile6
-rw-r--r--sys/boot/i386/libi386/amd64_tramp.S113
-rw-r--r--sys/boot/i386/libi386/biossmap.c107
-rw-r--r--sys/boot/i386/libi386/bootinfo.c207
-rw-r--r--sys/boot/i386/libi386/bootinfo32.c295
-rw-r--r--sys/boot/i386/libi386/bootinfo64.c306
-rw-r--r--sys/boot/i386/libi386/elf32_freebsd.c27
-rw-r--r--sys/boot/i386/libi386/elf64_freebsd.c71
-rw-r--r--sys/boot/i386/libi386/libi386.h8
-rw-r--r--sys/boot/i386/loader/conf.c2
-rw-r--r--sys/boot/i386/loader/main.c2
-rw-r--r--sys/boot/ia64/common/exec.c6
-rw-r--r--sys/boot/ia64/libski/elf_freebsd.c6
-rw-r--r--sys/boot/ia64/ski/elf_freebsd.c6
-rw-r--r--sys/boot/ofw/libofw/elf_freebsd.c10
23 files changed, 580 insertions, 754 deletions
diff --git a/sys/boot/alpha/libalpha/elf_freebsd.c b/sys/boot/alpha/libalpha/elf_freebsd.c
index 74faee2a77ec..a223652c863a 100644
--- a/sys/boot/alpha/libalpha/elf_freebsd.c
+++ b/sys/boot/alpha/libalpha/elf_freebsd.c
@@ -90,16 +90,16 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *afp);
+static int elf64_exec(struct preloaded_file *afp);
int bi_load(struct bootinfo_v1 *, vm_offset_t *,
struct preloaded_file *);
-struct file_format alpha_elf = { elf_loadfile, elf_exec };
+struct file_format alpha_elf = { elf64_loadfile, elf64_exec };
vm_offset_t ffp_save, ptbr_save;
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
static struct bootinfo_v1 bootinfo_v1;
struct file_metadata *md;
diff --git a/sys/boot/arc/lib/elf_freebsd.c b/sys/boot/arc/lib/elf_freebsd.c
index 994a78714bbf..41cdedb24811 100644
--- a/sys/boot/arc/lib/elf_freebsd.c
+++ b/sys/boot/arc/lib/elf_freebsd.c
@@ -90,16 +90,16 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
int bi_load(struct bootinfo_v1 *, vm_offset_t *,
struct preloaded_file *);
-struct file_format alpha_elf = { elf_loadfile, elf_exec };
+struct file_format alpha_elf = { elf64_loadfile, elf64_exec };
vm_offset_t ffp_save, ptbr_save;
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
#if 0
static struct bootinfo_v1 bootinfo_v1;
diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc
index 3f6c91078128..c72d09ea7e4b 100644
--- a/sys/boot/common/Makefile.inc
+++ b/sys/boot/common/Makefile.inc
@@ -1,9 +1,19 @@
# $FreeBSD$
SRCS+= bcache.c boot.c commands.c console.c devopen.c interp.c
-SRCS+= interp_backslash.c interp_parse.c load_elf.c ls.c misc.c
+SRCS+= interp_backslash.c interp_parse.c ls.c misc.c
SRCS+= module.c panic.c
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
+SRCS+= load_elf32.c load_elf64.c
+.endif
+.if ${MACHINE_ARCH} == "powerpc"
+SRCS+= load_elf32.c
+.endif
+.if ${MACHINE_ARCH} == "sparc64" || ${MACHINE_ARCH} == "ia64" || ${MACHINE_ARCH} == "alpha"
+SRCS+= load_elf64.c
+.endif
+
.if defined(LOADER_NET_SUPPORT)
SRCS+= dev_net.c
.endif
@@ -25,3 +35,6 @@ MAN+= ../forth/loader.4th.8
MAN+= loader.8
+.if ${MACHINE_ARCH} == "amd64"
+CFLAGS+= -m32
+.endif
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index d7a95a7e8847..6e17be7ca38c 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -210,7 +210,7 @@ struct preloaded_file
struct file_format
{
/* Load function must return EFTYPE if it can't handle the module supplied */
- int (* l_load)(char *filename, vm_offset_t dest, struct preloaded_file **result);
+ int (* l_load)(char *filename, u_int64_t dest, struct preloaded_file **result);
/* Only a loader that will load a kernel (first module) should have an exec handler */
int (* l_exec)(struct preloaded_file *mp);
};
@@ -231,7 +231,9 @@ int file_addmodule(struct preloaded_file *fp, char *modname, int version,
/* MI module loaders */
-int elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result);
+#ifdef __elfN
+int __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result);
+#endif
/*
* Support for commands
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index 63f5d6418e19..b28abb820cb7 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -41,6 +41,12 @@
#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l)
+#if defined(__i386__) && __ELF_WORD_SIZE == 64
+#undef ELF_TARG_CLASS
+#undef ELF_TARG_MACH
+#define ELF_TARG_CLASS ELFCLASS64
+#define ELF_TARG_MACH EM_X86_64
+#endif
typedef struct elf_file {
Elf_Phdr *ph;
@@ -59,20 +65,20 @@ typedef struct elf_file {
caddr_t firstpage;
size_t firstlen;
int kernel;
- vm_offset_t off;
+ u_int64_t off;
} *elf_file_t;
-static int elf_loadimage(struct preloaded_file *mp, elf_file_t ef, vm_offset_t loadaddr);
-static int elf_lookup_symbol(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
+static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t loadaddr);
+static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
#ifdef __sparc__
-static void elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef,
+static void __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
void *p, void *val, size_t len);
#endif
-static int elf_parse_modmetadata(struct preloaded_file *mp, elf_file_t ef);
+static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef);
static char *fake_modname(const char *name);
-const char *elf_kerneltype = "elf kernel";
-const char *elf_moduletype = "elf module";
+const char *__elfN(kerneltype) = "elf kernel";
+const char *__elfN(moduletype) = "elf module";
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
@@ -80,7 +86,7 @@ const char *elf_moduletype = "elf module";
* will be saved in (result).
*/
int
-elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
+__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
@@ -134,12 +140,12 @@ elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
if (ehdr->e_type == ET_DYN) {
/* Looks like a kld module */
if (kfp == NULL) {
- printf("elf_loadfile: can't load module before kernel\n");
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
- if (strcmp(elf_kerneltype, kfp->f_type)) {
- printf("elf_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
+ if (strcmp(__elfN(kerneltype), kfp->f_type)) {
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
err = EPERM;
goto oerr;
}
@@ -155,16 +161,16 @@ elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
} else if (ehdr->e_type == ET_EXEC) {
/* Looks like a kernel */
if (kfp != NULL) {
- printf("elf_loadfile: kernel already loaded\n");
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n");
err = EPERM;
goto oerr;
}
/*
* Calculate destination address based on kernel entrypoint
*/
- dest = (vm_offset_t) ehdr->e_entry;
+ dest = ehdr->e_entry;
if (dest == 0) {
- printf("elf_loadfile: not a kernel (maybe static binary?)\n");
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
err = EPERM;
goto oerr;
}
@@ -180,23 +186,23 @@ elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
*/
fp = file_alloc();
if (fp == NULL) {
- printf("elf_loadfile: cannot allocate module info\n");
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n");
err = EPERM;
goto out;
}
if (ef.kernel)
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
- fp->f_type = strdup(ef.kernel ? elf_kerneltype : elf_moduletype);
+ fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));
#ifdef ELF_VERBOSE
if (ef.kernel)
- printf("%s entry at %p\n", filename, (void *) dest);
+ printf("%s entry at 0x%jx\n", filename, (uintmax_t)dest);
#else
printf("%s ", filename);
#endif
- fp->f_size = elf_loadimage(fp, &ef, dest);
+ fp->f_size = __elfN(loadimage)(fp, &ef, dest);
if (fp->f_size == 0 || fp->f_addr == 0)
goto ioerr;
@@ -224,7 +230,7 @@ elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
* the Elf header, load the image at (off)
*/
static int
-elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
+__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
{
int i;
u_int j;
@@ -238,12 +244,13 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
size_t resid, chunk;
ssize_t result;
vm_offset_t dest;
- vm_offset_t ssym, esym;
+ Elf_Addr ssym, esym;
Elf_Dyn *dp;
+ Elf_Addr adp;
int ndp;
int symstrindex;
int symtabindex;
- long size;
+ Elf_Size size;
u_int fpcopy;
dp = NULL;
@@ -253,7 +260,11 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
ehdr = ef->ehdr;
if (ef->kernel) {
#ifdef __i386__
+#if __ELF_WORD_SIZE == 64
+ off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */
+#else
off = - (off & 0xff000000u); /* i386 relocates after locore */
+#endif
#else
off = 0; /* alpha is direct mapped for kernels */
#endif
@@ -261,7 +272,7 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
ef->off = off;
if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) {
- printf("elf_loadimage: program header not within first page\n");
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n");
goto out;
}
phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff);
@@ -295,12 +306,12 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
if (phdr[i].p_filesz > fpcopy) {
if (lseek(ef->fd, (off_t)(phdr[i].p_offset + fpcopy),
SEEK_SET) == -1) {
- printf("\nelf_loadexec: cannot seek\n");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: cannot seek\n");
goto out;
}
if (archsw.arch_readin(ef->fd, phdr[i].p_vaddr + off + fpcopy,
phdr[i].p_filesz - fpcopy) != (ssize_t)(phdr[i].p_filesz - fpcopy)) {
- printf("\nelf_loadexec: archsw.readin failed\n");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadexec: archsw.readin failed\n");
goto out;
}
}
@@ -315,7 +326,7 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
/* no archsw.arch_bzero */
buf = malloc(PAGE_SIZE);
if (buf == NULL) {
- printf("\nelf_loadimage: malloc() failed\n");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: malloc() failed\n");
goto out;
}
bzero(buf, PAGE_SIZE);
@@ -353,12 +364,12 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
if (shdr == NULL)
goto nosyms;
if (lseek(ef->fd, (off_t)ehdr->e_shoff, SEEK_SET) == -1) {
- printf("\nelf_loadimage: cannot lseek() to section headers");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: cannot lseek() to section headers");
goto nosyms;
}
result = read(ef->fd, shdr, chunk);
if (result < 0 || (size_t)result != chunk) {
- printf("\nelf_loadimage: read section headers failed");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: read section headers failed");
goto nosyms;
}
symtabindex = -1;
@@ -410,7 +421,7 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
size = shdr[i].sh_size;
archsw.arch_copyin(&size, lastaddr, sizeof(size));
- lastaddr += sizeof(long);
+ lastaddr += sizeof(size);
#ifdef ELF_VERBOSE
printf("\n%s: 0x%lx@0x%lx -> 0x%lx-0x%lx", secname,
@@ -419,25 +430,25 @@ elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off)
#else
if (i == symstrindex)
printf("+");
- printf("0x%lx+0x%lx", (long)sizeof(size), size);
+ printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
#endif
if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) {
- printf("\nelf_loadimage: could not seek for symbols - skipped!");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!");
lastaddr = ssym;
ssym = 0;
goto nosyms;
}
result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size);
if (result < 0 || (size_t)result != shdr[i].sh_size) {
- printf("\nelf_loadimage: could not read symbols - skipped!");
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped!");
lastaddr = ssym;
ssym = 0;
goto nosyms;
}
/* Reset offsets relative to ssym */
lastaddr += shdr[i].sh_size;
- lastaddr = roundup(lastaddr, sizeof(long));
+ lastaddr = roundup(lastaddr, sizeof(size));
if (i == symtabindex)
symtabindex = -1;
else if (i == symstrindex)
@@ -461,9 +472,8 @@ nosyms:
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type == PT_DYNAMIC) {
php = phdr + i;
- dp = (Elf_Dyn *)(php->p_vaddr);
- file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(dp), &dp);
- dp = NULL;
+ adp = php->p_vaddr;
+ file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp);
break;
}
}
@@ -485,19 +495,19 @@ nosyms:
break;
switch (dp[i].d_tag) {
case DT_HASH:
- ef->hashtab = (Elf_Hashelt*)(dp[i].d_un.d_ptr + off);
+ ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_STRTAB:
- ef->strtab = (char *)(dp[i].d_un.d_ptr + off);
+ ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_STRSZ:
ef->strsz = dp[i].d_un.d_val;
break;
case DT_SYMTAB:
- ef->symtab = (Elf_Sym*)(dp[i].d_un.d_ptr + off);
+ ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_RELA:
- ef->rela = (Elf_Rela *)(dp[i].d_un.d_ptr + off);
+ ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_RELASZ:
ef->relasz = dp[i].d_un.d_val;
@@ -513,7 +523,7 @@ nosyms:
COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
- if (elf_parse_modmetadata(fp, ef) == 0)
+ if (__elfN(parse_modmetadata)(fp, ef) == 0)
goto out;
if (ef->kernel) /* kernel must not depend on anything */
@@ -559,33 +569,34 @@ fake_modname(const char *name)
}
int
-elf_parse_modmetadata(struct preloaded_file *fp, elf_file_t ef)
+__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
{
struct mod_metadata md;
struct mod_depend *mdepend;
struct mod_version mver;
Elf_Sym sym;
- char *s, *v, **p, **p_stop;
+ char *s, **p, **p_stop;
int modcnt, minfolen;
+ Elf_Addr v;
- if (elf_lookup_symbol(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
+ if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
return ENOENT;
- p = (char **)(sym.st_value + ef->off);
- if (elf_lookup_symbol(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
+ p = (char **)(uintptr_t)(sym.st_value + ef->off);
+ if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
return ENOENT;
- p_stop = (char **)(sym.st_value + ef->off);
+ p_stop = (char **)(uintptr_t)(sym.st_value + ef->off);
modcnt = 0;
while (p < p_stop) {
COPYOUT(p, &v, sizeof(v));
#ifdef __sparc64__
- elf_reloc_ptr(fp, ef, p, &v, sizeof(v));
+ __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
#else
v += ef->off;
#endif
COPYOUT(v, &md, sizeof(md));
#ifdef __sparc64__
- elf_reloc_ptr(fp, ef, v, &md, sizeof(md));
+ __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md));
#else
md.md_cval += ef->off;
md.md_data += ef->off;
@@ -639,9 +650,9 @@ elf_hash(const char *name)
return h;
}
-static const char elf_bad_symtable[] = "elf_lookup_symbol: corrupt symbol table\n";
+static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n";
int
-elf_lookup_symbol(struct preloaded_file *fp, elf_file_t ef, const char* name,
+__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name,
Elf_Sym *symp)
{
Elf_Hashelt symnum;
@@ -654,13 +665,13 @@ elf_lookup_symbol(struct preloaded_file *fp, elf_file_t ef, const char* name,
while (symnum != STN_UNDEF) {
if (symnum >= ef->nchains) {
- printf(elf_bad_symtable);
+ printf(__elfN(bad_symtable));
return ENOENT;
}
COPYOUT(ef->symtab + symnum, &sym, sizeof(sym));
if (sym.st_name == 0) {
- printf(elf_bad_symtable);
+ printf(__elfN(bad_symtable));
return ENOENT;
}
@@ -688,7 +699,7 @@ elf_lookup_symbol(struct preloaded_file *fp, elf_file_t ef, const char* name,
* the image in-place, because this is done by kern_linker later on.
*/
static void
-elf_reloc_ptr(struct preloaded_file *mp, elf_file_t ef,
+__elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
void *p, void *val, size_t len)
{
Elf_Addr off = (Elf_Addr)p - ef->off, word;
diff --git a/sys/boot/common/load_elf32.c b/sys/boot/common/load_elf32.c
new file mode 100644
index 000000000000..59b6496b0a2d
--- /dev/null
+++ b/sys/boot/common/load_elf32.c
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+#define __ELF_WORD_SIZE 32
+#include "load_elf.c"
diff --git a/sys/boot/common/load_elf64.c b/sys/boot/common/load_elf64.c
new file mode 100644
index 000000000000..d5f99d90ee42
--- /dev/null
+++ b/sys/boot/common/load_elf64.c
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+#define __ELF_WORD_SIZE 64
+#include "load_elf.c"
diff --git a/sys/boot/efi/libefi/elf_freebsd.c b/sys/boot/efi/libefi/elf_freebsd.c
index 7df9950bbce6..27d2b6e08568 100644
--- a/sys/boot/efi/libefi/elf_freebsd.c
+++ b/sys/boot/efi/libefi/elf_freebsd.c
@@ -94,9 +94,9 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
-struct file_format ia64_elf = { elf_loadfile, elf_exec };
+struct file_format ia64_elf = { elf64_loadfile, elf64_exec };
static __inline u_int64_t
disable_ic()
@@ -136,7 +136,7 @@ enter_kernel(u_int64_t start, struct bootinfo *bi)
}
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *hdr;
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 19fa0bf36471..b7cb2cc852b6 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -4,9 +4,11 @@ LIB= i386
INTERNALLIB= true
SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
- biospci.c bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \
+ biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
+ comconsole.c devicename.c elf32_freebsd.c \
+ elf64_freebsd.c gatea20.c \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
- time.c vidconsole.c
+ time.c vidconsole.c amd64_tramp.S
CFLAGS+= -ffreestanding
BOOT_COMCONSOLE_PORT?= 0x3f8
diff --git a/sys/boot/i386/libi386/amd64_tramp.S b/sys/boot/i386/libi386/amd64_tramp.S
new file mode 100644
index 000000000000..012512d8c8a8
--- /dev/null
+++ b/sys/boot/i386/libi386/amd64_tramp.S
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Quick and dirty trampoline to get into 64 bit (long) mode and running
+ * with paging enabled so that we enter the kernel at its linked address.
+ */
+#define MSR_EFER 0xc0000080
+#define EFER_LME 0x00000100
+#define CR4_PAE 0x00000020
+#define CR4_PSE 0x00000010
+#define CR0_PG 0x80000000
+
+/* GRRR. Deal with BTX that links us for a non-zero location */
+#define VPBASE 0xa000
+#define VTOP(x) ((x) + VPBASE)
+
+ .data
+
+ .p2align 12,0x40
+
+ .globl PT4
+PT4:
+ .space 0x1000
+ .globl PT3
+PT3:
+ .space 0x1000
+ .globl PT2
+PT2:
+ .space 0x1000
+
+gdtdesc:
+ .word gdtend - gdt
+ .long VTOP(gdt) # low
+ .long 0 # high
+
+gdt:
+ .long 0 # null descriptor
+ .long 0
+ .long 0x00000000 # %cs
+ .long 0x00209800
+ .long 0x00000000 # %ds
+ .long 0x00008000
+gdtend:
+
+ .text
+ .code32
+
+ .globl amd64_tramp
+amd64_tramp:
+ /* Be sure that interrupts are disabled */
+ cli
+
+ /* Turn on EFER.LME */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orl $EFER_LME, %eax
+ wrmsr
+
+ /* Turn on PAE */
+ movl %cr4, %eax
+ orl $(CR4_PAE | CR4_PSE), %eax
+ movl %eax, %cr4
+
+ /* Set %cr3 for PT4 */
+ movl $VTOP(PT4), %eax
+ movl %eax, %cr3
+
+ /* Turn on paging (implicitly sets EFER.LMA) */
+ movl %cr0, %eax
+ orl $CR0_PG, %eax
+ movl %eax, %cr0
+
+ /* Now we're in compatability mode. set %cs for long mode */
+ movl $VTOP(gdtdesc), %eax
+ movl VTOP(entry_hi), %esi
+ movl VTOP(entry_lo), %edi
+ lgdt (%eax)
+ ljmp $0x8, $VTOP(longmode)
+
+ .code64
+longmode:
+ /* We're still running V=P, jump to entry point */
+ movl %esi, %eax
+ salq $32, %rax
+ movl %edi, %eax
+ pushq %rax
+ ret
diff --git a/sys/boot/i386/libi386/biossmap.c b/sys/boot/i386/libi386/biossmap.c
new file mode 100644
index 000000000000..1548dd901e19
--- /dev/null
+++ b/sys/boot/i386/libi386/biossmap.c
@@ -0,0 +1,107 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Obtain memory configuration information from the BIOS
+ */
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <machine/metadata.h>
+#include "bootstrap.h"
+#include "libi386.h"
+#include "btxv86.h"
+
+#define SMAPSIG 0x534D4150
+
+struct smap {
+ u_int64_t base;
+ u_int64_t length;
+ u_int32_t type;
+} __packed;
+
+static struct smap smap;
+
+static struct smap *smapbase;
+static int smaplen;
+
+void
+bios_getsmap(void)
+{
+ int n;
+
+ n = 0;
+ smaplen = 0;
+ /* Count up segments in system memory map */
+ v86.ebx = 0;
+ do {
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x15; /* int 0x15 function 0xe820*/
+ v86.eax = 0xe820;
+ v86.ecx = sizeof(struct smap);
+ v86.edx = SMAPSIG;
+ v86.es = VTOPSEG(&smap);
+ v86.edi = VTOPOFF(&smap);
+ v86int();
+ if ((v86.efl & 1) || (v86.eax != SMAPSIG))
+ break;
+ n++;
+ } while (v86.ebx != 0);
+ if (n == 0)
+ return;
+ n += 10; /* spare room */
+ smapbase = malloc(n * sizeof(*smapbase));
+
+ /* Save system memory map */
+ v86.ebx = 0;
+ do {
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x15; /* int 0x15 function 0xe820*/
+ v86.eax = 0xe820;
+ v86.ecx = sizeof(struct smap);
+ v86.edx = SMAPSIG;
+ v86.es = VTOPSEG(&smapbase[smaplen]);
+ v86.edi = VTOPOFF(&smapbase[smaplen]);
+ v86int();
+ smaplen++;
+ if ((v86.efl & 1) || (v86.eax != SMAPSIG))
+ break;
+ } while (v86.ebx != 0 && smaplen < n);
+}
+void
+bios_addsmapdata(struct preloaded_file *kfp)
+{
+ int len;
+
+ if (smapbase == 0 || smaplen == 0)
+ return;
+ len = smaplen * sizeof(*smapbase);
+ file_addmetadata(kfp, MODINFOMD_SMAP, len, smapbase);
+ /* Temporary compatability with older development kernels */
+ file_addmetadata(kfp, 0x0009, len, smapbase);
+}
diff --git a/sys/boot/i386/libi386/bootinfo.c b/sys/boot/i386/libi386/bootinfo.c
index fb269dfa43cc..5de13a7a9918 100644
--- a/sys/boot/i386/libi386/bootinfo.c
+++ b/sys/boot/i386/libi386/bootinfo.c
@@ -30,13 +30,10 @@
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/linker.h>
-#include <machine/bootinfo.h>
#include "bootstrap.h"
#include "libi386.h"
#include "btxv86.h"
-static struct bootinfo bi;
-
/*
* Return a 'boothowto' value corresponding to the kernel arguments in
* (kargs) and any relevant environment variables.
@@ -58,8 +55,6 @@ static struct
{NULL, 0}
};
-vm_offset_t bi_copymodules(vm_offset_t addr);
-
int
bi_getboothowto(char *kargs)
{
@@ -159,205 +154,3 @@ bi_copyenv(vm_offset_t addr)
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) { \
- 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_long));\
-}
-
-#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_long)); \
-}
-
-#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_long));\
-}
-
-#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) {
-
- MOD_NAME(addr, fp->f_name); /* this field must come first */
- 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 an i386 kernel.
- *
- * - The 'boothowto' argument is constructed
- * - The 'bootdev' argument is constructed
- * - The 'bootinfo' struct is constructed, and copied into the kernel space.
- * - The kernel environment is copied into kernel space.
- * - Module metadata are formatted and placed in kernel space.
- */
-int
-bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
-{
- struct preloaded_file *xp;
- struct i386_devdesc *rootdev;
- vm_offset_t addr;
- char *rootdevname;
- int bootdevnr, i;
- u_int pad;
- char *kernelname;
- const char *kernelpath;
-
- *howtop = bi_getboothowto(args);
-
- /*
- * Allow the environment variable 'rootdev' to override the supplied device
- * This should perhaps go to MI code and/or have $rootdev tested/set by
- * MI code before launching the kernel.
- */
- rootdevname = getenv("rootdev");
- i386_getdev((void **)(&rootdev), rootdevname, NULL);
- if (rootdev == NULL) { /* bad $rootdev/$currdev */
- printf("can't determine root device\n");
- return(EINVAL);
- }
-
- /* Try reading the /etc/fstab file to select the root device */
- getrootmount(i386_fmtdev((void *)rootdev));
-
- /* Do legacy rootdev guessing */
-
- /* XXX - use a default bootdev of 0. Is this ok??? */
- bootdevnr = 0;
-
- switch(rootdev->d_type) {
- case DEVT_CD:
- /* Pass in BIOS device number. */
- bi.bi_bios_dev = bc_unit2bios(rootdev->d_kind.bioscd.unit);
- bootdevnr = bc_getdev(rootdev);
- break;
-
- case DEVT_DISK:
- /* pass in the BIOS device number of the current disk */
- bi.bi_bios_dev = bd_unit2bios(rootdev->d_kind.biosdisk.unit);
- bootdevnr = bd_getdev(rootdev);
- break;
-
- case DEVT_NET:
- break;
-
- default:
- printf("WARNING - don't know how to boot from device type %d\n", rootdev->d_type);
- }
- if (bootdevnr == -1) {
- printf("root device %s invalid\n", i386_fmtdev(rootdev));
- return (EINVAL);
- }
- free(rootdev);
- *bootdevp = bootdevnr;
-
- /* legacy bootinfo structure */
- bi.bi_version = BOOTINFO_VERSION;
- bi.bi_kernelname = 0; /* XXX char * -> kernel name */
- bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
- bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
- for (i = 0; i < N_BIOS_GEOM; i++)
- bi.bi_bios_geom[i] = bd_getbigeom(i);
- bi.bi_size = sizeof(bi);
- bi.bi_memsizes_valid = 1;
- bi.bi_basemem = bios_basemem / 1024;
- bi.bi_extmem = bios_extmem / 1024;
-
- /* 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 = (u_int)addr & PAGE_MASK;
- if (pad != 0) {
- pad = PAGE_SIZE - pad;
- addr += pad;
- }
-
- /* copy our environment */
- bi.bi_envp = 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.bi_modulep = addr;
- addr = bi_copymodules(addr);
-
- /* all done copying stuff in, save end of loaded object space */
- bi.bi_kernend = addr;
-
- *howtop |= RB_BOOTINFO; /* it's there now */
-
- /*
- * Get the kernel name, strip off any device prefix.
- */
- kernelname = getenv("kernelname");
- i386_getdev(NULL, kernelname, &kernelpath);
- bi.bi_kernelname = VTOP(kernelpath);
- *bip = VTOP(&bi);
-
- return(0);
-}
diff --git a/sys/boot/i386/libi386/bootinfo32.c b/sys/boot/i386/libi386/bootinfo32.c
index fb269dfa43cc..a2fc2c8d0361 100644
--- a/sys/boot/i386/libi386/bootinfo32.c
+++ b/sys/boot/i386/libi386/bootinfo32.c
@@ -35,130 +35,7 @@
#include "libi386.h"
#include "btxv86.h"
-static struct bootinfo bi;
-
-/*
- * 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_userconfig", RB_CONFIG},
- {"boot_ddb", RB_KDB},
- {"boot_gdb", RB_GDB},
- {"boot_single", RB_SINGLE},
- {"boot_verbose", RB_VERBOSE},
- {"boot_multicons", RB_MULTIPLE},
- {"boot_serial", RB_SERIAL},
- {NULL, 0}
-};
-
-vm_offset_t bi_copymodules(vm_offset_t addr);
-
-int
-bi_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_CONFIG;
- 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 <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) {
- 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);
-}
+static struct bootinfo bi;
/*
* Copy module-related data into the load area, where it can be
@@ -176,65 +53,71 @@ bi_copyenv(vm_offset_t addr)
* MOD_SIZE sizeof(size_t) module size
* MOD_METADATA (variable) type-specific metadata
*/
-#define COPY32(v, a) { \
+#define COPY32(v, a, c) { \
u_int32_t x = (v); \
- i386_copyin(&x, a, sizeof(x)); \
+ if (c) \
+ 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); \
+#define MOD_STR(t, a, s, c) { \
+ COPY32(t, a, c); \
+ COPY32(strlen(s) + 1, a, c); \
+ if (c) \
+ i386_copyin(s, a, strlen(s) + 1); \
a += roundup(strlen(s) + 1, sizeof(u_long));\
}
-#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_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) { \
- COPY32(t, a); \
- COPY32(sizeof(s), a); \
- i386_copyin(&s, a, sizeof(s)); \
+#define MOD_VAR(t, a, s, c) { \
+ COPY32(t, a, c); \
+ COPY32(sizeof(s), a, c); \
+ if (c) \
+ i386_copyin(&s, a, sizeof(s)); \
a += roundup(sizeof(s), sizeof(u_long)); \
}
-#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s)
-#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s)
+#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) { \
- COPY32(MODINFO_METADATA | mm->md_type, a); \
- COPY32(mm->md_size, a); \
- i386_copyin(mm->md_data, a, mm->md_size); \
+#define MOD_METADATA(a, mm, c) { \
+ COPY32(MODINFO_METADATA | mm->md_type, a, c); \
+ COPY32(mm->md_size, a, c); \
+ if (c) \
+ i386_copyin(mm->md_data, a, mm->md_size); \
a += roundup(mm->md_size, sizeof(u_long));\
}
-#define MOD_END(a) { \
- COPY32(MODINFO_END, a); \
- COPY32(0, a); \
+#define MOD_END(a, c) { \
+ COPY32(MODINFO_END, a, c); \
+ COPY32(0, a, c); \
}
-vm_offset_t
-bi_copymodules(vm_offset_t addr)
+static vm_offset_t
+bi_copymodules32(vm_offset_t addr)
{
struct preloaded_file *fp;
struct file_metadata *md;
+ int c;
+ c = addr != 0;
/* start with the first module on the list, should be the kernel */
for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
- MOD_NAME(addr, fp->f_name); /* this field must come first */
- MOD_TYPE(addr, fp->f_type);
+ 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);
- MOD_ADDR(addr, fp->f_addr);
- MOD_SIZE(addr, fp->f_size);
+ 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);
+ MOD_METADATA(addr, md, c);
}
- MOD_END(addr);
+ MOD_END(addr, c);
return(addr);
}
@@ -248,18 +131,22 @@ bi_copymodules(vm_offset_t addr)
* - Module metadata are formatted and placed in kernel space.
*/
int
-bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
+bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp)
{
- struct preloaded_file *xp;
+ struct preloaded_file *xp, *kfp;
struct i386_devdesc *rootdev;
+ struct file_metadata *md;
vm_offset_t addr;
+ vm_offset_t kernend;
+ vm_offset_t envp;
+ vm_offset_t size;
+ vm_offset_t ssym, esym;
char *rootdevname;
- int bootdevnr, i;
- u_int pad;
+ int bootdevnr, i, howto;
char *kernelname;
const char *kernelpath;
- *howtop = bi_getboothowto(args);
+ howto = bi_getboothowto(args);
/*
* Allow the environment variable 'rootdev' to override the supplied device
@@ -305,19 +192,6 @@ bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
return (EINVAL);
}
free(rootdev);
- *bootdevp = bootdevnr;
-
- /* legacy bootinfo structure */
- bi.bi_version = BOOTINFO_VERSION;
- bi.bi_kernelname = 0; /* XXX char * -> kernel name */
- bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
- bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
- for (i = 0; i < N_BIOS_GEOM; i++)
- bi.bi_bios_geom[i] = bd_getbigeom(i);
- bi.bi_size = sizeof(bi);
- bi.bi_memsizes_valid = 1;
- bi.bi_basemem = bios_basemem / 1024;
- bi.bi_extmem = bios_extmem / 1024;
/* find the last module in the chain */
addr = 0;
@@ -326,37 +200,72 @@ bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
addr = xp->f_addr + xp->f_size;
}
/* pad to a page boundary */
- pad = (u_int)addr & PAGE_MASK;
- if (pad != 0) {
- pad = PAGE_SIZE - pad;
- addr += pad;
- }
+ addr = roundup(addr, PAGE_SIZE);
/* copy our environment */
- bi.bi_envp = addr;
+ envp = 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.bi_modulep = addr;
- addr = bi_copymodules(addr);
+ addr = roundup(addr, PAGE_SIZE);
- /* all done copying stuff in, save end of loaded object space */
- bi.bi_kernend = addr;
+ kfp = file_findfile(NULL, "elf64 kernel");
+ if (kfp == NULL)
+ kfp = file_findfile(NULL, "elf32 kernel");
+ if (kfp == NULL)
+ panic("can't find kernel file");
+ kernend = 0; /* fill it in later */
+ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
+ file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+ file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+ bios_addsmapdata(kfp);
- *howtop |= RB_BOOTINFO; /* it's there now */
+ /* Figure out the size and location of the metadata */
+ *modulep = addr;
+ size = bi_copymodules32(0);
+ kernend = roundup(addr + size, PAGE_SIZE);
+ *kernendp = kernend;
- /*
- * Get the kernel name, strip off any device prefix.
- */
+ /* patch MODINFOMD_KERNEND */
+ md = file_findmetadata(kfp, MODINFOMD_KERNEND);
+ bcopy(&kernend, md->md_data, sizeof kernend);
+
+ /* copy module list and metadata */
+ (void)bi_copymodules32(addr);
+
+ ssym = esym = 0;
+ md = file_findmetadata(kfp, MODINFOMD_SSYM);
+ if (md != NULL)
+ ssym = *((vm_offset_t *)&(md->md_data));
+ md = file_findmetadata(kfp, MODINFOMD_ESYM);
+ if (md != NULL)
+ esym = *((vm_offset_t *)&(md->md_data));
+ if (ssym == 0 || esym == 0)
+ ssym = esym = 0; /* sanity */
+
+ /* legacy bootinfo structure */
kernelname = getenv("kernelname");
i386_getdev(NULL, kernelname, &kernelpath);
+ bi.bi_version = BOOTINFO_VERSION;
+ bi.bi_kernelname = 0; /* XXX char * -> kernel name */
+ bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
+ bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
+ for (i = 0; i < N_BIOS_GEOM; i++)
+ bi.bi_bios_geom[i] = bd_getbigeom(i);
+ bi.bi_size = sizeof(bi);
+ bi.bi_memsizes_valid = 1;
+ bi.bi_basemem = bios_basemem / 1024;
+ bi.bi_extmem = bios_extmem / 1024;
+ bi.bi_envp = envp;
+ bi.bi_modulep = *modulep;
+ bi.bi_kernend = kernend;
bi.bi_kernelname = VTOP(kernelpath);
+ bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */
+ bi.bi_esymtab = esym;
+
+ /* legacy boot arguments */
+ *howtop = howto | RB_BOOTINFO;
+ *bootdevp = bootdevnr;
*bip = VTOP(&bi);
return(0);
diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c
index fb269dfa43cc..5398a0c0a41a 100644
--- a/sys/boot/i386/libi386/bootinfo64.c
+++ b/sys/boot/i386/libi386/bootinfo64.c
@@ -35,131 +35,6 @@
#include "libi386.h"
#include "btxv86.h"
-static struct bootinfo bi;
-
-/*
- * 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_userconfig", RB_CONFIG},
- {"boot_ddb", RB_KDB},
- {"boot_gdb", RB_GDB},
- {"boot_single", RB_SINGLE},
- {"boot_verbose", RB_VERBOSE},
- {"boot_multicons", RB_MULTIPLE},
- {"boot_serial", RB_SERIAL},
- {NULL, 0}
-};
-
-vm_offset_t bi_copymodules(vm_offset_t addr);
-
-int
-bi_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_CONFIG;
- 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 <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) {
- 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);
-}
-
/*
* Copy module-related data into the load area, where it can be
* used as a directory for loaded modules.
@@ -176,65 +51,74 @@ bi_copyenv(vm_offset_t addr)
* MOD_SIZE sizeof(size_t) module size
* MOD_METADATA (variable) type-specific metadata
*/
-#define COPY32(v, a) { \
+#define COPY32(v, a, c) { \
u_int32_t x = (v); \
- i386_copyin(&x, a, sizeof(x)); \
+ if (c) \
+ 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_long));\
+#define MOD_STR(t, a, s, c) { \
+ COPY32(t, a, c); \
+ COPY32(strlen(s) + 1, a, c); \
+ if (c) \
+ 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_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) { \
- COPY32(t, a); \
- COPY32(sizeof(s), a); \
- i386_copyin(&s, a, sizeof(s)); \
- a += roundup(sizeof(s), sizeof(u_long)); \
+#define MOD_VAR(t, a, s, c) { \
+ COPY32(t, a, c); \
+ COPY32(sizeof(s), a, c); \
+ if (c) \
+ 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_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) { \
- 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_long));\
+#define MOD_METADATA(a, mm, c) { \
+ COPY32(MODINFO_METADATA | mm->md_type, a, c); \
+ COPY32(mm->md_size, a, c); \
+ if (c) \
+ 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); \
+#define MOD_END(a, c) { \
+ COPY32(MODINFO_END, a, c); \
+ COPY32(0, a, c); \
}
-vm_offset_t
-bi_copymodules(vm_offset_t addr)
+static vm_offset_t
+bi_copymodules64(vm_offset_t addr)
{
struct preloaded_file *fp;
struct file_metadata *md;
+ int c;
+ u_int64_t v;
+ c = addr != 0;
/* start with the first module on the list, should be the kernel */
for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
- MOD_NAME(addr, fp->f_name); /* this field must come first */
- MOD_TYPE(addr, fp->f_type);
+ 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);
- MOD_ADDR(addr, fp->f_addr);
- MOD_SIZE(addr, fp->f_size);
+ MOD_ARGS(addr, fp->f_args, c);
+ v = fp->f_addr;
+ MOD_ADDR(addr, v, c);
+ v = fp->f_size;
+ MOD_SIZE(addr, v, c);
for (md = fp->f_metadata; md != NULL; md = md->md_next)
if (!(md->md_type & MODINFOMD_NOCOPY))
- MOD_METADATA(addr, md);
+ MOD_METADATA(addr, md, c);
}
- MOD_END(addr);
+ MOD_END(addr, c);
return(addr);
}
@@ -248,18 +132,21 @@ bi_copymodules(vm_offset_t addr)
* - Module metadata are formatted and placed in kernel space.
*/
int
-bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
+bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
{
- struct preloaded_file *xp;
+ struct preloaded_file *xp, *kfp;
struct i386_devdesc *rootdev;
+ struct file_metadata *md;
vm_offset_t addr;
+ u_int64_t kernend;
+ u_int64_t envp;
+ vm_offset_t size;
char *rootdevname;
- int bootdevnr, i;
- u_int pad;
+ int i, howto;
char *kernelname;
const char *kernelpath;
- *howtop = bi_getboothowto(args);
+ howto = bi_getboothowto(args);
/*
* Allow the environment variable 'rootdev' to override the supplied device
@@ -276,49 +163,6 @@ bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
/* Try reading the /etc/fstab file to select the root device */
getrootmount(i386_fmtdev((void *)rootdev));
- /* Do legacy rootdev guessing */
-
- /* XXX - use a default bootdev of 0. Is this ok??? */
- bootdevnr = 0;
-
- switch(rootdev->d_type) {
- case DEVT_CD:
- /* Pass in BIOS device number. */
- bi.bi_bios_dev = bc_unit2bios(rootdev->d_kind.bioscd.unit);
- bootdevnr = bc_getdev(rootdev);
- break;
-
- case DEVT_DISK:
- /* pass in the BIOS device number of the current disk */
- bi.bi_bios_dev = bd_unit2bios(rootdev->d_kind.biosdisk.unit);
- bootdevnr = bd_getdev(rootdev);
- break;
-
- case DEVT_NET:
- break;
-
- default:
- printf("WARNING - don't know how to boot from device type %d\n", rootdev->d_type);
- }
- if (bootdevnr == -1) {
- printf("root device %s invalid\n", i386_fmtdev(rootdev));
- return (EINVAL);
- }
- free(rootdev);
- *bootdevp = bootdevnr;
-
- /* legacy bootinfo structure */
- bi.bi_version = BOOTINFO_VERSION;
- bi.bi_kernelname = 0; /* XXX char * -> kernel name */
- bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */
- bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */
- for (i = 0; i < N_BIOS_GEOM; i++)
- bi.bi_bios_geom[i] = bd_getbigeom(i);
- bi.bi_size = sizeof(bi);
- bi.bi_memsizes_valid = 1;
- bi.bi_basemem = bios_basemem / 1024;
- bi.bi_extmem = bios_extmem / 1024;
-
/* find the last module in the chain */
addr = 0;
for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
@@ -326,38 +170,38 @@ bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip)
addr = xp->f_addr + xp->f_size;
}
/* pad to a page boundary */
- pad = (u_int)addr & PAGE_MASK;
- if (pad != 0) {
- pad = PAGE_SIZE - pad;
- addr += pad;
- }
+ addr = roundup(addr, PAGE_SIZE);
/* copy our environment */
- bi.bi_envp = addr;
+ envp = 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.bi_modulep = addr;
- addr = bi_copymodules(addr);
+ addr = roundup(addr, PAGE_SIZE);
- /* all done copying stuff in, save end of loaded object space */
- bi.bi_kernend = addr;
+ kfp = file_findfile(NULL, "elf64 kernel");
+ if (kfp == NULL)
+ kfp = file_findfile(NULL, "elf32 kernel");
+ if (kfp == NULL)
+ panic("can't find kernel file");
+ kernend = 0; /* fill it in later */
+ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
+ file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+ file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+ bios_addsmapdata(kfp);
- *howtop |= RB_BOOTINFO; /* it's there now */
+ /* Figure out the size and location of the metadata */
+ *modulep = addr;
+ size = bi_copymodules64(0);
+ kernend = roundup(addr + size, PAGE_SIZE);
+ *kernendp = kernend;
- /*
- * Get the kernel name, strip off any device prefix.
- */
- kernelname = getenv("kernelname");
- i386_getdev(NULL, kernelname, &kernelpath);
- bi.bi_kernelname = VTOP(kernelpath);
- *bip = VTOP(&bi);
+ /* patch MODINFOMD_KERNEND */
+ md = file_findmetadata(kfp, MODINFOMD_KERNEND);
+ bcopy(&kernend, md->md_data, sizeof kernend);
+
+ /* copy module list and metadata */
+ (void)bi_copymodules64(addr);
return(0);
}
diff --git a/sys/boot/i386/libi386/elf32_freebsd.c b/sys/boot/i386/libi386/elf32_freebsd.c
index 514183db144c..3c9397b3a094 100644
--- a/sys/boot/i386/libi386/elf32_freebsd.c
+++ b/sys/boot/i386/libi386/elf32_freebsd.c
@@ -38,9 +38,9 @@
#include "libi386.h"
#include "btxv86.h"
-static int elf_exec(struct preloaded_file *amp);
+static int elf32_exec(struct preloaded_file *amp);
-struct file_format i386_elf = { elf_loadfile, elf_exec };
+struct file_format i386_elf = { elf32_loadfile, elf32_exec };
/*
* There is an a.out kernel and one or more a.out modules loaded.
@@ -48,41 +48,28 @@ struct file_format i386_elf = { elf_loadfile, elf_exec };
* preparations as are required, and do so.
*/
static int
-elf_exec(struct preloaded_file *fp)
+elf32_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *ehdr;
- vm_offset_t entry, bootinfop;
+ vm_offset_t entry, bootinfop, modulep, kernend;
int boothowto, err, bootdev;
- struct bootinfo *bi;
- vm_offset_t ssym, esym;
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
return(EFTYPE); /* XXX actually EFUCKUP */
ehdr = (Elf_Ehdr *)&(md->md_data);
- if ((err = bi_load(fp->f_args, &boothowto, &bootdev, &bootinfop)) != 0)
+ err = bi_load32(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend);
+ if (err != 0)
return(err);
entry = ehdr->e_entry & 0xffffff;
- ssym = esym = 0;
- if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL)
- ssym = *((vm_offset_t *)&(md->md_data));
- if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL)
- esym = *((vm_offset_t *)&(md->md_data));
- if (ssym == 0 || esym == 0)
- ssym = esym = 0; /* sanity */
- bi = (struct bootinfo *)PTOV(bootinfop);
- bi->bi_symtab = ssym; /* XXX this is only the primary kernel symtab */
- bi->bi_esymtab = esym;
-
-
#ifdef DEBUG
printf("Start @ 0x%lx ...\n", entry);
#endif
dev_cleanup();
- __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop);
+ __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend);
panic("exec returned");
}
diff --git a/sys/boot/i386/libi386/elf64_freebsd.c b/sys/boot/i386/libi386/elf64_freebsd.c
index 514183db144c..d1033f29c7d0 100644
--- a/sys/boot/i386/libi386/elf64_freebsd.c
+++ b/sys/boot/i386/libi386/elf64_freebsd.c
@@ -26,6 +26,7 @@
* $FreeBSD$
*/
+#define __ELF_WORD_SIZE 64
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/linker.h>
@@ -38,9 +39,26 @@
#include "libi386.h"
#include "btxv86.h"
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
-struct file_format i386_elf = { elf_loadfile, elf_exec };
+struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
+
+#define PG_V 0x001
+#define PG_RW 0x002
+#define PG_U 0x004
+#define PG_PS 0x080
+
+typedef u_int64_t p4_entry_t;
+typedef u_int64_t p3_entry_t;
+typedef u_int64_t p2_entry_t;
+extern p4_entry_t PT4[];
+extern p3_entry_t PT3[];
+extern p2_entry_t PT2[];
+
+u_int32_t entry_hi;
+u_int32_t entry_lo;
+
+extern amd64_tramp();
/*
* There is an a.out kernel and one or more a.out modules loaded.
@@ -48,41 +66,52 @@ struct file_format i386_elf = { elf_loadfile, elf_exec };
* preparations as are required, and do so.
*/
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *ehdr;
- vm_offset_t entry, bootinfop;
- int boothowto, err, bootdev;
- struct bootinfo *bi;
- vm_offset_t ssym, esym;
+ vm_offset_t modulep, kernend;
+ int err;
+ int i;
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
return(EFTYPE); /* XXX actually EFUCKUP */
ehdr = (Elf_Ehdr *)&(md->md_data);
- if ((err = bi_load(fp->f_args, &boothowto, &bootdev, &bootinfop)) != 0)
+ err = bi_load64(fp->f_args, &modulep, &kernend);
+ if (err != 0)
return(err);
- entry = ehdr->e_entry & 0xffffff;
- ssym = esym = 0;
- if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL)
- ssym = *((vm_offset_t *)&(md->md_data));
- if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL)
- esym = *((vm_offset_t *)&(md->md_data));
- if (ssym == 0 || esym == 0)
- ssym = esym = 0; /* sanity */
- bi = (struct bootinfo *)PTOV(bootinfop);
- bi->bi_symtab = ssym; /* XXX this is only the primary kernel symtab */
- bi->bi_esymtab = esym;
+ bzero(PT4, PAGE_SIZE);
+ bzero(PT3, PAGE_SIZE);
+ bzero(PT2, PAGE_SIZE);
+
+ /* single PML4 entry */
+ PT4[0] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]);
+ PT4[0] |= PG_V | PG_RW | PG_U;
+
+ /* Direct map 1GB at address zero */
+ PT3[0] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
+ PT3[0] |= PG_V | PG_RW | PG_U;
+
+ /* Direct map 1GB at KERNBASE (hardcoded for now) */
+ PT3[1] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
+ PT3[1] |= PG_V | PG_RW | PG_U;
+ /* 512 PG_PS (2MB) page mappings for 1GB of direct mapping */
+ for (i = 0; i < 512; i++) {
+ PT2[i] = i * (2 * 1024 * 1024);
+ PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
+ }
+ entry_lo = ehdr->e_entry & 0xffffffff;
+ entry_hi = (ehdr->e_entry >> 32) & 0xffffffff;
#ifdef DEBUG
- printf("Start @ 0x%lx ...\n", entry);
+ printf("Start @ %#llx ...\n", ehdr->e_entry);
#endif
dev_cleanup();
- __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop);
+ __exec((void *)VTOP(amd64_tramp), modulep, kernend);
panic("exec returned");
}
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index cabe735b7bcf..f2696e0a360d 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -84,6 +84,10 @@ ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len);
ssize_t i386_copyout(const vm_offset_t src, void *dest, const size_t len);
ssize_t i386_readin(const int fd, vm_offset_t dest, const size_t len);
+struct preloaded_file;
+void bios_addsmapdata(struct preloaded_file *);
+void bios_getsmap(void);
+
void bios_getmem(void);
extern u_int32_t bios_basemem; /* base memory in bytes */
extern u_int32_t bios_extmem; /* extended memory in bytes */
@@ -97,6 +101,8 @@ int i386_autoload(void);
int bi_getboothowto(char *kargs);
vm_offset_t bi_copyenv(vm_offset_t addr);
-int bi_load(char *args, int *howtop, int *bootdevp, vm_offset_t *bip);
+int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
+ vm_offset_t *modulep, vm_offset_t *kernend);
+int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
void pxe_enable(void *pxeinfo);
diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c
index 78b5d59b72ad..17d8d7d43dbd 100644
--- a/sys/boot/i386/loader/conf.c
+++ b/sys/boot/i386/loader/conf.c
@@ -82,9 +82,11 @@ struct fs_ops *file_system[] = {
* rather than reading the file go first.
*/
extern struct file_format i386_elf;
+extern struct file_format amd64_elf;
struct file_format *file_formats[] = {
&i386_elf,
+ &amd64_elf,
NULL
};
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index f30213111858..ff2ee1034801 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -144,6 +144,8 @@ main(void)
extract_currdev(); /* set $currdev and $loaddev */
setenv("LINES", "24", 1); /* optional */
+ bios_getsmap();
+
archsw.arch_autoload = i386_autoload;
archsw.arch_getdev = i386_getdev;
archsw.arch_copyin = i386_copyin;
diff --git a/sys/boot/ia64/common/exec.c b/sys/boot/ia64/common/exec.c
index 7df9950bbce6..27d2b6e08568 100644
--- a/sys/boot/ia64/common/exec.c
+++ b/sys/boot/ia64/common/exec.c
@@ -94,9 +94,9 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
-struct file_format ia64_elf = { elf_loadfile, elf_exec };
+struct file_format ia64_elf = { elf64_loadfile, elf64_exec };
static __inline u_int64_t
disable_ic()
@@ -136,7 +136,7 @@ enter_kernel(u_int64_t start, struct bootinfo *bi)
}
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *hdr;
diff --git a/sys/boot/ia64/libski/elf_freebsd.c b/sys/boot/ia64/libski/elf_freebsd.c
index e72a52d5a7b9..c6599a77a2b6 100644
--- a/sys/boot/ia64/libski/elf_freebsd.c
+++ b/sys/boot/ia64/libski/elf_freebsd.c
@@ -91,9 +91,9 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
-struct file_format ia64_elf = { elf_loadfile, elf_exec };
+struct file_format ia64_elf = { elf64_loadfile, elf64_exec };
#define PTE_MA_WB 0
#define PTE_MA_UC 4
@@ -154,7 +154,7 @@ enter_kernel(const char* filename, u_int64_t start, struct bootinfo *bi)
}
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *hdr;
diff --git a/sys/boot/ia64/ski/elf_freebsd.c b/sys/boot/ia64/ski/elf_freebsd.c
index e72a52d5a7b9..c6599a77a2b6 100644
--- a/sys/boot/ia64/ski/elf_freebsd.c
+++ b/sys/boot/ia64/ski/elf_freebsd.c
@@ -91,9 +91,9 @@
#define _KERNEL
-static int elf_exec(struct preloaded_file *amp);
+static int elf64_exec(struct preloaded_file *amp);
-struct file_format ia64_elf = { elf_loadfile, elf_exec };
+struct file_format ia64_elf = { elf64_loadfile, elf64_exec };
#define PTE_MA_WB 0
#define PTE_MA_UC 4
@@ -154,7 +154,7 @@ enter_kernel(const char* filename, u_int64_t start, struct bootinfo *bi)
}
static int
-elf_exec(struct preloaded_file *fp)
+elf64_exec(struct preloaded_file *fp)
{
struct file_metadata *md;
Elf_Ehdr *hdr;
diff --git a/sys/boot/ofw/libofw/elf_freebsd.c b/sys/boot/ofw/libofw/elf_freebsd.c
index 95d4a908af69..7fa75860d808 100644
--- a/sys/boot/ofw/libofw/elf_freebsd.c
+++ b/sys/boot/ofw/libofw/elf_freebsd.c
@@ -42,13 +42,13 @@ extern char end[];
extern vm_offset_t reloc; /* From <arch>/conf.c */
int
-ofw_elf_loadfile(char *filename, vm_offset_t dest,
+__elfN(ofw_loadfile)(char *filename, vm_offset_t dest,
struct preloaded_file **result)
{
int r;
void *addr;
- r = elf_loadfile(filename, dest, result);
+ r = __elfN(loadfile)(filename, dest, result);
if (r != 0)
return (r);
@@ -56,7 +56,7 @@ ofw_elf_loadfile(char *filename, vm_offset_t dest,
}
int
-ofw_elf_exec(struct preloaded_file *fp)
+__elfN(ofw_exec)(struct preloaded_file *fp)
{
struct file_metadata *fmp;
vm_offset_t mdp;
@@ -83,6 +83,6 @@ ofw_elf_exec(struct preloaded_file *fp)
struct file_format ofw_elf =
{
- ofw_elf_loadfile,
- ofw_elf_exec
+ __elfN(ofw_loadfile),
+ __elfN(ofw_exec)
};