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é <roy...@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 ***
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to