mirror of https://github.com/ipxe/ipxe.git
Place multiboot tables in base memory; at least some OSes won't see it
if we don't.pull/1/head
parent
5c72d9c4e0
commit
bcd6ca3291
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <alloca.h>
|
#include <realmode.h>
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
#include <gpxe/uaccess.h>
|
#include <gpxe/uaccess.h>
|
||||||
#include <gpxe/image.h>
|
#include <gpxe/image.h>
|
||||||
|
@ -35,6 +35,18 @@
|
||||||
|
|
||||||
struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT );
|
struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of modules we will allow for
|
||||||
|
*
|
||||||
|
* If this has bitten you: sorry. I did have a perfect scheme with a
|
||||||
|
* dynamically allocated list of modules on the protected-mode stack,
|
||||||
|
* but it was incompatible with some broken OSes that can only access
|
||||||
|
* low memory at boot time (even though we kindly set up 4GB flat
|
||||||
|
* physical addressing as per the multiboot specification.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define MAX_MODULES 8
|
||||||
|
|
||||||
/** Multiboot flags that we support */
|
/** Multiboot flags that we support */
|
||||||
#define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
|
#define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
|
||||||
MB_FLAG_VIDMODE | MB_FLAG_RAW )
|
MB_FLAG_VIDMODE | MB_FLAG_RAW )
|
||||||
|
@ -66,9 +78,11 @@ struct multiboot_header_info {
|
||||||
*
|
*
|
||||||
* @v mbinfo Multiboot information structure
|
* @v mbinfo Multiboot information structure
|
||||||
* @v mbmemmap Multiboot memory map
|
* @v mbmemmap Multiboot memory map
|
||||||
|
* @v limit Maxmimum number of memory map entries
|
||||||
*/
|
*/
|
||||||
static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
|
static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
|
||||||
struct multiboot_memory_map *mbmemmap ) {
|
struct multiboot_memory_map *mbmemmap,
|
||||||
|
unsigned int limit ) {
|
||||||
struct memory_map memmap;
|
struct memory_map memmap;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
@ -78,6 +92,11 @@ static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
|
||||||
/* Translate into multiboot format */
|
/* Translate into multiboot format */
|
||||||
memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
|
memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
|
||||||
for ( i = 0 ; i < memmap.count ; i++ ) {
|
for ( i = 0 ; i < memmap.count ; i++ ) {
|
||||||
|
if ( i >= limit ) {
|
||||||
|
DBG ( "Multiboot limit of %d memmap entries reached\n",
|
||||||
|
limit );
|
||||||
|
break;
|
||||||
|
}
|
||||||
mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
|
mbmemmap[i].size = ( sizeof ( mbmemmap[i] ) -
|
||||||
sizeof ( mbmemmap[i].size ) );
|
sizeof ( mbmemmap[i].size ) );
|
||||||
mbmemmap[i].base_addr = memmap.regions[i].start;
|
mbmemmap[i].base_addr = memmap.regions[i].start;
|
||||||
|
@ -102,7 +121,8 @@ static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
|
||||||
*/
|
*/
|
||||||
static unsigned int
|
static unsigned int
|
||||||
multiboot_build_module_list ( struct image *image,
|
multiboot_build_module_list ( struct image *image,
|
||||||
struct multiboot_module *modules ) {
|
struct multiboot_module *modules,
|
||||||
|
unsigned int limit ) {
|
||||||
struct image *module_image;
|
struct image *module_image;
|
||||||
struct multiboot_module *module;
|
struct multiboot_module *module;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
@ -114,6 +134,12 @@ multiboot_build_module_list ( struct image *image,
|
||||||
/* Add each image as a multiboot module */
|
/* Add each image as a multiboot module */
|
||||||
for_each_image ( module_image ) {
|
for_each_image ( module_image ) {
|
||||||
|
|
||||||
|
if ( count >= limit ) {
|
||||||
|
DBG ( "Multiboot limit of %d modules reached\n",
|
||||||
|
limit );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do not include kernel image itself as a module */
|
/* Do not include kernel image itself as a module */
|
||||||
if ( module_image == image )
|
if ( module_image == image )
|
||||||
continue;
|
continue;
|
||||||
|
@ -158,6 +184,29 @@ multiboot_build_module_list ( struct image *image,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multiboot information structure
|
||||||
|
*
|
||||||
|
* Kept in base memory because some OSes won't find it elsewhere,
|
||||||
|
* along with the other structures belonging to the Multiboot
|
||||||
|
* information table.
|
||||||
|
*/
|
||||||
|
static struct multiboot_info __data16 ( mbinfo );
|
||||||
|
#define mbinfo __use_data16 ( mbinfo )
|
||||||
|
|
||||||
|
/** The multiboot bootloader name */
|
||||||
|
static const char * __data16 ( mb_bootloader_name ) = "gPXE " VERSION;
|
||||||
|
#define mb_bootloader_name __use_data16 ( mb_bootloader_name )
|
||||||
|
|
||||||
|
/** The multiboot memory map */
|
||||||
|
static struct multiboot_memory_map
|
||||||
|
__data16_array ( mbmemmap, [MAX_MEMORY_REGIONS] );
|
||||||
|
#define mbmemmap __use_data16 ( mbmemmap )
|
||||||
|
|
||||||
|
/** The multiboot module list */
|
||||||
|
static struct multiboot_module __data16_array ( mbmodules, [MAX_MODULES] );
|
||||||
|
#define mbmodules __use_data16 ( mbmodules )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute multiboot image
|
* Execute multiboot image
|
||||||
*
|
*
|
||||||
|
@ -165,45 +214,26 @@ multiboot_build_module_list ( struct image *image,
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int multiboot_exec ( struct image *image ) {
|
static int multiboot_exec ( struct image *image ) {
|
||||||
static const char *bootloader_name = "gPXE " VERSION;
|
|
||||||
struct multiboot_info mbinfo;
|
|
||||||
struct multiboot_memory_map mbmemmap[MAX_MEMORY_REGIONS];
|
|
||||||
struct multiboot_module *modules;
|
|
||||||
unsigned int num_modules;
|
|
||||||
|
|
||||||
/* Populate multiboot information structure */
|
/* Populate multiboot information structure */
|
||||||
memset ( &mbinfo, 0, sizeof ( mbinfo ) );
|
memset ( &mbinfo, 0, sizeof ( mbinfo ) );
|
||||||
|
mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
|
||||||
/* Set boot loader name */
|
MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
|
||||||
mbinfo.boot_loader_name = virt_to_phys ( bootloader_name );
|
multiboot_build_memmap ( &mbinfo, mbmemmap,
|
||||||
mbinfo.flags |= MBI_FLAG_LOADER;
|
( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
|
||||||
|
|
||||||
/* Build memory map */
|
|
||||||
multiboot_build_memmap ( &mbinfo, mbmemmap );
|
|
||||||
mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
|
|
||||||
mbinfo.flags |= ( MBI_FLAG_MEM | MBI_FLAG_MMAP );
|
|
||||||
|
|
||||||
/* Set command line */
|
|
||||||
mbinfo.cmdline = virt_to_phys ( image->cmdline );
|
mbinfo.cmdline = virt_to_phys ( image->cmdline );
|
||||||
mbinfo.flags |= MBI_FLAG_CMDLINE;
|
mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
|
||||||
|
( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
|
||||||
/* Construct module list */
|
mbinfo.mods_addr = virt_to_phys ( mbmodules );
|
||||||
num_modules = multiboot_build_module_list ( image, NULL );
|
mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
|
||||||
modules = alloca ( num_modules * sizeof ( *modules ) );
|
mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
|
||||||
multiboot_build_module_list ( image, modules );
|
|
||||||
mbinfo.mods_count = num_modules;
|
|
||||||
mbinfo.mods_addr = virt_to_phys ( modules );
|
|
||||||
mbinfo.flags |= MBI_FLAG_MODS;
|
|
||||||
|
|
||||||
/* Jump to OS with flat physical addressing */
|
/* Jump to OS with flat physical addressing */
|
||||||
__asm__ __volatile__ ( PHYS_CODE ( /* Preserve %ebp for alloca() */
|
__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
|
||||||
"pushl %%ebp\n\t"
|
|
||||||
"call *%%edi\n\t"
|
|
||||||
"popl %%ebp\n\t" )
|
|
||||||
: : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
|
: : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
|
||||||
"b" ( virt_to_phys ( &mbinfo ) ),
|
"b" ( virt_to_phys ( &mbinfo ) ),
|
||||||
"D" ( image->entry )
|
"D" ( image->entry )
|
||||||
: "ecx", "edx", "esi", "memory" );
|
: "ecx", "edx", "esi", "ebp", "memory" );
|
||||||
|
|
||||||
return -ECANCELED;
|
return -ECANCELED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue