소스 검색

[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 15 년 전
부모
커밋
1dda75c9cd
1개의 변경된 파일45개의 추가작업 그리고 14개의 파일을 삭제
  1. 45
    14
      src/arch/i386/firmware/pcbios/e820mangler.S

+ 45
- 14
src/arch/i386/firmware/pcbios/e820mangler.S 파일 보기

25
 
25
 
26
 #define SMAP 0x534d4150
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
  * Allowed memory windows
50
  * Allowed memory windows
204
 
224
 
205
 	/* If the requested region is in the cache, return it */
225
 	/* If the requested region is in the cache, return it */
206
 	cmpw	%bx, underlying_e820_index
226
 	cmpw	%bx, underlying_e820_index
207
-	jne	1f
227
+	jne	2f
208
 	pushw	%di
228
 	pushw	%di
209
 	pushw	%si
229
 	pushw	%si
210
 	movw	$underlying_e820_cache, %si
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
 	rep movsb
235
 	rep movsb
236
+	popl	%ecx
213
 	popw	%si
237
 	popw	%si
214
 	popw	%di
238
 	popw	%di
215
-	movw	$20, %cx
216
 	incw	%bx
239
 	incw	%bx
217
 	movl	%edx, %eax
240
 	movl	%edx, %eax
218
 	ret
241
 	ret
219
-1:	
242
+2:	
220
 	/* If the requested region is earlier than the cached region,
243
 	/* If the requested region is earlier than the cached region,
221
 	 * invalidate the cache.
244
 	 * invalidate the cache.
222
 	 */
245
 	 */
250
 	pushw	%ds
273
 	pushw	%ds
251
 	popw	%es
274
 	popw	%es
252
 	movw	$underlying_e820_cache, %di
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
 	stc
280
 	stc
256
 	pushfw
281
 	pushfw
257
 	lcall	*%cs:int15_vector
282
 	lcall	*%cs:int15_vector
258
 	popw	%di
283
 	popw	%di
259
 	popw	%es
284
 	popw	%es
260
 	/* Check for error return from underlying e820 call */
285
 	/* Check for error return from underlying e820 call */
261
-	jc	1f /* CF set: error */
286
+	jc	2f /* CF set: error */
262
 	cmpl	$SMAP, %eax
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
 	stc	/* Force CF set if SMAP was missing */
290
 	stc	/* Force CF set if SMAP was missing */
266
 	addr32 leal 16(%esp), %esp /* avoid changing other flags */
291
 	addr32 leal 16(%esp), %esp /* avoid changing other flags */
267
 	ret
292
 	ret
268
-2:	/* No error occurred */
293
+3:	/* No error occurred */
269
 	movl	%ebx, underlying_e820_ebx
294
 	movl	%ebx, underlying_e820_ebx
295
+	movl	%ecx, underlying_e820_cache_size
270
 	popl	%edx
296
 	popl	%edx
271
 	popl	%ecx
297
 	popl	%ecx
272
 	popl	%ebx
298
 	popl	%ebx
290
 
316
 
291
 	.section ".bss16"
317
 	.section ".bss16"
292
 underlying_e820_cache:
318
 underlying_e820_cache:
293
-	.space	20
319
+	.space	E820MAXSIZE
294
 	.size underlying_e820_cache, . - underlying_e820_cache
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
  * Get windowed e820 region, without empty region stripping
328
  * Get windowed e820 region, without empty region stripping
298
  *
329
  *
437
 	/* Peek ahead to see if there are any further nonempty regions */
468
 	/* Peek ahead to see if there are any further nonempty regions */
438
 	pushal
469
 	pushal
439
 	pushw	%es
470
 	pushw	%es
440
-	subw	$20, %sp
471
+	movw	%sp, %bp
472
+	subw	%cx, %sp
441
 	movl	$0xe820, %eax
473
 	movl	$0xe820, %eax
442
 	movl	$SMAP, %edx
474
 	movl	$SMAP, %edx
443
-	movl	$20, %ecx
444
 	pushw	%ss
475
 	pushw	%ss
445
 	popw	%es
476
 	popw	%es
446
 	movw	%sp, %di
477
 	movw	%sp, %di
447
 	call	get_nonempty_e820
478
 	call	get_nonempty_e820
448
-	addr32 leal 20(%esp), %esp /* avoid changing flags */
479
+	movw	%bp, %sp
449
 	popw	%es
480
 	popw	%es
450
 	popal
481
 	popal
451
 	jnc	99f /* There are further nonempty regions */
482
 	jnc	99f /* There are further nonempty regions */

Loading…
취소
저장