1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
9 ;; (at your option) any later version; incorporated herein by reference.
11 ;; -----------------------------------------------------------------------
16 ;; Probe for the size of high memory. This can be overridden by a
17 ;; mem= command on the command line while booting a new kernel.
23 ; This is set up as a subroutine; it will set up the global variable
24 ; HighMemSize. All registers are preserved. Assumes DS == CS.
31 ; First, try INT 15:E820 (get BIOS memory map)
34 xor ebx,ebx ; Start with first record
35 mov dword [E820Max],-(1 << 20) ; Max amount of high memory
36 mov dword [E820Mem],ebx ; Detected amount of high memory
37 mov es,bx ; Need ES = DS = 0 for now
38 jmp short .do_e820 ; Skip "at end" check first time!
39 .int_loop: and ebx,ebx ; If we're back at beginning...
40 jz .e820_done ; ... we're done
41 .do_e820: mov eax,0000E820h
42 mov edx,534D4150h ; "SMAP" backwards
48 ; If carry, ebx == 0 means error, ebx != 0 means we're done
56 ; Look for a memory block starting at <= 1 MB and continuing upward
58 cmp dword [E820Buf+4], byte 0
59 ja .int_loop ; Start >= 4 GB?
62 jnb .ram_range ; Start >= 1 MB?
63 ; If we get here, it starts > 1 MB but < 4 GB; if this is a
64 ; *non*-memory range, remember this as unusable; some BIOSes
65 ; get the length of primary RAM wrong!
66 cmp dword [E820Buf+16], byte 1
67 je .int_loop ; If it's memory, don't worry about it
68 neg edx ; This means what for memory limit?
69 cmp edx,[E820Max] ; Better or worse
76 sbb eax,eax ; eax <- 0xFFFFFFFF
77 cmp dword [E820Buf+12], byte 0
78 ja .huge ; Size >= 4 GB
80 .huge: sub eax, edx ; Adjust size to start at 1 MB
81 jbe .int_loop ; Completely below 1 MB?
83 ; Now EAX contains the size of memory 1 MB...up
84 cmp dword [E820Buf+16], byte 1
85 jne .int_loop ; High memory isn't usable memory!!!!
89 jmp .int_loop ; Still need to add low 1 MB
94 jz no_e820 ; Nothing found by E820?
95 cmp eax,[E820Max] ; Make sure we're not limited
96 jna got_highmem_add1mb
98 jmp got_highmem_add1mb
101 ; INT 15:E820 failed. Try INT 15:E801.
104 mov ax,0e801h ; Query high memory (semi-recent)
108 ja no_e801 ; > 3C00h something's wrong with this call
109 jb e801_hole ; If memory hole we can only use low part
112 shl eax,16 ; 64K chunks
113 add eax,(16 << 20) ; Add first 16M
114 jmp short got_highmem
117 ; INT 15:E801 failed. Try INT 15:88.
120 mov ah,88h ; Query high memory (oldest)
122 cmp ax,14*1024 ; Don't trust memory >15M
127 shl eax,10 ; Convert from kilobytes
129 add eax,(1 << 20) ; First megabyte
131 %if HIGHMEM_SLOP != 0
134 mov [HighMemSize],eax
141 E820Buf resd 5 ; INT 15:E820 data buffer
142 E820Mem resd 1 ; Memory detected by E820
143 E820Max resd 1 ; Is E820 memory capped?
144 HighMemSize resd 1 ; End of memory pointer (bytes)