1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2008 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.
34 ; First, try INT 15:E820 (get BIOS memory map)
36 ; Note: we may have to scan this multiple times, because some (daft) BIOSes
37 ; report main memory as multiple contiguous ranges...
40 mov dword [E820Max],-(1 << 20) ; Max amount of high memory
41 mov dword [E820Mem],(1 << 20) ; End of detected high memory
46 rep stosw ; Clear buffer
47 mov byte [di-4],01h ; Initial extattr value
48 xor ebx,ebx ; Start with first record
49 jmp short .do_e820 ; Skip "at end" check first time!
50 .int_loop: and ebx,ebx ; If we're back at beginning...
51 jz .e820_done ; ... we're done
52 .do_e820: mov eax,0000E820h
53 mov edx,534D4150h ; "SMAP" backwards
55 mov cl,24 ; ECX <- 24 (size of buffer)
59 ; If carry, ebx == 0 means error, ebx != 0 means we're done
69 ; Some blithering idiot added a whole new field to E820,
70 ; completely without regard for its implications...
72 test byte [E820Buf+20],1 ; AddressRangeEnabled
76 ; Look for a memory block starting at <= 1 MB and continuing upward
78 cmp dword [E820Buf+4], byte 0
79 ja .int_loop ; Start >= 4 GB?
81 cmp dword [E820Buf+16],1
82 je .is_ram ; Is it memory?
84 ; Non-memory range. Remember this as a limit; some BIOSes get the length
85 ; of primary RAM incorrect!
89 jb .int_loop ; Starts in lowmem region
91 jae .int_loop ; Already above limit
92 mov [E820Max],eax ; Set limit
97 ja .int_loop ; Not contiguous with our starting point
100 cmp dword [E820Buf+12],0
106 jbe .int_loop ; All is below our baseline
108 jmp .start_over ; Start over in case we find an adjacent range
117 ja got_highmem ; Did we actually find memory?
118 ; otherwise fall through
121 ; INT 15:E820 failed. Try INT 15:E801.
124 mov ax,0e801h ; Query high memory (semi-recent)
128 ja no_e801 ; > 3C00h something's wrong with this call
129 jb e801_hole ; If memory hole we can only use low part
132 shl eax,16 ; 64K chunks
133 add eax,(16 << 20) ; Add first 16M
134 jmp short got_highmem
137 ; INT 15:E801 failed. Try INT 15:88.
140 mov ah,88h ; Query high memory (oldest)
142 cmp ax,14*1024 ; Don't trust memory >15M
147 shl eax,10 ; Convert from kilobytes
148 add eax,(1 << 20) ; First megabyte
150 %if HIGHMEM_SLOP != 0
153 mov [HighMemSize],eax
160 E820Buf resd 6 ; INT 15:E820 data buffer
161 E820Mem resd 1 ; Memory detected by E820
162 E820Max resd 1 ; Is E820 memory capped?
163 HighMemSize resd 1 ; End of memory pointer (bytes)