Browse Source

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.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
aaed3d50a8
2 changed files with 80 additions and 43 deletions
  1. 77
    18
      src/arch/i386/firmware/pcbios/hidemem.c
  2. 3
    25
      src/include/gpxe/hidemem.h

+ 77
- 18
src/arch/i386/firmware/pcbios/hidemem.c View File

@@ -16,19 +16,28 @@
16 16
  */
17 17
 
18 18
 #include <realmode.h>
19
+#include <bios.h>
19 20
 #include <biosint.h>
20 21
 #include <gpxe/hidemem.h>
21 22
 
22
-/* Linker-defined symbols */
23
-extern char _text[];
24
-extern char _end[];
23
+/** Alignment for hidden memory regions */
24
+#define ALIGN_HIDDEN 4096   /* 4kB page alignment should be enough */
25 25
 
26
-/** Assembly routine in e820mangler.S */
27
-extern void int15();
28
-
29
-/** Vector for storing original INT 15 handler */
30
-extern struct segoff __text16 ( int15_vector );
31
-#define int15_vector __use_text16 ( int15_vector )
26
+/**
27
+ * A hidden region of Etherboot
28
+ *
29
+ * This represents a region that will be edited out of the system's
30
+ * memory map.
31
+ *
32
+ * This structure is accessed by assembly code, so must not be
33
+ * changed.
34
+ */
35
+struct hidden_region {
36
+	/* Physical start address */
37
+	physaddr_t start;
38
+	/* Physical end address */
39
+	physaddr_t end;
40
+};
32 41
 
33 42
 /**
34 43
  * List of hidden regions
@@ -37,10 +46,64 @@ extern struct segoff __text16 ( int15_vector );
37 46
  */
38 47
 struct hidden_region __data16_array ( hidden_regions, [] ) = {
39 48
 	[TEXT] = { 0, 0 },
40
-	[BASEMEM] = { 0, ( 640 * 1024 ) },
49
+	[BASEMEM] = { ( 640 * 1024 ), ( 640 * 1024 ) },
41 50
 	[EXTMEM] = { 0, 0 },
42 51
 	{ 0, 0, } /* Terminator */
43 52
 };
53
+#define hidden_regions __use_data16 ( hidden_regions )
54
+
55
+/** Assembly routine in e820mangler.S */
56
+extern void int15();
57
+
58
+/** Vector for storing original INT 15 handler */
59
+extern struct segoff __text16 ( int15_vector );
60
+#define int15_vector __use_text16 ( int15_vector )
61
+
62
+/**
63
+ * Hide region of memory from system memory map
64
+ *
65
+ * @v start		Start of region
66
+ * @v end		End of region
67
+ */
68
+void hide_region ( unsigned int region_id, physaddr_t start, physaddr_t end ) {
69
+	struct hidden_region *region = &hidden_regions[region_id];
70
+
71
+	/* Some operating systems get a nasty shock if a region of the
72
+	 * E820 map seems to start on a non-page boundary.  Make life
73
+	 * safer by rounding out our edited region.
74
+	 */	
75
+	region->start = ( start & ~( ALIGN_HIDDEN - 1 ) );
76
+	region->end = ( ( end + ALIGN_HIDDEN - 1 ) & ~( ALIGN_HIDDEN - 1 ) );
77
+	DBG ( "Hiding [%lx,%lx)\n", region->start, region->end );
78
+}
79
+
80
+/**
81
+ * Hide Etherboot text
82
+ *
83
+ */
84
+static void hide_text ( void ) {
85
+
86
+	/* The linker defines these symbols for us */
87
+	extern char _text[];
88
+	extern char _end[];
89
+
90
+	hide_region ( TEXT, virt_to_phys ( _text ), virt_to_phys ( _end ) );
91
+}
92
+
93
+/**
94
+ * Hide used base memory
95
+ *
96
+ */
97
+static void hide_basemem ( void ) {
98
+	uint16_t fbms;
99
+
100
+	/* Hide from the top of free base memory to 640kB.  Don't use
101
+	 * hide_region(), because we don't want this rounded to the
102
+	 * nearest page boundary.
103
+	 */
104
+	get_real ( fbms, BDA_SEG, BDA_FBMS );
105
+	hidden_regions[BASEMEM].start = ( fbms * 1024 );
106
+}
44 107
 
45 108
 /**
46 109
  * Hide Etherboot
@@ -49,16 +112,12 @@ struct hidden_region __data16_array ( hidden_regions, [] ) = {
49 112
  * returned by the BIOS.
50 113
  */
51 114
 void hide_etherboot ( void ) {
52
-	hidden_regions[TEXT].start = virt_to_phys ( _text );
53
-	hidden_regions[TEXT].end = virt_to_phys ( _end );
54
-	hidden_regions[BASEMEM].start = ( rm_cs << 4 );
55 115
 
56
-	DBG ( "Hiding [%lx,%lx) and [%lx,%lx)\n",
57
-	      ( unsigned long ) hidden_regions[TEXT].start,
58
-	      ( unsigned long ) hidden_regions[TEXT].end,
59
-	      ( unsigned long ) hidden_regions[BASEMEM].start,
60
-	      ( unsigned long ) hidden_regions[BASEMEM].end );
116
+	/* Initialise the hidden regions */
117
+	hide_text();
118
+	hide_basemem();
61 119
 
120
+	/* Hook INT 15 */
62 121
 	hook_bios_interrupt ( 0x15, ( unsigned int ) int15,
63 122
 			      &int15_vector );
64 123
 }

+ 3
- 25
src/include/gpxe/hidemem.h View File

@@ -8,38 +8,16 @@
8 8
  *
9 9
  */
10 10
 
11
-/**
12
- * A hidden region of Etherboot
13
- *
14
- * This represents a region that will be edited out of the system's
15
- * memory map.
16
- *
17
- * This structure is accessed by assembly code, so must not be
18
- * changed.
19
- */
20
-struct hidden_region {
21
-	/* Physical start address */
22
-	physaddr_t start;
23
-	/* Physical end address */
24
-	physaddr_t end;
25
-};
26
-
27 11
 /**
28 12
  * Unique IDs for hidden regions
29 13
  */
30
-enum {
14
+enum hidemem_region_id {
31 15
 	TEXT = 0,
32 16
 	BASEMEM,
33 17
 	EXTMEM,
34 18
 };
35 19
 
36
-extern struct hidden_region __data16_array ( hidden_regions, [] );
37
-#define hidden_regions __use_data16 ( hidden_regions )
38
-
39
-static inline void hide_region ( unsigned int region,
40
-				 physaddr_t start, physaddr_t end ) {
41
-	hidden_regions[region].start = start;
42
-	hidden_regions[region].end = end;
43
-}
20
+extern void hide_region ( unsigned int region_id, physaddr_t start,
21
+			  physaddr_t end );
44 22
 
45 23
 #endif /* _GPXE_HIDEMEM_H */

Loading…
Cancel
Save