loader/multiboot: fix multiboot loading
The current multiboot loader code doesn't clean the metadata added to the kernel after the bi_load64 dry run, which breaks accounting of the required memory for the metadata. This issue didn't show itself before because all the metadata items where small (8bytes), but after r316343 there's a big blob in the metadata, which triggers this. Fix it by cleaning the metadata added to the kernel after the bi_load64 dry run. Also add a comment describing the memory layout when booting using multiboot (Xen Dom0). This unbreaks booting a FreeBSD/Xen Dom0 after r316343. MFC after: 3 weeks Sponsored by: Citrix Systems R&D
This commit is contained in:
parent
9f67a48145
commit
6696a07ed5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=316754
@ -228,6 +228,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
|
||||
|
@ -663,6 +663,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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user