svn commit: r294417 - in stable/10/sys/boot: common fdt forth i386/libi386 i386/loader
Roger Pau Monné
royger at FreeBSD.org
Wed Jan 20 13:23:05 UTC 2016
Author: royger
Date: Wed Jan 20 13:23:02 2016
New Revision: 294417
URL: https://svnweb.freebsd.org/changeset/base/294417
Log:
MFC r277215, r277291, r277418, r280953 and r280954:
loader: implement multiboot support for Xen Dom0
Note that only the subset of the multiboot specification needed in order to
boot a Xen Dom0 is implemented.
Sponsored by: Citrix Systems R&D
Added:
stable/10/sys/boot/i386/libi386/multiboot.c
- copied, changed from r277215, head/sys/boot/i386/libi386/multiboot.c
stable/10/sys/boot/i386/libi386/multiboot.h
- copied unchanged from r277215, head/sys/boot/i386/libi386/multiboot.h
stable/10/sys/boot/i386/libi386/multiboot_tramp.S
- copied unchanged from r277215, head/sys/boot/i386/libi386/multiboot_tramp.S
Modified:
stable/10/sys/boot/common/bootstrap.h
stable/10/sys/boot/common/load_elf.c
stable/10/sys/boot/common/load_elf_obj.c
stable/10/sys/boot/common/module.c
stable/10/sys/boot/fdt/fdt_loader_cmd.c
stable/10/sys/boot/forth/beastie.4th
stable/10/sys/boot/forth/loader.4th
stable/10/sys/boot/forth/support.4th
stable/10/sys/boot/i386/libi386/Makefile
stable/10/sys/boot/i386/libi386/bootinfo64.c
stable/10/sys/boot/i386/libi386/elf64_freebsd.c
stable/10/sys/boot/i386/libi386/libi386.h
stable/10/sys/boot/i386/loader/conf.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/boot/common/bootstrap.h
==============================================================================
--- stable/10/sys/boot/common/bootstrap.h Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/common/bootstrap.h Wed Jan 20 13:23:02 2016 (r294417)
@@ -231,9 +231,9 @@ int mod_load(char *name, struct mod_de
int mod_loadkld(const char *name, int argc, char *argv[]);
struct preloaded_file *file_alloc(void);
-struct preloaded_file *file_findfile(char *name, char *type);
+struct preloaded_file *file_findfile(const char *name, const char *type);
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
-struct preloaded_file *file_loadraw(char *name, char *type);
+struct preloaded_file *file_loadraw(char *name, char *type, int insert);
void file_discard(struct preloaded_file *fp);
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
int file_addmodule(struct preloaded_file *fp, char *modname, int version,
@@ -257,6 +257,9 @@ int __elfN(obj_loadfile)(char *filename,
int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
const void *reldata, int reltype, Elf_Addr relbase,
Elf_Addr dataaddr, void *data, size_t len);
+int __elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot);
+int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest);
#endif
/*
Modified: stable/10/sys/boot/common/load_elf.c
==============================================================================
--- stable/10/sys/boot/common/load_elf.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/common/load_elf.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -76,7 +76,8 @@ static int __elfN(loadimage)(struct prel
static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len);
-static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef);
+static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end);
static symaddr_fn __elfN(symaddr);
static char *fake_modname(const char *name);
@@ -85,6 +86,61 @@ const char *__elfN(moduletype) = "elf mo
u_int64_t __elfN(relocation_offset) = 0;
+static int
+__elfN(load_elf_header)(char *filename, elf_file_t ef)
+{
+ ssize_t bytes_read;
+ Elf_Ehdr *ehdr;
+ int err;
+
+ /*
+ * Open the image, read and validate the ELF header
+ */
+ if (filename == NULL) /* can't handle nameless */
+ return (EFTYPE);
+ if ((ef->fd = open(filename, O_RDONLY)) == -1)
+ return (errno);
+ ef->firstpage = malloc(PAGE_SIZE);
+ if (ef->firstpage == NULL) {
+ close(ef->fd);
+ return (ENOMEM);
+ }
+ bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE);
+ ef->firstlen = (size_t)bytes_read;
+ if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
+ err = EFTYPE; /* could be EIO, but may be small file */
+ goto error;
+ }
+ ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage;
+
+ /* Is it ELF? */
+ if (!IS_ELF(*ehdr)) {
+ err = EFTYPE;
+ goto error;
+ }
+ if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
+ ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
+ ehdr->e_version != EV_CURRENT ||
+ ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
+ err = EFTYPE;
+ goto error;
+ }
+
+ return (0);
+
+error:
+ if (ef->firstpage != NULL) {
+ free(ef->firstpage);
+ ef->firstpage = NULL;
+ }
+ if (ef->fd != -1) {
+ close(ef->fd);
+ ef->fd = -1;
+ }
+ return (err);
+}
+
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
* (dest), and a pointer to a module structure describing the loaded object
@@ -93,54 +149,32 @@ u_int64_t __elfN(relocation_offset) = 0;
int
__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
{
+ return (__elfN(loadfile_raw)(filename, dest, result, 0));
+}
+
+int
+__elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot)
+{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
Elf_Ehdr *ehdr;
int err;
- ssize_t bytes_read;
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
- /*
- * Open the image, read and validate the ELF header
- */
- if (filename == NULL) /* can't handle nameless */
- return(EFTYPE);
- if ((ef.fd = open(filename, O_RDONLY)) == -1)
- return(errno);
- ef.firstpage = malloc(PAGE_SIZE);
- if (ef.firstpage == NULL) {
- close(ef.fd);
- return(ENOMEM);
- }
- bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE);
- ef.firstlen = (size_t)bytes_read;
- if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) {
- err = EFTYPE; /* could be EIO, but may be small file */
- goto oerr;
- }
- ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage;
-
- /* Is it ELF? */
- if (!IS_ELF(*ehdr)) {
- err = EFTYPE;
- goto oerr;
- }
- if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
- ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
- ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
- ehdr->e_version != EV_CURRENT ||
- ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
- err = EFTYPE;
- goto oerr;
- }
+ err = __elfN(load_elf_header)(filename, &ef);
+ if (err != 0)
+ return (err);
+ ehdr = ef.ehdr;
/*
* Check to see what sort of module we are.
*/
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(kerneltype));
#ifdef __powerpc__
/*
* Kernels can be ET_DYN, so just assume the first loaded object is the
@@ -177,6 +211,11 @@ __elfN(loadfile)(char *filename, u_int64
} else if (ehdr->e_type == ET_DYN) {
/* Looks like a kld module */
+ if (multiboot != 0) {
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
+ err = EPERM;
+ goto oerr;
+ }
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
err = EPERM;
@@ -209,10 +248,14 @@ __elfN(loadfile)(char *filename, u_int64
err = EPERM;
goto out;
}
- if (ef.kernel)
+ if (ef.kernel == 1 && multiboot == 0)
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
- fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));
+ if (multiboot == 0)
+ fp->f_type = strdup(ef.kernel ?
+ __elfN(kerneltype) : __elfN(moduletype));
+ else
+ fp->f_type = strdup("elf multiboot kernel");
#ifdef ELF_VERBOSE
if (ef.kernel)
@@ -240,7 +283,8 @@ __elfN(loadfile)(char *filename, u_int64
out:
if (ef.firstpage)
free(ef.firstpage);
- close(ef.fd);
+ if (ef.fd != -1)
+ close(ef.fd);
return(err);
}
@@ -269,6 +313,8 @@ __elfN(loadimage)(struct preloaded_file
int symtabindex;
Elf_Size size;
u_int fpcopy;
+ Elf_Sym sym;
+ Elf_Addr p_start, p_end;
dp = NULL;
shdr = NULL;
@@ -571,7 +617,15 @@ nosyms:
COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
- if (__elfN(parse_modmetadata)(fp, ef) == 0)
+
+ if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
+ return 0;
+ p_start = sym.st_value + ef->off;
+ if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
+ return ENOENT;
+ p_end = sym.st_value + ef->off;
+
+ if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0)
goto out;
if (ef->kernel) /* kernel must not depend on anything */
@@ -634,7 +688,123 @@ struct mod_metadata32 {
#endif
int
-__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
+__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest)
+{
+ struct elf_file ef;
+ int err, i, j;
+ Elf_Shdr *sh_meta, *shdr = NULL;
+ Elf_Shdr *sh_data[2];
+ char *shstrtab = NULL;
+ size_t size;
+ Elf_Addr p_start, p_end;
+
+ bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
+
+ err = __elfN(load_elf_header)(fp->f_name, &ef);
+ if (err != 0)
+ goto out;
+
+ if (ef.ehdr->e_type == ET_EXEC) {
+ ef.kernel = 1;
+ } else if (ef.ehdr->e_type != ET_DYN) {
+ err = EFTYPE;
+ goto out;
+ }
+
+ size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize;
+ shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size);
+ if (shdr == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* Load shstrtab. */
+ shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset,
+ shdr[ef.ehdr->e_shstrndx].sh_size);
+ if (shstrtab == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load shstrtab\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Find set_modmetadata_set and data sections. */
+ sh_data[0] = sh_data[1] = sh_meta = NULL;
+ for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) {
+ if (strcmp(&shstrtab[shdr[i].sh_name],
+ "set_modmetadata_set") == 0) {
+ sh_meta = &shdr[i];
+ }
+ if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) ||
+ (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) {
+ sh_data[j++] = &shdr[i];
+ }
+ }
+ if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to find set_modmetadata_set or data sections\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Load set_modmetadata_set into memory */
+ err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
+ goto out;
+ }
+ p_start = dest;
+ p_end = dest + sh_meta->sh_size;
+ dest += sh_meta->sh_size;
+
+ /* Load data sections into memory. */
+ err = kern_pread(ef.fd, dest, sh_data[0]->sh_size,
+ sh_data[0]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ /*
+ * We have to increment the dest, so that the offset is the same into
+ * both the .rodata and .data sections.
+ */
+ ef.off = -(sh_data[0]->sh_addr - dest);
+ dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr);
+
+ err = kern_pread(ef.fd, dest, sh_data[1]->sh_size,
+ sh_data[1]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to parse metadata: %d\n", err);
+ goto out;
+ }
+
+out:
+ if (shstrtab != NULL)
+ free(shstrtab);
+ if (shdr != NULL)
+ free(shdr);
+ if (ef.firstpage != NULL)
+ free(ef.firstpage);
+ if (ef.fd != -1)
+ close(ef.fd);
+ return (err);
+}
+
+int
+__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end)
{
struct mod_metadata md;
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
@@ -644,20 +814,13 @@ __elfN(parse_modmetadata)(struct preload
#endif
struct mod_depend *mdepend;
struct mod_version mver;
- Elf_Sym sym;
char *s;
int error, modcnt, minfolen;
- Elf_Addr v, p, p_stop;
-
- if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
- return 0;
- p = sym.st_value + ef->off;
- if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
- return ENOENT;
- p_stop = sym.st_value + ef->off;
+ Elf_Addr v, p;
modcnt = 0;
- while (p < p_stop) {
+ p = p_start;
+ while (p < p_end) {
COPYOUT(p, &v, sizeof(v));
error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
if (error == EOPNOTSUPP)
Modified: stable/10/sys/boot/common/load_elf_obj.c
==============================================================================
--- stable/10/sys/boot/common/load_elf_obj.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/common/load_elf_obj.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -129,20 +129,13 @@ __elfN(obj_loadfile)(char *filename, u_i
goto oerr;
}
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(obj_kerneltype));
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
- if (strcmp(__elfN(obj_kerneltype), kfp->f_type)) {
- printf("elf" __XSTRING(__ELF_WORD_SIZE)
- "_obj_loadfile: can't load module with kernel type '%s'\n",
- kfp->f_type);
- err = EPERM;
- goto oerr;
- }
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
Modified: stable/10/sys/boot/common/module.c
==============================================================================
--- stable/10/sys/boot/common/module.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/common/module.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -138,7 +138,7 @@ command_load(int argc, char *argv[])
command_errmsg = "invalid load type";
return(CMD_ERROR);
}
- return(file_loadraw(argv[1], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR);
}
/*
* Do we have explicit KLD load ?
@@ -193,7 +193,7 @@ command_load_geli(int argc, char *argv[]
argv += (optind - 1);
argc -= (optind - 1);
sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
- return(file_loadraw(argv[2], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
}
COMMAND_SET(unload, "unload", "unload all modules", command_unload);
@@ -362,7 +362,7 @@ file_load_dependencies(struct preloaded_
* no arguments or anything.
*/
struct preloaded_file *
-file_loadraw(char *name, char *type)
+file_loadraw(char *name, char *type, int insert)
{
struct preloaded_file *fp;
char *cp;
@@ -421,7 +421,8 @@ file_loadraw(char *name, char *type)
loadaddr = laddr;
/* Add to the list of loaded files */
- file_insert_tail(fp);
+ if (insert != 0)
+ file_insert_tail(fp);
close(fd);
return(fp);
}
@@ -524,7 +525,7 @@ mod_loadkld(const char *kldname, int arg
* NULL may be passed as a wildcard to either.
*/
struct preloaded_file *
-file_findfile(char *name, char *type)
+file_findfile(const char *name, const char *type)
{
struct preloaded_file *fp;
Modified: stable/10/sys/boot/fdt/fdt_loader_cmd.c
==============================================================================
--- stable/10/sys/boot/fdt/fdt_loader_cmd.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/fdt/fdt_loader_cmd.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -261,7 +261,7 @@ fdt_load_dtb_file(const char * filename)
oldbfp = file_findfile(NULL, "dtb");
/* Attempt to load and validate a new dtb from a file. */
- if ((bfp = file_loadraw(filename, "dtb")) == NULL) {
+ if ((bfp = file_loadraw(filename, "dtb", 1)) == NULL) {
sprintf(command_errbuf, "failed to load file '%s'", filename);
return (1);
}
Modified: stable/10/sys/boot/forth/beastie.4th
==============================================================================
--- stable/10/sys/boot/forth/beastie.4th Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/forth/beastie.4th Wed Jan 20 13:23:02 2016 (r294417)
@@ -93,6 +93,7 @@ also support-functions
s" beastie_disable" getenv dup -1 <> if
s" YES" compare-insensitive 0= if
any_conf_read? if
+ load_xen_throw
load_kernel
load_modules
then
Modified: stable/10/sys/boot/forth/loader.4th
==============================================================================
--- stable/10/sys/boot/forth/loader.4th Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/forth/loader.4th Wed Jan 20 13:23:02 2016 (r294417)
@@ -147,13 +147,14 @@ only forth definitions also support-func
\ was succesfully loaded!
any_conf_read? if
s" loader_delay" getenv -1 = if
+ load_xen_throw
load_kernel
load_modules
else
drop
." Loading Kernel and Modules (Ctrl-C to Abort)" cr
s" also support-functions" evaluate
- s" set delay_command='load_kernel load_modules'" evaluate
+ s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate
s" set delay_showdots" evaluate
delay_execute
then
Modified: stable/10/sys/boot/forth/support.4th
==============================================================================
--- stable/10/sys/boot/forth/support.4th Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/forth/support.4th Wed Jan 20 13:23:02 2016 (r294417)
@@ -1460,6 +1460,20 @@ also builtins
abort" Unable to load a kernel!"
;
+: load_xen ( -- )
+ s" xen_kernel" getenv dup -1 <> if
+ 1 1 load
+ else
+ drop
+ 0
+ then
+;
+
+: load_xen_throw ( -- ) ( throws: abort )
+ load_xen
+ abort" Unable to load Xen!"
+;
+
: set_defaultoptions ( -- )
s" kernel_options" getenv dup -1 = if
drop
@@ -1578,12 +1592,15 @@ also builtins
else
drop
then
- r> if ( a path was passed )
- load_directory_or_file
- else
- standard_kernel_search
+ load_xen
+ ?dup 0= if ( success )
+ r> if ( a path was passed )
+ load_directory_or_file
+ else
+ standard_kernel_search
+ then
+ ?dup 0= if ['] load_modules catch then
then
- ?dup 0= if ['] load_modules catch then
;
only forth definitions
Modified: stable/10/sys/boot/i386/libi386/Makefile
==============================================================================
--- stable/10/sys/boot/i386/libi386/Makefile Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/i386/libi386/Makefile Wed Jan 20 13:23:02 2016 (r294417)
@@ -6,7 +6,7 @@ INTERNALLIB=
SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
comconsole.c devicename.c elf32_freebsd.c \
- elf64_freebsd.c \
+ elf64_freebsd.c multiboot.c multiboot_tramp.S \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c
.PATH: ${.CURDIR}/../../zfs
@@ -65,6 +65,7 @@ machine:
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS}
+CFLAGS.multiboot_tramp.S= ${CLANG_NO_IAS}
CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
.if ${MACHINE_CPUARCH} == "amd64"
Modified: stable/10/sys/boot/i386/libi386/bootinfo64.c
==============================================================================
--- stable/10/sys/boot/i386/libi386/bootinfo64.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/i386/libi386/bootinfo64.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
+#include <machine/metadata.h>
#include <machine/psl.h>
#include <machine/specialreg.h>
#include "bootstrap.h"
@@ -176,14 +177,15 @@ bi_checkcpu(void)
* - Module metadata are formatted and placed in kernel space.
*/
int
-bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
+bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernendp, int add_smap)
{
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;
+ u_int64_t module;
vm_offset_t size;
char *rootdevname;
int howto;
@@ -210,21 +212,18 @@ bi_load64(char *args, vm_offset_t *modul
/* Try reading the /etc/fstab file to select the root device */
getrootmount(i386_fmtdev((void *)rootdev));
- /* 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;
+ if (addr == 0) {
+ /* find the last module in the chain */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ if (addr < (xp->f_addr + xp->f_size))
+ addr = xp->f_addr + xp->f_size;
+ }
}
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
- /* copy our environment */
- envp = addr;
- addr = bi_copyenv(addr);
-
- /* pad to a page boundary */
- addr = roundup(addr, PAGE_SIZE);
+ /* place the metadata before anything */
+ module = *modulep = addr;
kfp = file_findfile(NULL, "elf kernel");
if (kfp == NULL)
@@ -235,20 +234,30 @@ bi_load64(char *args, vm_offset_t *modul
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);
+ file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof module, &module);
+ if (add_smap != 0)
+ bios_addsmapdata(kfp);
- /* Figure out the size and location of the metadata */
- *modulep = addr;
size = bi_copymodules64(0);
- kernend = roundup(addr + size, PAGE_SIZE);
+
+ /* copy our environment */
+ envp = roundup(addr + size, PAGE_SIZE);
+ addr = bi_copyenv(envp);
+
+ /* set kernend */
+ kernend = roundup(addr, PAGE_SIZE);
*kernendp = kernend;
/* patch MODINFOMD_KERNEND */
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
+ /* patch MODINFOMD_ENVP */
+ md = file_findmetadata(kfp, MODINFOMD_ENVP);
+ bcopy(&envp, md->md_data, sizeof envp);
+
/* copy module list and metadata */
- (void)bi_copymodules64(addr);
+ (void)bi_copymodules64(*modulep);
return(0);
}
Modified: stable/10/sys/boot/i386/libi386/elf64_freebsd.c
==============================================================================
--- stable/10/sys/boot/i386/libi386/elf64_freebsd.c Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/i386/libi386/elf64_freebsd.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -81,7 +81,7 @@ elf64_exec(struct preloaded_file *fp)
return(EFTYPE);
ehdr = (Elf_Ehdr *)&(md->md_data);
- err = bi_load64(fp->f_args, &modulep, &kernend);
+ err = bi_load64(fp->f_args, 0, &modulep, &kernend, 1);
if (err != 0)
return(err);
Modified: stable/10/sys/boot/i386/libi386/libi386.h
==============================================================================
--- stable/10/sys/boot/i386/libi386/libi386.h Wed Jan 20 13:14:36 2016 (r294416)
+++ stable/10/sys/boot/i386/libi386/libi386.h Wed Jan 20 13:23:02 2016 (r294417)
@@ -117,6 +117,7 @@ void bi_setboothowto(int howto);
vm_offset_t bi_copyenv(vm_offset_t addr);
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);
+int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernend, int add_smap);
void pxe_enable(void *pxeinfo);
Copied and modified: stable/10/sys/boot/i386/libi386/multiboot.c (from r277215, head/sys/boot/i386/libi386/multiboot.c)
==============================================================================
--- head/sys/boot/i386/libi386/multiboot.c Thu Jan 15 16:27:20 2015 (r277215, copy source)
+++ stable/10/sys/boot/i386/libi386/multiboot.c Wed Jan 20 13:23:02 2016 (r294417)
@@ -243,7 +243,7 @@ multiboot_exec(struct preloaded_file *fp
/* Find the entry point of the Xen kernel and save it for later */
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
printf("Unable to find %s entry point\n", fp->f_name);
- error = EFTYPE;
+ error = EINVAL;
goto error;
}
ehdr = (Elf_Ehdr *)&(md->md_data);
@@ -271,10 +271,17 @@ multiboot_exec(struct preloaded_file *fp
fp = file_findfile(NULL, "elf kernel");
if (fp == NULL) {
printf("No FreeBSD kernel provided, aborting\n");
- error = EFTYPE;
+ error = EINVAL;
goto error;
}
+
mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
+ if (mb_mod == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+
+ bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);
/*
* Calculate how much memory is needed for the metatdata. We did
@@ -373,7 +380,7 @@ multiboot_obj_loadfile(char *filename, u
printf(
"Unable to load %s as a multiboot payload kernel\n",
filename);
- return (EFTYPE);
+ return (EINVAL);
}
/* Load kernel metadata... */
@@ -382,7 +389,7 @@ multiboot_obj_loadfile(char *filename, u
if (error) {
printf("Unable to load kernel %s metadata error: %d\n",
rfp->f_name, error);
- return (EFTYPE);
+ return (EINVAL);
}
/*
Copied: stable/10/sys/boot/i386/libi386/multiboot.h (from r277215, head/sys/boot/i386/libi386/multiboot.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/boot/i386/libi386/multiboot.h Wed Jan 20 13:23:02 2016 (r294417, copy of r277215, head/sys/boot/i386/libi386/multiboot.h)
@@ -0,0 +1,225 @@
+/* multiboot.h - Multiboot header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to
+* deal in the Software without restriction, including without limitation the
+* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+* sell copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+* $FreeBSD$
+*/
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 8192
+
+/* The magic field should contain this. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* This should be in %eax. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The bits in the required part of flags field we don't support. */
+#define MULTIBOOT_UNSUPPORTED 0x0000fffc
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000004
+
+/* Flags set in the 'flags' member of the multiboot header. */
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+
+/* Flags to be set in the 'flags' member of the multiboot info structure. */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+
+#ifndef ASM_FILE
+
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+/* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+/* Feature flags. */
+ multiboot_uint32_t flags;
+
+/* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+
+/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+ multiboot_uint32_t entry_addr;
+
+/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ multiboot_uint32_t mode_type;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table
+{
+ multiboot_uint32_t tabsize;
+ multiboot_uint32_t strsize;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t reserved;
+};
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table
+{
+ multiboot_uint32_t num;
+ multiboot_uint32_t size;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t shndx;
+};
+typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+
+struct multiboot_info
+{
+/* Multiboot info version number */
+ multiboot_uint32_t flags;
+
+/* Available memory from BIOS */
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+
+/* "root" partition */
+ multiboot_uint32_t boot_device;
+
+/* Kernel command line */
+ multiboot_uint32_t cmdline;
+
+/* Boot-Module list */
+ multiboot_uint32_t mods_count;
+ multiboot_uint32_t mods_addr;
+
+ union
+ {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+
+/* Memory Mapping buffer */
+ multiboot_uint32_t mmap_length;
+ multiboot_uint32_t mmap_addr;
+
+/* Drive Info buffer */
+ multiboot_uint32_t drives_length;
+ multiboot_uint32_t drives_addr;
+
+/* ROM configuration table */
+ multiboot_uint32_t config_table;
+
+/* Boot Loader Name */
+ multiboot_uint32_t boot_loader_name;
+
+/* APM table */
+ multiboot_uint32_t apm_table;
+
+/* Video */
+ multiboot_uint32_t vbe_control_info;
+ multiboot_uint32_t vbe_mode_info;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+};
+typedef struct multiboot_info multiboot_info_t;
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint32_t size;
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+ multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_mod_list
+{
+/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+
+/* Module command line */
+ multiboot_uint32_t cmdline;
+
+/* padding to take it to 16 bytes (must be zero) */
+ multiboot_uint32_t pad;
+};
+typedef struct multiboot_mod_list multiboot_module_t;
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
Copied: stable/10/sys/boot/i386/libi386/multiboot_tramp.S (from r277215, head/sys/boot/i386/libi386/multiboot_tramp.S)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/boot/i386/libi386/multiboot_tramp.S Wed Jan 20 13:23:02 2016 (r294417, copy of r277215, head/sys/boot/i386/libi386/multiboot_tramp.S)
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2014 Roger Pau Monné <royger at 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$
+ */
+
+#define ASM_FILE
+#include "multiboot.h"
+
+/*
+ * The multiboot specification requires the executable to be launched
+ * with %cs set to a flat read/execute segment with offset 0 and limit
+ * 0xFFFFFFFF, and the rest of the segment registers (%ds, %es, %fs,
+ * %gs, %ss) to flat read/write segments with the same offset and limit.
+ * This is already done by the BTX code before calling multiboot_tramp,
+ * so there is no need to do anything here.
+ */
+
+ .globl multiboot_tramp
+multiboot_tramp:
+ /* Be sure that interrupts are disabled. */
+ cli
+
+ movl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+ /* Get the entry point and address of the multiboot_info parameter. */
+ movl 8(%esp), %ebx
+ movl 4(%esp), %ecx
+
+ call *%ecx
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-10
mailing list