mirror of https://github.com/ipxe/ipxe.git
[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.pull/1/head
parent
040f7cdf3a
commit
1dda75c9cd
|
@ -25,6 +25,26 @@
|
||||||
|
|
||||||
#define SMAP 0x534d4150
|
#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
|
* Allowed memory windows
|
||||||
|
@ -204,19 +224,22 @@ get_underlying_e820:
|
||||||
|
|
||||||
/* If the requested region is in the cache, return it */
|
/* If the requested region is in the cache, return it */
|
||||||
cmpw %bx, underlying_e820_index
|
cmpw %bx, underlying_e820_index
|
||||||
jne 1f
|
jne 2f
|
||||||
pushw %di
|
pushw %di
|
||||||
pushw %si
|
pushw %si
|
||||||
movw $underlying_e820_cache, %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
|
rep movsb
|
||||||
|
popl %ecx
|
||||||
popw %si
|
popw %si
|
||||||
popw %di
|
popw %di
|
||||||
movw $20, %cx
|
|
||||||
incw %bx
|
incw %bx
|
||||||
movl %edx, %eax
|
movl %edx, %eax
|
||||||
ret
|
ret
|
||||||
1:
|
2:
|
||||||
/* If the requested region is earlier than the cached region,
|
/* If the requested region is earlier than the cached region,
|
||||||
* invalidate the cache.
|
* invalidate the cache.
|
||||||
*/
|
*/
|
||||||
|
@ -250,23 +273,26 @@ get_underlying_e820:
|
||||||
pushw %ds
|
pushw %ds
|
||||||
popw %es
|
popw %es
|
||||||
movw $underlying_e820_cache, %di
|
movw $underlying_e820_cache, %di
|
||||||
movl $20, %ecx
|
cmpl $E820MAXSIZE, %ecx
|
||||||
movl underlying_e820_ebx, %ebx
|
jbe 1f
|
||||||
|
movl $E820MAXSIZE, %ecx
|
||||||
|
1: movl underlying_e820_ebx, %ebx
|
||||||
stc
|
stc
|
||||||
pushfw
|
pushfw
|
||||||
lcall *%cs:int15_vector
|
lcall *%cs:int15_vector
|
||||||
popw %di
|
popw %di
|
||||||
popw %es
|
popw %es
|
||||||
/* Check for error return from underlying e820 call */
|
/* Check for error return from underlying e820 call */
|
||||||
jc 1f /* CF set: error */
|
jc 2f /* CF set: error */
|
||||||
cmpl $SMAP, %eax
|
cmpl $SMAP, %eax
|
||||||
je 2f /* 'SMAP' missing: error */
|
je 3f /* 'SMAP' missing: error */
|
||||||
1: /* An error occurred: return values returned by underlying e820 call */
|
2: /* An error occurred: return values returned by underlying e820 call */
|
||||||
stc /* Force CF set if SMAP was missing */
|
stc /* Force CF set if SMAP was missing */
|
||||||
addr32 leal 16(%esp), %esp /* avoid changing other flags */
|
addr32 leal 16(%esp), %esp /* avoid changing other flags */
|
||||||
ret
|
ret
|
||||||
2: /* No error occurred */
|
3: /* No error occurred */
|
||||||
movl %ebx, underlying_e820_ebx
|
movl %ebx, underlying_e820_ebx
|
||||||
|
movl %ecx, underlying_e820_cache_size
|
||||||
popl %edx
|
popl %edx
|
||||||
popl %ecx
|
popl %ecx
|
||||||
popl %ebx
|
popl %ebx
|
||||||
|
@ -290,9 +316,14 @@ underlying_e820_ebx:
|
||||||
|
|
||||||
.section ".bss16"
|
.section ".bss16"
|
||||||
underlying_e820_cache:
|
underlying_e820_cache:
|
||||||
.space 20
|
.space E820MAXSIZE
|
||||||
.size underlying_e820_cache, . - underlying_e820_cache
|
.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
|
* 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 */
|
/* Peek ahead to see if there are any further nonempty regions */
|
||||||
pushal
|
pushal
|
||||||
pushw %es
|
pushw %es
|
||||||
subw $20, %sp
|
movw %sp, %bp
|
||||||
|
subw %cx, %sp
|
||||||
movl $0xe820, %eax
|
movl $0xe820, %eax
|
||||||
movl $SMAP, %edx
|
movl $SMAP, %edx
|
||||||
movl $20, %ecx
|
|
||||||
pushw %ss
|
pushw %ss
|
||||||
popw %es
|
popw %es
|
||||||
movw %sp, %di
|
movw %sp, %di
|
||||||
call get_nonempty_e820
|
call get_nonempty_e820
|
||||||
addr32 leal 20(%esp), %esp /* avoid changing flags */
|
movw %bp, %sp
|
||||||
popw %es
|
popw %es
|
||||||
popal
|
popal
|
||||||
jnc 99f /* There are further nonempty regions */
|
jnc 99f /* There are further nonempty regions */
|
||||||
|
|
Loading…
Reference in New Issue