From 7b8d48197b82b9a27c61d7d4c6f02f00a08fef2d Mon Sep 17 00:00:00 2001 From: "Joshua M. Clulow" Date: Sat, 1 May 2021 15:33:25 -0700 Subject: [PATCH] [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. --- src/arch/x86/image/multiboot.c | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/arch/x86/image/multiboot.c b/src/arch/x86/image/multiboot.c index 0c85df708..59ef0ca4f 100644 --- a/src/arch/x86/image/multiboot.c +++ b/src/arch/x86/image/multiboot.c @@ -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; }