diff options
author | Michael Brown | 2007-01-14 00:38:33 +0100 |
---|---|---|
committer | Michael Brown | 2007-01-14 00:38:33 +0100 |
commit | aaed3d50a84505b38f81e197e700212fa22cabc7 (patch) | |
tree | a1c99d7d7ac40611358ead12417fcd2aa2a93cee /src/arch/i386/firmware/pcbios/hidemem.c | |
parent | Add some trace messages for important events (diff) | |
download | ipxe-aaed3d50a84505b38f81e197e700212fa22cabc7.tar.gz ipxe-aaed3d50a84505b38f81e197e700212fa22cabc7.tar.xz ipxe-aaed3d50a84505b38f81e197e700212fa22cabc7.zip |
Some operating systems get a nasty shock if a region of the E820 map seems
to start on a non-page boundary. Make life safer by rounding out our
edited regions.
Diffstat (limited to 'src/arch/i386/firmware/pcbios/hidemem.c')
-rw-r--r-- | src/arch/i386/firmware/pcbios/hidemem.c | 95 |
1 files changed, 77 insertions, 18 deletions
diff --git a/src/arch/i386/firmware/pcbios/hidemem.c b/src/arch/i386/firmware/pcbios/hidemem.c index 3a57fcba..3396e1e6 100644 --- a/src/arch/i386/firmware/pcbios/hidemem.c +++ b/src/arch/i386/firmware/pcbios/hidemem.c @@ -16,19 +16,28 @@ */ #include <realmode.h> +#include <bios.h> #include <biosint.h> #include <gpxe/hidemem.h> -/* Linker-defined symbols */ -extern char _text[]; -extern char _end[]; +/** Alignment for hidden memory regions */ +#define ALIGN_HIDDEN 4096 /* 4kB page alignment should be enough */ -/** Assembly routine in e820mangler.S */ -extern void int15(); - -/** Vector for storing original INT 15 handler */ -extern struct segoff __text16 ( int15_vector ); -#define int15_vector __use_text16 ( int15_vector ) +/** + * A hidden region of Etherboot + * + * This represents a region that will be edited out of the system's + * memory map. + * + * This structure is accessed by assembly code, so must not be + * changed. + */ +struct hidden_region { + /* Physical start address */ + physaddr_t start; + /* Physical end address */ + physaddr_t end; +}; /** * List of hidden regions @@ -37,10 +46,64 @@ extern struct segoff __text16 ( int15_vector ); */ struct hidden_region __data16_array ( hidden_regions, [] ) = { [TEXT] = { 0, 0 }, - [BASEMEM] = { 0, ( 640 * 1024 ) }, + [BASEMEM] = { ( 640 * 1024 ), ( 640 * 1024 ) }, [EXTMEM] = { 0, 0 }, { 0, 0, } /* Terminator */ }; +#define hidden_regions __use_data16 ( hidden_regions ) + +/** Assembly routine in e820mangler.S */ +extern void int15(); + +/** Vector for storing original INT 15 handler */ +extern struct segoff __text16 ( int15_vector ); +#define int15_vector __use_text16 ( int15_vector ) + +/** + * Hide region of memory from system memory map + * + * @v start Start of region + * @v end End of region + */ +void hide_region ( unsigned int region_id, physaddr_t start, physaddr_t end ) { + struct hidden_region *region = &hidden_regions[region_id]; + + /* Some operating systems get a nasty shock if a region of the + * E820 map seems to start on a non-page boundary. Make life + * safer by rounding out our edited region. + */ + region->start = ( start & ~( ALIGN_HIDDEN - 1 ) ); + region->end = ( ( end + ALIGN_HIDDEN - 1 ) & ~( ALIGN_HIDDEN - 1 ) ); + DBG ( "Hiding [%lx,%lx)\n", region->start, region->end ); +} + +/** + * Hide Etherboot text + * + */ +static void hide_text ( void ) { + + /* The linker defines these symbols for us */ + extern char _text[]; + extern char _end[]; + + hide_region ( TEXT, virt_to_phys ( _text ), virt_to_phys ( _end ) ); +} + +/** + * Hide used base memory + * + */ +static void hide_basemem ( void ) { + uint16_t fbms; + + /* Hide from the top of free base memory to 640kB. Don't use + * hide_region(), because we don't want this rounded to the + * nearest page boundary. + */ + get_real ( fbms, BDA_SEG, BDA_FBMS ); + hidden_regions[BASEMEM].start = ( fbms * 1024 ); +} /** * Hide Etherboot @@ -49,16 +112,12 @@ struct hidden_region __data16_array ( hidden_regions, [] ) = { * returned by the BIOS. */ void hide_etherboot ( void ) { - hidden_regions[TEXT].start = virt_to_phys ( _text ); - hidden_regions[TEXT].end = virt_to_phys ( _end ); - hidden_regions[BASEMEM].start = ( rm_cs << 4 ); - DBG ( "Hiding [%lx,%lx) and [%lx,%lx)\n", - ( unsigned long ) hidden_regions[TEXT].start, - ( unsigned long ) hidden_regions[TEXT].end, - ( unsigned long ) hidden_regions[BASEMEM].start, - ( unsigned long ) hidden_regions[BASEMEM].end ); + /* Initialise the hidden regions */ + hide_text(); + hide_basemem(); + /* Hook INT 15 */ hook_bios_interrupt ( 0x15, ( unsigned int ) int15, &int15_vector ); } |