diff options
| author | Michael Brown | 2007-01-12 13:03:19 +0100 |
|---|---|---|
| committer | Michael Brown | 2007-01-12 13:03:19 +0100 |
| commit | 0f29e0e46e1ccdc7000805ca0ea38e603f248462 (patch) | |
| tree | dca1c70ae17055c3fa0132f3ec1991619e85dfef /src | |
| parent | Fix the memory map. (diff) | |
| download | ipxe-0f29e0e46e1ccdc7000805ca0ea38e603f248462.tar.gz ipxe-0f29e0e46e1ccdc7000805ca0ea38e603f248462.tar.xz ipxe-0f29e0e46e1ccdc7000805ca0ea38e603f248462.zip | |
Ensure multiboot modules are in ascending order of memory start
address, to work around OS bugs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/i386/image/multiboot.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index 2411aec43..25f5d2b07 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 ); - - /* We promise to page-align modules, so at least check */ - assert ( ( module->mod_start & 0xfff ) == 0 ); + /* 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 ); + } + + 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; |
