|
@@ -25,6 +25,26 @@
|
25
|
25
|
|
26
|
26
|
#define SMAP 0x534d4150
|
27
|
27
|
|
|
28
|
+/* Most documentation refers to the E820 buffer as being 20 bytes, and
|
|
29
|
+ * the API makes it perfectly legitimate to pass only a 20-byte buffer
|
|
30
|
+ * and expect to get valid data. However, some morons at ACPI decided
|
|
31
|
+ * to extend the data structure by adding an extra "extended
|
|
32
|
+ * attributes" field and by including critical information within this
|
|
33
|
+ * field, such as whether or not the region is enabled. A caller who
|
|
34
|
+ * passes in only a 20-byte buffer therefore risks getting very, very
|
|
35
|
+ * misleading information.
|
|
36
|
+ *
|
|
37
|
+ * I have personally witnessed an HP BIOS that returns a value of
|
|
38
|
+ * 0x0009 in the extended attributes field. If we don't pass this
|
|
39
|
+ * value through to the caller, 32-bit WinPE will die, usually with a
|
|
40
|
+ * PAGE_FAULT_IN_NONPAGED_AREA blue screen of death.
|
|
41
|
+ *
|
|
42
|
+ * Allow a ridiculously large maximum value (64 bytes) for the E820
|
|
43
|
+ * buffer as a guard against insufficiently creative idiots in the
|
|
44
|
+ * future.
|
|
45
|
+ */
|
|
46
|
+#define E820MAXSIZE 64
|
|
47
|
+
|
28
|
48
|
/****************************************************************************
|
29
|
49
|
*
|
30
|
50
|
* Allowed memory windows
|
|
@@ -204,19 +224,22 @@ get_underlying_e820:
|
204
|
224
|
|
205
|
225
|
/* If the requested region is in the cache, return it */
|
206
|
226
|
cmpw %bx, underlying_e820_index
|
207
|
|
- jne 1f
|
|
227
|
+ jne 2f
|
208
|
228
|
pushw %di
|
209
|
229
|
pushw %si
|
210
|
230
|
movw $underlying_e820_cache, %si
|
211
|
|
- movw $20, %cx
|
|
231
|
+ cmpl underlying_e820_cache_size, %ecx
|
|
232
|
+ jbe 1f
|
|
233
|
+ movl underlying_e820_cache_size, %ecx
|
|
234
|
+1: pushl %ecx
|
212
|
235
|
rep movsb
|
|
236
|
+ popl %ecx
|
213
|
237
|
popw %si
|
214
|
238
|
popw %di
|
215
|
|
- movw $20, %cx
|
216
|
239
|
incw %bx
|
217
|
240
|
movl %edx, %eax
|
218
|
241
|
ret
|
219
|
|
-1:
|
|
242
|
+2:
|
220
|
243
|
/* If the requested region is earlier than the cached region,
|
221
|
244
|
* invalidate the cache.
|
222
|
245
|
*/
|
|
@@ -250,23 +273,26 @@ get_underlying_e820:
|
250
|
273
|
pushw %ds
|
251
|
274
|
popw %es
|
252
|
275
|
movw $underlying_e820_cache, %di
|
253
|
|
- movl $20, %ecx
|
254
|
|
- movl underlying_e820_ebx, %ebx
|
|
276
|
+ cmpl $E820MAXSIZE, %ecx
|
|
277
|
+ jbe 1f
|
|
278
|
+ movl $E820MAXSIZE, %ecx
|
|
279
|
+1: movl underlying_e820_ebx, %ebx
|
255
|
280
|
stc
|
256
|
281
|
pushfw
|
257
|
282
|
lcall *%cs:int15_vector
|
258
|
283
|
popw %di
|
259
|
284
|
popw %es
|
260
|
285
|
/* Check for error return from underlying e820 call */
|
261
|
|
- jc 1f /* CF set: error */
|
|
286
|
+ jc 2f /* CF set: error */
|
262
|
287
|
cmpl $SMAP, %eax
|
263
|
|
- je 2f /* 'SMAP' missing: error */
|
264
|
|
-1: /* An error occurred: return values returned by underlying e820 call */
|
|
288
|
+ je 3f /* 'SMAP' missing: error */
|
|
289
|
+2: /* An error occurred: return values returned by underlying e820 call */
|
265
|
290
|
stc /* Force CF set if SMAP was missing */
|
266
|
291
|
addr32 leal 16(%esp), %esp /* avoid changing other flags */
|
267
|
292
|
ret
|
268
|
|
-2: /* No error occurred */
|
|
293
|
+3: /* No error occurred */
|
269
|
294
|
movl %ebx, underlying_e820_ebx
|
|
295
|
+ movl %ecx, underlying_e820_cache_size
|
270
|
296
|
popl %edx
|
271
|
297
|
popl %ecx
|
272
|
298
|
popl %ebx
|
|
@@ -290,9 +316,14 @@ underlying_e820_ebx:
|
290
|
316
|
|
291
|
317
|
.section ".bss16"
|
292
|
318
|
underlying_e820_cache:
|
293
|
|
- .space 20
|
|
319
|
+ .space E820MAXSIZE
|
294
|
320
|
.size underlying_e820_cache, . - underlying_e820_cache
|
295
|
321
|
|
|
322
|
+ .section ".bss16"
|
|
323
|
+underlying_e820_cache_size:
|
|
324
|
+ .long 0
|
|
325
|
+ .size underlying_e820_cache_size, . - underlying_e820_cache_size
|
|
326
|
+
|
296
|
327
|
/****************************************************************************
|
297
|
328
|
* Get windowed e820 region, without empty region stripping
|
298
|
329
|
*
|
|
@@ -437,15 +468,15 @@ get_mangled_e820:
|
437
|
468
|
/* Peek ahead to see if there are any further nonempty regions */
|
438
|
469
|
pushal
|
439
|
470
|
pushw %es
|
440
|
|
- subw $20, %sp
|
|
471
|
+ movw %sp, %bp
|
|
472
|
+ subw %cx, %sp
|
441
|
473
|
movl $0xe820, %eax
|
442
|
474
|
movl $SMAP, %edx
|
443
|
|
- movl $20, %ecx
|
444
|
475
|
pushw %ss
|
445
|
476
|
popw %es
|
446
|
477
|
movw %sp, %di
|
447
|
478
|
call get_nonempty_e820
|
448
|
|
- addr32 leal 20(%esp), %esp /* avoid changing flags */
|
|
479
|
+ movw %bp, %sp
|
449
|
480
|
popw %es
|
450
|
481
|
popal
|
451
|
482
|
jnc 99f /* There are further nonempty regions */
|