Procházet zdrojové kódy

[pcbios] Print INT 15,E820 extended attributes, if present

The ACPI specification defines an additional 4-byte field at offset 20
for an E820 memory map entry.  This field is presumably optional,
since generally E820 gets given only a 20-byte buffer to fill.
However, the bits of this optional field are defined as:

  bit 0 : region is enabled
  bit 1 : region is non-volatile memory rather than RAM

so it seems as though callers that pass in only a 20-byte buffer may
be missing out on some rather important information.
tags/v0.9.5
Michael Brown před 16 roky
rodič
revize
040f7cdf3a
1 změnil soubory, kde provedl 43 přidání a 3 odebrání
  1. 43
    3
      src/arch/i386/firmware/pcbios/memmap.c

+ 43
- 3
src/arch/i386/firmware/pcbios/memmap.c Zobrazit soubor

@@ -41,6 +41,8 @@ struct e820_entry {
41 41
 	uint64_t len;
42 42
 	/** Type of region */
43 43
 	uint32_t type;
44
+	/** Extended attributes (optional) */
45
+	uint32_t attrs;
44 46
 } __attribute__ (( packed ));
45 47
 
46 48
 #define E820_TYPE_RAM		1 /**< Normal memory */
@@ -48,6 +50,12 @@ struct e820_entry {
48 50
 #define E820_TYPE_ACPI		3 /**< ACPI reclaim memory */
49 51
 #define E820_TYPE_NVS		4 /**< ACPI NVS memory */
50 52
 
53
+#define E820_ATTR_ENABLED	0x00000001UL
54
+#define E820_ATTR_NONVOLATILE	0x00000002UL
55
+#define E820_ATTR_UNKNOWN	0xfffffffcUL
56
+
57
+#define E820_MIN_SIZE		20
58
+
51 59
 /** Buffer for INT 15,e820 calls */
52 60
 static struct e820_entry __bss16 ( e820buf );
53 61
 #define e820buf __use_data16 ( e820buf )
@@ -148,8 +156,15 @@ static int meme820 ( struct memory_map *memmap ) {
148 156
 	struct memory_region *region = memmap->regions;
149 157
 	uint32_t next = 0;
150 158
 	uint32_t smap;
159
+	size_t size;
151 160
 	unsigned int flags;
152
-	unsigned int discard_c, discard_d, discard_D;
161
+	unsigned int discard_d, discard_D;
162
+
163
+	/* Clear the E820 buffer.  Do this once before starting,
164
+	 * rather than on each call; some BIOSes rely on the contents
165
+	 * being preserved between calls.
166
+	 */
167
+	memset ( &e820buf, 0, sizeof ( e820buf ) );
153 168
 
154 169
 	do {
155 170
 		__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
@@ -158,7 +173,7 @@ static int meme820 ( struct memory_map *memmap ) {
158 173
 						   "popw %w0\n\t" )
159 174
 				       : "=r" ( flags ), "=a" ( smap ),
160 175
 					 "=b" ( next ), "=D" ( discard_D ),
161
-					 "=c" ( discard_c ), "=d" ( discard_d )
176
+					 "=c" ( size ), "=d" ( discard_d )
162 177
 				       : "a" ( 0xe820 ), "b" ( next ),
163 178
 					 "D" ( __from_data16 ( &e820buf ) ),
164 179
 					 "c" ( sizeof ( e820buf ) ),
@@ -170,17 +185,42 @@ static int meme820 ( struct memory_map *memmap ) {
170 185
 			return -ENOTSUP;
171 186
 		}
172 187
 
188
+		if ( size < E820_MIN_SIZE ) {
189
+			DBG ( "INT 15,e820 returned only %zd bytes\n", size );
190
+			return -EINVAL;
191
+		}
192
+
173 193
 		if ( flags & CF ) {
174 194
 			DBG ( "INT 15,e820 terminated on CF set\n" );
175 195
 			break;
176 196
 		}
177 197
 
178
-		DBG ( "INT 15,e820 region [%llx,%llx) type %d\n",
198
+		DBG ( "INT 15,e820 region [%llx,%llx) type %d",
179 199
 		      e820buf.start, ( e820buf.start + e820buf.len ),
180 200
 		      ( int ) e820buf.type );
201
+		if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
202
+			DBG ( " (%s", ( ( e820buf.attrs & E820_ATTR_ENABLED )
203
+					? "enabled" : "disabled" ) );
204
+			if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
205
+				DBG ( ", non-volatile" );
206
+			if ( e820buf.attrs & E820_ATTR_UNKNOWN )
207
+				DBG ( ", other [%08lx]", e820buf.attrs );
208
+			DBG ( ")" );
209
+		}
210
+		DBG ( "\n" );
211
+
212
+		/* Discard non-RAM regions */
181 213
 		if ( e820buf.type != E820_TYPE_RAM )
182 214
 			continue;
183 215
 
216
+		/* Check extended attributes, if present */
217
+		if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
218
+			if ( ! ( e820buf.attrs & E820_ATTR_ENABLED ) )
219
+				continue;
220
+			if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
221
+				continue;
222
+		}
223
+
184 224
 		region->start = e820buf.start;
185 225
 		region->end = e820buf.start + e820buf.len;
186 226
 		region++;

Načítá se…
Zrušit
Uložit