|
@@ -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++;
|