summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/firmware/pcbios/hidemem.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-14 00:38:33 +0100
committerMichael Brown2007-01-14 00:38:33 +0100
commitaaed3d50a84505b38f81e197e700212fa22cabc7 (patch)
treea1c99d7d7ac40611358ead12417fcd2aa2a93cee /src/arch/i386/firmware/pcbios/hidemem.c
parentAdd some trace messages for important events (diff)
downloadipxe-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.c95
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 );
}