summaryrefslogtreecommitdiffstats
path: root/sys/boot/i386
diff options
context:
space:
mode:
authorroyger <royger@FreeBSD.org>2017-05-09 09:53:18 +0000
committerroyger <royger@FreeBSD.org>2017-05-09 09:53:18 +0000
commitf20a7aeef0f6912c9d47d5ceb488ff7b745c5369 (patch)
treec81475e713b208d6570fe587744b6141305847c8 /sys/boot/i386
parente776c54686e61cb89b170e3ec621f197edd73050 (diff)
downloadFreeBSD-src-f20a7aeef0f6912c9d47d5ceb488ff7b745c5369.zip
FreeBSD-src-f20a7aeef0f6912c9d47d5ceb488ff7b745c5369.tar.gz
MFC r316754: loader/multiboot: fix multiboot loading
Sponsored by: Citrix Systems R&D
Diffstat (limited to 'sys/boot/i386')
-rw-r--r--sys/boot/i386/libi386/multiboot.c42
1 files changed, 42 insertions, 0 deletions
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.
OpenPOWER on IntegriCloud