summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2004-04-23 04:14:15 +0000
committerhpa <hpa>2004-04-23 04:14:15 +0000
commit8340f5e03ec7d5abd68f55a76e7e8c9bf8a29ecc (patch)
tree8ac11a986ee15e3202e12905eb3487cb36e34017
parentda71d74b613d9f5aa065e921bcec5a1b4d41c95e (diff)
downloadsyslinux-8340f5e03ec7d5abd68f55a76e7e8c9bf8a29ecc.tar.gz
Better E820 memory parsersyslinux-2.09-pre15
-rw-r--r--NEWS2
-rw-r--r--highmem.inc41
-rw-r--r--isolinux.asm2
-rw-r--r--ldlinux.asm2
-rw-r--r--pxelinux.asm2
5 files changed, 43 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 9a80c882..3f1682b5 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ Changes in 2.09:
SYSLINUX from COMBOOT!!!!
* COMBOOT: Fix "get key without echo" API function.
* SYSLINUX: Fix bug that affected the API open function.
+ * ALL: Improve the E820 memory parser, to work around some
+ buggy BIOSes.
Changes in 2.08:
* Add new configuration command "ontimeout" to allow timeout
diff --git a/highmem.inc b/highmem.inc
index e3a830b7..b10cc8be 100644
--- a/highmem.inc
+++ b/highmem.inc
@@ -1,7 +1,7 @@
;; $Id$
;; -----------------------------------------------------------------------
;;
-;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
+;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -31,17 +31,24 @@ highmemsize:
;
get_e820:
xor ebx,ebx ; Start with first record
+ mov dword [E820Max],-(1 << 20) ; Max amount of high memory
+ mov dword [E820Mem],ebx ; Detected amount of high memory
mov es,bx ; Need ES = DS = 0 for now
jmp short .do_e820 ; Skip "at end" check first time!
.int_loop: and ebx,ebx ; If we're back at beginning...
- jz no_e820 ; ... bail; nothing found
+ jz .e820_done ; ... we're done
.do_e820: mov eax,0000E820h
mov edx,534D4150h ; "SMAP" backwards
xor ecx,ecx
mov cl,20 ; ECX <- 20
mov di,E820Buf
int 15h
- jc no_e820
+ jnc .no_carry
+ ; If carry, ebx == 0 means error, ebx != 0 means we're done
+ and ebx,ebx
+ jnz .e820_done
+ jmp no_e820
+.no_carry:
cmp eax,534D4150h
jne no_e820
;
@@ -51,7 +58,19 @@ get_e820:
ja .int_loop ; Start >= 4 GB?
mov edx, (1 << 20)
sub edx, [E820Buf]
- jb .int_loop ; Start >= 1 MB?
+ jnb .ram_range ; Start >= 1 MB?
+ ; If we get here, it starts > 1 MB but < 4 GB; if this is a
+ ; *non*-memory range, remember this as unusable; some BIOSes
+ ; get the length of primary RAM wrong!
+ cmp dword [E820Buf+16], byte 1
+ je .int_loop ; If it's memory, don't worry about it
+ neg edx ; This means what for memory limit?
+ cmp edx,[E820Max] ; Better or worse
+ jnb .int_loop
+ mov [E820Max],edx
+ jmp .int_loop
+
+.ram_range:
stc
sbb eax,eax ; eax <- 0xFFFFFFFF
cmp dword [E820Buf+12], byte 0
@@ -62,10 +81,20 @@ get_e820:
; Now EAX contains the size of memory 1 MB...up
cmp dword [E820Buf+16], byte 1
- jne near err_nohighmem ; High memory isn't usable memory!!!!
+ jne .int_loop ; High memory isn't usable memory!!!!
; We're good!
- jmp short got_highmem_add1mb ; Still need to add low 1 MB
+ mov [E820Mem],eax
+ jmp .int_loop ; Still need to add low 1 MB
+
+.e820_done:
+ mov eax,[E820Mem]
+ and eax,eax
+ jz no_e820 ; Nothing found by E820?
+ cmp eax,[E820Max] ; Make sure we're not limited
+ jna got_highmem_add1mb
+ mov eax,[E820Max]
+ jmp got_highmem_add1mb
;
; INT 15:E820 failed. Try INT 15:E801.
diff --git a/isolinux.asm b/isolinux.asm
index 028c35ae..33d22314 100644
--- a/isolinux.asm
+++ b/isolinux.asm
@@ -152,6 +152,8 @@ MNameBuf resb FILENAME_MAX
InitRD resb FILENAME_MAX
PartInfo resb 16 ; Partition table entry
E820Buf resd 5 ; INT 15:E820 data buffer
+E820Mem resd 1 ; Memory detected by E820
+E820Max resd 1 ; Is E820 memory capped?
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk
diff --git a/ldlinux.asm b/ldlinux.asm
index 138ad6a6..675b3e16 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -148,6 +148,8 @@ EndofDirSec resw 1 ; = trackbuf+bsBytesPerSec-31
alignb 4
E820Buf resd 5 ; INT 15:E820 data buffer
+E820Mem resd 1 ; Memory detected by E820
+E820Max resd 1 ; Is E820 memory capped?
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk
diff --git a/pxelinux.asm b/pxelinux.asm
index edc081d9..ffbeed12 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -238,6 +238,8 @@ MAC resb 16 ; Actual MAC address
MACStr resb 3*17 ; MAC address as a string
PartInfo resb 16 ; Partition table entry
E820Buf resd 5 ; INT 15:E820 data buffer
+E820Mem resd 1 ; Memory detected by E820
+E820Max resd 1 ; Is E820 memory capped?
HiLoadAddr resd 1 ; Address pointer for high load loop
HighMemSize resd 1 ; End of memory pointer (bytes)
RamdiskMax resd 1 ; Highest address for a ramdisk