Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Jan 2016 13:23:02 +0000 (UTC)
From:      =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r294417 - in stable/10/sys/boot: common fdt forth i386/libi386 i386/loader
Message-ID:  <201601201323.u0KDN2s0057920@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601201323.u0KDN2s0057920>