diff options
author | royger <royger@FreeBSD.org> | 2017-05-09 09:53:18 +0000 |
---|---|---|
committer | royger <royger@FreeBSD.org> | 2017-05-09 09:53:18 +0000 |
commit | f20a7aeef0f6912c9d47d5ceb488ff7b745c5369 (patch) | |
tree | c81475e713b208d6570fe587744b6141305847c8 | |
parent | e776c54686e61cb89b170e3ec621f197edd73050 (diff) | |
download | FreeBSD-src-f20a7aeef0f6912c9d47d5ceb488ff7b745c5369.zip FreeBSD-src-f20a7aeef0f6912c9d47d5ceb488ff7b745c5369.tar.gz |
MFC r316754: loader/multiboot: fix multiboot loading
Sponsored by: Citrix Systems R&D
-rw-r--r-- | sys/boot/common/bootstrap.h | 1 | ||||
-rw-r--r-- | sys/boot/common/module.c | 16 | ||||
-rw-r--r-- | sys/boot/i386/libi386/multiboot.c | 42 |
3 files changed, 59 insertions, 0 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 472fc3e..a4c8939 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -229,6 +229,7 @@ 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, struct kernel_module **newmp); +void file_removemetadata(struct preloaded_file *fp); /* MI module loaders */ #ifdef __elfN diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 15c4807..e96aabb 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -642,6 +642,22 @@ file_findmetadata(struct preloaded_file *fp, int type) return(md); } +/* + * Remove all metadata from the file. + */ +void +file_removemetadata(struct preloaded_file *fp) +{ + struct file_metadata *md, *next; + + for (md = fp->f_metadata; md != NULL; md = next) + { + next = md->md_next; + free(md); + } + fp->f_metadata = NULL; +} + struct file_metadata * metadata_next(struct file_metadata *md, int type) { diff --git a/sys/boot/i386/libi386/multiboot.c b/sys/boot/i386/libi386/multiboot.c index 00e36f2..9aac640 100644 --- a/sys/boot/i386/libi386/multiboot.c +++ b/sys/boot/i386/libi386/multiboot.c @@ -267,7 +267,39 @@ multiboot_exec(struct preloaded_file *fp) * information is placed at the start of the second module and * the original modulep value is saved together with the other * metadata, so we can relocate everything. + * + * Native layout: + * fp->f_addr + fp->f_size + * +---------+----------------+------------+ + * | | | | + * | Kernel | Modules | Metadata | + * | | | | + * +---------+----------------+------------+ + * fp->f_addr modulep kernend + * + * Xen layout: + * + * Initial: + * fp->f_addr + fp->f_size + * +---------+----------+----------------+------------+ + * | | | | | + * | Kernel | Reserved | Modules | Metadata | + * | | | | dry run | + * +---------+----------+----------------+------------+ + * fp->f_addr + * + * After metadata polacement (ie: final): + * fp->f_addr + fp->f_size + * +-----------+---------+----------+----------------+ + * | | | | | + * | Kernel | Free | Metadata | Modules | + * | | | | | + * +-----------+---------+----------+----------------+ + * fp->f_addr modulep kernend + * \__________/ \__________________________/ + * Multiboot module 0 Multiboot module 1 */ + fp = file_findfile(NULL, "elf kernel"); if (fp == NULL) { printf("No FreeBSD kernel provided, aborting\n"); @@ -275,6 +307,13 @@ multiboot_exec(struct preloaded_file *fp) goto error; } + if (fp->f_metadata != NULL) { + printf("FreeBSD kernel already contains metadata, aborting\n"); + error = EINVAL; + goto error; + } + + mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES); if (mb_mod == NULL) { error = ENOMEM; @@ -312,6 +351,9 @@ multiboot_exec(struct preloaded_file *fp) goto error; } + /* Clean the metadata added to the kernel in the bi_load64 dry run */ + file_removemetadata(fp); + /* * This is the position where the second multiboot module * will be placed. |