Browse Source

[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 16 years ago
parent
commit
040f7cdf3a
1 changed files with 43 additions and 3 deletions
  1. 43
    3
      src/arch/i386/firmware/pcbios/memmap.c

+ 43
- 3
src/arch/i386/firmware/pcbios/memmap.c View File

41
 	uint64_t len;
41
 	uint64_t len;
42
 	/** Type of region */
42
 	/** Type of region */
43
 	uint32_t type;
43
 	uint32_t type;
44
+	/** Extended attributes (optional) */
45
+	uint32_t attrs;
44
 } __attribute__ (( packed ));
46
 } __attribute__ (( packed ));
45
 
47
 
46
 #define E820_TYPE_RAM		1 /**< Normal memory */
48
 #define E820_TYPE_RAM		1 /**< Normal memory */
48
 #define E820_TYPE_ACPI		3 /**< ACPI reclaim memory */
50
 #define E820_TYPE_ACPI		3 /**< ACPI reclaim memory */
49
 #define E820_TYPE_NVS		4 /**< ACPI NVS memory */
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
 /** Buffer for INT 15,e820 calls */
59
 /** Buffer for INT 15,e820 calls */
52
 static struct e820_entry __bss16 ( e820buf );
60
 static struct e820_entry __bss16 ( e820buf );
53
 #define e820buf __use_data16 ( e820buf )
61
 #define e820buf __use_data16 ( e820buf )
148
 	struct memory_region *region = memmap->regions;
156
 	struct memory_region *region = memmap->regions;
149
 	uint32_t next = 0;
157
 	uint32_t next = 0;
150
 	uint32_t smap;
158
 	uint32_t smap;
159
+	size_t size;
151
 	unsigned int flags;
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
 	do {
169
 	do {
155
 		__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
170
 		__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
158
 						   "popw %w0\n\t" )
173
 						   "popw %w0\n\t" )
159
 				       : "=r" ( flags ), "=a" ( smap ),
174
 				       : "=r" ( flags ), "=a" ( smap ),
160
 					 "=b" ( next ), "=D" ( discard_D ),
175
 					 "=b" ( next ), "=D" ( discard_D ),
161
-					 "=c" ( discard_c ), "=d" ( discard_d )
176
+					 "=c" ( size ), "=d" ( discard_d )
162
 				       : "a" ( 0xe820 ), "b" ( next ),
177
 				       : "a" ( 0xe820 ), "b" ( next ),
163
 					 "D" ( __from_data16 ( &e820buf ) ),
178
 					 "D" ( __from_data16 ( &e820buf ) ),
164
 					 "c" ( sizeof ( e820buf ) ),
179
 					 "c" ( sizeof ( e820buf ) ),
170
 			return -ENOTSUP;
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
 		if ( flags & CF ) {
193
 		if ( flags & CF ) {
174
 			DBG ( "INT 15,e820 terminated on CF set\n" );
194
 			DBG ( "INT 15,e820 terminated on CF set\n" );
175
 			break;
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
 		      e820buf.start, ( e820buf.start + e820buf.len ),
199
 		      e820buf.start, ( e820buf.start + e820buf.len ),
180
 		      ( int ) e820buf.type );
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
 		if ( e820buf.type != E820_TYPE_RAM )
213
 		if ( e820buf.type != E820_TYPE_RAM )
182
 			continue;
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
 		region->start = e820buf.start;
224
 		region->start = e820buf.start;
185
 		region->end = e820buf.start + e820buf.len;
225
 		region->end = e820buf.start + e820buf.len;
186
 		region++;
226
 		region++;

Loading…
Cancel
Save