summaryrefslogtreecommitdiff
path: root/highmem.inc
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 /highmem.inc
parentda71d74b613d9f5aa065e921bcec5a1b4d41c95e (diff)
downloadsyslinux-8340f5e03ec7d5abd68f55a76e7e8c9bf8a29ecc.tar.gz
Better E820 memory parsersyslinux-2.09-pre15
Diffstat (limited to 'highmem.inc')
-rw-r--r--highmem.inc41
1 files changed, 35 insertions, 6 deletions
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.