2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-23 01:51:58 +00:00

[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.
This commit is contained in:
Michael Brown 2008-09-29 05:11:51 +01:00
parent 040f7cdf3a
commit 1dda75c9cd

View File

@ -25,6 +25,26 @@
#define SMAP 0x534d4150
/* Most documentation refers to the E820 buffer as being 20 bytes, and
* the API makes it perfectly legitimate to pass only a 20-byte buffer
* and expect to get valid data. However, some morons at ACPI decided
* to extend the data structure by adding an extra "extended
* attributes" field and by including critical information within this
* field, such as whether or not the region is enabled. A caller who
* passes in only a 20-byte buffer therefore risks getting very, very
* misleading information.
*
* I have personally witnessed an HP BIOS that returns a value of
* 0x0009 in the extended attributes field. If we don't pass this
* value through to the caller, 32-bit WinPE will die, usually with a
* PAGE_FAULT_IN_NONPAGED_AREA blue screen of death.
*
* Allow a ridiculously large maximum value (64 bytes) for the E820
* buffer as a guard against insufficiently creative idiots in the
* future.
*/
#define E820MAXSIZE 64
/****************************************************************************
*
* Allowed memory windows
@ -204,19 +224,22 @@ get_underlying_e820:
/* If the requested region is in the cache, return it */
cmpw %bx, underlying_e820_index
jne 1f
jne 2f
pushw %di
pushw %si
movw $underlying_e820_cache, %si
movw $20, %cx
cmpl underlying_e820_cache_size, %ecx
jbe 1f
movl underlying_e820_cache_size, %ecx
1: pushl %ecx
rep movsb
popl %ecx
popw %si
popw %di
movw $20, %cx
incw %bx
movl %edx, %eax
ret
1:
2:
/* If the requested region is earlier than the cached region,
* invalidate the cache.
*/
@ -250,23 +273,26 @@ get_underlying_e820:
pushw %ds
popw %es
movw $underlying_e820_cache, %di
movl $20, %ecx
movl underlying_e820_ebx, %ebx
cmpl $E820MAXSIZE, %ecx
jbe 1f
movl $E820MAXSIZE, %ecx
1: movl underlying_e820_ebx, %ebx
stc
pushfw
lcall *%cs:int15_vector
popw %di
popw %es
/* Check for error return from underlying e820 call */
jc 1f /* CF set: error */
jc 2f /* CF set: error */
cmpl $SMAP, %eax
je 2f /* 'SMAP' missing: error */
1: /* An error occurred: return values returned by underlying e820 call */
je 3f /* 'SMAP' missing: error */
2: /* An error occurred: return values returned by underlying e820 call */
stc /* Force CF set if SMAP was missing */
addr32 leal 16(%esp), %esp /* avoid changing other flags */
ret
2: /* No error occurred */
3: /* No error occurred */
movl %ebx, underlying_e820_ebx
movl %ecx, underlying_e820_cache_size
popl %edx
popl %ecx
popl %ebx
@ -290,9 +316,14 @@ underlying_e820_ebx:
.section ".bss16"
underlying_e820_cache:
.space 20
.space E820MAXSIZE
.size underlying_e820_cache, . - underlying_e820_cache
.section ".bss16"
underlying_e820_cache_size:
.long 0
.size underlying_e820_cache_size, . - underlying_e820_cache_size
/****************************************************************************
* Get windowed e820 region, without empty region stripping
*
@ -437,15 +468,15 @@ get_mangled_e820:
/* Peek ahead to see if there are any further nonempty regions */
pushal
pushw %es
subw $20, %sp
movw %sp, %bp
subw %cx, %sp
movl $0xe820, %eax
movl $SMAP, %edx
movl $20, %ecx
pushw %ss
popw %es
movw %sp, %di
call get_nonempty_e820
addr32 leal 20(%esp), %esp /* avoid changing flags */
movw %bp, %sp
popw %es
popal
jnc 99f /* There are further nonempty regions */