Bladeren bron

[pcbios] Allow for larger-than-20-byte buffers in e820mangler.S

Although the E820 API allows for a caller to provide only a 20-byte
buffer, there exists at least one combination (HP BIOS, 32-bit WinPE)
that relies on information found only in the "extended attributes"
field, which requires a 24-byte buffer.

Allow for up to a 64-byte E820 buffer, in the hope of coping with
future idiocies like this one.
tags/v0.9.5
Michael Brown 16 jaren geleden
bovenliggende
commit
1dda75c9cd
1 gewijzigde bestanden met toevoegingen van 45 en 14 verwijderingen
  1. 45
    14
      src/arch/i386/firmware/pcbios/e820mangler.S

+ 45
- 14
src/arch/i386/firmware/pcbios/e820mangler.S Bestand weergeven

@@ -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 */

Laden…
Annuleren
Opslaan