version: Update to 4.08, update year to 2014
[syslinux/sherbszt.git] / core / highmem.inc
blobea386ffcd38844bdd108ced860e4468740238a46
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
4 ;;
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 ;; -----------------------------------------------------------------------
14 ;; highmem.inc
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.
20                 section .text16
23 ; This is set up as a subroutine; it will set up the global variable
24 ; HighMemSize.  All registers are preserved.
26 highmemsize:
27                 push es
28                 pushfd
29                 pushad
31                 push cs
32                 pop es
35 ; First, try INT 15:E820 (get BIOS memory map)
37 ; Note: we may have to scan this multiple times, because some (daft) BIOSes
38 ; report main memory as multiple contiguous ranges...
40 get_e820:
41                 mov dword [E820Max],-(1 << 20)  ; Max amount of high memory
42                 mov dword [E820Mem],(1 << 20)   ; End of detected high memory
43 .start_over:
44                 mov di,E820Buf
45                 xor ax,ax
46                 mov cx,10
47                 rep stosw                       ; Clear buffer
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
54                 xor ecx,ecx
55                 mov cl,20                       ; ECX <- 20 (size of buffer)
56                 mov di,E820Buf
57                 int 15h
58                 jnc .no_carry
59                 ; If carry, ebx == 0 means error, ebx != 0 means we're done
60                 and ebx,ebx
61                 jnz .e820_done
62                 jmp no_e820
63 .no_carry:
64                 cmp eax,534D4150h
65                 jne no_e820
66                 cmp cx,20
67                 jb no_e820
70 ; Look for a memory block starting at <= 1 MB and continuing upward
72                 cmp dword [E820Buf+4], byte 0
73                 ja .int_loop                    ; Start >= 4 GB?
74                 mov eax, [E820Buf]
75                 cmp dword [E820Buf+16],1
76                 je .is_ram                      ; Is it memory?
77                 ;
78                 ; Non-memory range.  Remember this as a limit; some BIOSes get the length
79                 ; of primary RAM incorrect!
80                 ;
81 .not_ram:
82                 cmp eax, (1 << 20)
83                 jb .int_loop                    ; Starts in lowmem region
84                 cmp eax,[E820Max]
85                 jae .int_loop                   ; Already above limit
86                 mov [E820Max],eax               ; Set limit
87                 jmp .int_loop
89 .is_ram:
90                 cmp eax,[E820Mem]
91                 ja .int_loop                    ; Not contiguous with our starting point
92                 add eax,[E820Buf+8]
93                 jc .overflow
94                 cmp dword [E820Buf+12],0
95                 je .nooverflow
96 .overflow:
97                 or eax,-1
98 .nooverflow:
99                 cmp eax,[E820Mem]
100                 jbe .int_loop                   ; All is below our baseline
101                 mov [E820Mem],eax
102                 jmp .start_over                 ; Start over in case we find an adjacent range
104 .e820_done:
105                 mov eax,[E820Mem]
106                 cmp eax,[E820Max]
107                 jna .not_limited
108                 mov eax,[E820Max]
109 .not_limited:
110                 cmp eax,(1 << 20)
111                 ja got_highmem                  ; Did we actually find memory?
112                 ; otherwise fall through
115 ; INT 15:E820 failed.  Try INT 15:E801.
117 no_e820:
118                 mov ax,0e801h                   ; Query high memory (semi-recent)
119                 int 15h
120                 jc no_e801
121                 cmp ax,3c00h
122                 ja no_e801                      ; > 3C00h something's wrong with this call
123                 jb e801_hole                    ; If memory hole we can only use low part
125                 mov ax,bx
126                 shl eax,16                      ; 64K chunks
127                 add eax,(16 << 20)              ; Add first 16M
128                 jmp short got_highmem
131 ; INT 15:E801 failed.  Try INT 15:88.
133 no_e801:
134                 mov ah,88h                      ; Query high memory (oldest)
135                 int 15h
136                 cmp ax,14*1024                  ; Don't trust memory >15M
137                 jna e801_hole
138                 mov ax,14*1024
139 e801_hole:
140                 and eax,0ffffh
141                 shl eax,10                      ; Convert from kilobytes
142                 add eax,(1 << 20)               ; First megabyte
143 got_highmem:
144 %if HIGHMEM_SLOP != 0
145                 sub eax,HIGHMEM_SLOP
146 %endif
147                 mov [HighMemSize],eax
148                 popad
149                 popfd
150                 pop es
151                 ret                             ; Done!
153                 section .bss16
154                 alignb 4
155 E820Buf         resd 5                  ; INT 15:E820 data buffer
156 E820Mem         resd 1                  ; Memory detected by E820
157 E820Max         resd 1                  ; Is E820 memory capped?
158 ; HighMemSize is defined in com32.inc