This commit was manufactured by cvs2svn to create branch
[bootcd.git] / syslinux / highmem.inc
1 ;; $Id: highmem.inc,v 1.4 2004/12/17 06:42:01 hpa Exp $
2 ;; -----------------------------------------------------------------------
3 ;;   
4 ;;   Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
5 ;;
6 ;;   This program is free software; you can redistribute it and/or modify
7 ;;   it under the terms of the GNU General Public License as published by
8 ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 ;;   Boston MA 02111-1307, USA; either version 2 of the License, or
10 ;;   (at your option) any later version; incorporated herein by reference.
11 ;;
12 ;; -----------------------------------------------------------------------
13
14 ;;
15 ;; highmem.inc
16 ;; 
17 ;; Probe for the size of high memory.  This can be overridden by a
18 ;; mem= command on the command line while booting a new kernel.
19 ;;
20
21                 section .text
22
23 ;
24 ; This is set up as a subroutine; it will set up the global variable
25 ; HighMemSize.  All registers are preserved.  Assumes DS == CS.
26 ;
27 highmemsize:
28                 push es
29                 pushad
30
31 ;
32 ; First, try INT 15:E820 (get BIOS memory map)
33 ;
34 get_e820:
35                 xor ebx,ebx                     ; Start with first record
36                 mov dword [E820Max],-(1 << 20)  ; Max amount of high memory
37                 mov dword [E820Mem],ebx         ; Detected amount of high memory
38                 mov es,bx                       ; Need ES = DS = 0 for now
39                 jmp short .do_e820              ; Skip "at end" check first time!
40 .int_loop:      and ebx,ebx                     ; If we're back at beginning...
41                 jz .e820_done                   ; ... we're done
42 .do_e820:       mov eax,0000E820h
43                 mov edx,534D4150h               ; "SMAP" backwards
44                 xor ecx,ecx
45                 mov cl,20                       ; ECX <- 20
46                 mov di,E820Buf
47                 int 15h
48                 jnc .no_carry
49                 ; If carry, ebx == 0 means error, ebx != 0 means we're done
50                 and ebx,ebx
51                 jnz .e820_done
52                 jmp no_e820
53 .no_carry:
54                 cmp eax,534D4150h
55                 jne no_e820
56 ;
57 ; Look for a memory block starting at <= 1 MB and continuing upward
58 ;
59                 cmp dword [E820Buf+4], byte 0
60                 ja .int_loop                    ; Start >= 4 GB?
61                 mov edx, (1 << 20)
62                 sub edx, [E820Buf]
63                 jnb .ram_range                  ; Start >= 1 MB?
64                 ; If we get here, it starts > 1 MB but < 4 GB; if this is a
65                 ; *non*-memory range, remember this as unusable; some BIOSes
66                 ; get the length of primary RAM wrong!
67                 cmp dword [E820Buf+16], byte 1
68                 je .int_loop                    ; If it's memory, don't worry about it
69                 neg edx                         ; This means what for memory limit?
70                 cmp edx,[E820Max]               ; Better or worse
71                 jnb .int_loop
72                 mov [E820Max],edx
73                 jmp .int_loop
74                 
75 .ram_range:
76                 stc
77                 sbb eax,eax                     ; eax <- 0xFFFFFFFF
78                 cmp dword [E820Buf+12], byte 0
79                 ja .huge                        ; Size >= 4 GB
80                 mov eax, [E820Buf+8]
81 .huge:          sub eax, edx                    ; Adjust size to start at 1 MB
82                 jbe .int_loop                   ; Completely below 1 MB?
83
84                 ; Now EAX contains the size of memory 1 MB...up
85                 cmp dword [E820Buf+16], byte 1
86                 jne .int_loop                   ; High memory isn't usable memory!!!!
87
88                 ; We're good!
89                 mov [E820Mem],eax
90                 jmp .int_loop                   ; Still need to add low 1 MB
91
92 .e820_done:
93                 mov eax,[E820Mem]
94                 and eax,eax
95                 jz no_e820                      ; Nothing found by E820?
96                 cmp eax,[E820Max]               ; Make sure we're not limited
97                 jna got_highmem_add1mb
98                 mov eax,[E820Max]
99                 jmp got_highmem_add1mb
100
101 ;
102 ; INT 15:E820 failed.  Try INT 15:E801.
103 ;
104 no_e820:
105                 mov ax,0e801h                   ; Query high memory (semi-recent)
106                 int 15h
107                 jc no_e801
108                 cmp ax,3c00h
109                 ja no_e801                      ; > 3C00h something's wrong with this call
110                 jb e801_hole                    ; If memory hole we can only use low part
111
112                 mov ax,bx
113                 shl eax,16                      ; 64K chunks
114                 add eax,(16 << 20)              ; Add first 16M
115                 jmp short got_highmem                           
116
117 ;
118 ; INT 15:E801 failed.  Try INT 15:88.
119 ;
120 no_e801:
121                 mov ah,88h                      ; Query high memory (oldest)
122                 int 15h
123                 cmp ax,14*1024                  ; Don't trust memory >15M
124                 jna e801_hole
125                 mov ax,14*1024
126 e801_hole:
127                 and eax,0ffffh
128                 shl eax,10                      ; Convert from kilobytes
129 got_highmem_add1mb:
130                 add eax,(1 << 20)               ; First megabyte
131 got_highmem:
132 %if HIGHMEM_SLOP != 0
133                 sub eax,HIGHMEM_SLOP
134 %endif
135                 mov [HighMemSize],eax
136                 popad
137                 pop es
138                 ret                             ; Done!
139
140                 section .bss
141                 alignb 4
142 E820Buf         resd 5                  ; INT 15:E820 data buffer
143 E820Mem         resd 1                  ; Memory detected by E820
144 E820Max         resd 1                  ; Is E820 memory capped?
145 HighMemSize     resd 1                  ; End of memory pointer (bytes)