From 0f29e0e46e1ccdc7000805ca0ea38e603f248462 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 12 Jan 2007 12:03:19 +0000 Subject: [PATCH] Ensure multiboot modules are in ascending order of memory start address, to work around OS bugs. --- src/arch/i386/image/multiboot.c | 53 ++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index 2411aec4..25f5d2b0 100644 --- a/src/arch/i386/image/multiboot.c +++ b/src/arch/i386/image/multiboot.c @@ -106,28 +106,53 @@ multiboot_build_module_list ( struct image *image, struct image *module_image; struct multiboot_module *module; unsigned int count = 0; + unsigned int insert; + physaddr_t start; + physaddr_t end; + unsigned int i; + /* Add each image as a multiboot module */ for_each_image ( module_image ) { /* Do not include kernel image itself as a module */ if ( module_image == image ) continue; - module = &modules[count++]; - /* Populate module data structure, if applicable */ - if ( ! modules ) - continue; - module->mod_start = user_to_phys ( module_image->data, 0 ); - module->mod_end = user_to_phys ( module_image->data, - module_image->len ); - module->string = virt_to_phys ( module_image->cmdline ); - module->reserved = 0; - DBG ( "Multiboot module %lx is [%lx,%lx)\n", - virt_to_phys ( module ), - module->mod_start, module->mod_end ); + /* If we don't have a data structure to populate, just count */ + if ( modules ) { + + /* At least some OSes expect the multiboot + * modules to be in ascending order, so we + * have to support it. + */ + start = user_to_phys ( module_image->data, 0 ); + end = user_to_phys ( module_image->data, + module_image->len ); + for ( insert = 0 ; insert < count ; insert++ ) { + if ( start < modules[insert].mod_start ) + break; + } + module = &modules[insert]; + memmove ( ( module + 1 ), module, + ( ( count - insert ) * sizeof ( *module ) )); + module->mod_start = start; + module->mod_end = end; + module->string = virt_to_phys ( module_image->cmdline); + module->reserved = 0; + + /* We promise to page-align modules */ + assert ( ( module->mod_start & 0xfff ) == 0 ); + } - /* We promise to page-align modules, so at least check */ - assert ( ( module->mod_start & 0xfff ) == 0 ); + count++; + } + + /* Dump module configuration */ + if ( modules ) { + for ( i = 0 ; i < count ; i++ ) { + DBG ( "Multiboot module %d is [%lx,%lx)\n", i, + modules[i].mod_start, modules[i].mod_end ); + } } return count;