[multiboot] try other regions for large modules

Multiboot modules are placed immediately after the primary executable
image.  If the memory region where the executable is placed is not very
large, modules may not fit in that region.  Try skipping over holes to
see if the module will fit in a subsequent region.
pull/350/head
Joshua M. Clulow 2021-05-01 15:33:25 -07:00
parent 3efdbef2f0
commit 7b8d48197b
1 changed files with 38 additions and 0 deletions

View File

@ -178,6 +178,36 @@ static physaddr_t multiboot_add_cmdline ( struct image *image ) {
return virt_to_phys ( mb_cmdline );
}
static int multiboot_find_new_start ( struct image *image, physaddr_t *start ) {
struct memory_map memmap;
unsigned int i;
unsigned int current;
get_memmap ( &memmap );
/* Find the current region: */
for ( i = 0 ; i < memmap.count ; i++ ) {
if ( *start >= memmap.regions[i].start &&
*start < memmap.regions[i].end ) {
current = i;
goto found;
}
}
DBGC ( image, "MULTIBOOT could not find region for %lx\n", *start);
return -ENOENT;
found:
if ( current + 1 < memmap.count ) {
*start = memmap.regions[current + 1].start;
DBGC ( image, "MULTIBOOT skipping ahead to %lx\n", *start);
return 0;
}
DBGC ( image, "MULTIBOOT no more regions to try" );
return -ENOMEM;
}
/**
* Add multiboot modules
*
@ -208,6 +238,7 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
if ( module_image == image )
continue;
again:
/* Page-align the module */
start = ( ( start + 0xfff ) & ~0xfff );
@ -218,6 +249,13 @@ static int multiboot_add_modules ( struct image *image, physaddr_t start,
DBGC ( image, "MULTIBOOT %p could not prepare module "
"%s: %s\n", image, module_image->name,
strerror ( rc ) );
DBGC ( image, "MULTIBOOT trying to find another "
"memory region\n" );
if ( multiboot_find_new_start ( image, &start ) == 0 ) {
goto again;
}
return rc;
}