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,12 +16,41 @@ */ #include +#include #include #include -/* Linker-defined symbols */ -extern char _text[]; -extern char _end[]; +/** Alignment for hidden memory regions */ +#define ALIGN_HIDDEN 4096 /* 4kB page alignment should be enough */ + +/** + * 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 + * + * Must be terminated by a zero entry. + */ +struct hidden_region __data16_array ( hidden_regions, [] ) = { + [TEXT] = { 0, 0 }, + [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(); @@ -31,16 +60,50 @@ extern struct segoff __text16 ( int15_vector ); #define int15_vector __use_text16 ( int15_vector ) /** - * List of hidden regions + * Hide region of memory from system memory map * - * Must be terminated by a zero entry. + * @v start Start of region + * @v end End of region */ -struct hidden_region __data16_array ( hidden_regions, [] ) = { - [TEXT] = { 0, 0 }, - [BASEMEM] = { 0, ( 640 * 1024 ) }, - [EXTMEM] = { 0, 0 }, - { 0, 0, } /* Terminator */ -}; +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 ); } diff --git a/src/include/gpxe/hidemem.h b/src/include/gpxe/hidemem.h index 89109004..547f8881 100644 --- a/src/include/gpxe/hidemem.h +++ b/src/include/gpxe/hidemem.h @@ -8,38 +8,16 @@ * */ -/** - * 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; -}; - /** * Unique IDs for hidden regions */ -enum { +enum hidemem_region_id { TEXT = 0, BASEMEM, EXTMEM, }; -extern struct hidden_region __data16_array ( hidden_regions, [] ); -#define hidden_regions __use_data16 ( hidden_regions ) - -static inline void hide_region ( unsigned int region, - physaddr_t start, physaddr_t end ) { - hidden_regions[region].start = start; - hidden_regions[region].end = end; -} +extern void hide_region ( unsigned int region_id, physaddr_t start, + physaddr_t end ); #endif /* _GPXE_HIDEMEM_H */