Contents of /trunk/mkinitrd-magellan/isolinux/highmem.inc
Parent Directory | Revision Log
Revision 1133 -
(show annotations)
(download)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
File size: 3938 byte(s)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
File size: 3938 byte(s)
-updated to isolinux-3.86
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. |
10 | ;; |
11 | ;; ----------------------------------------------------------------------- |
12 | |
13 | ;; |
14 | ;; highmem.inc |
15 | ;; |
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. |
18 | ;; |
19 | |
20 | section .text |
21 | |
22 | ; |
23 | ; This is set up as a subroutine; it will set up the global variable |
24 | ; HighMemSize. All registers are preserved. |
25 | ; |
26 | highmemsize: |
27 | push es |
28 | pushfd |
29 | pushad |
30 | |
31 | push cs |
32 | pop es |
33 | |
34 | ; |
35 | ; First, try INT 15:E820 (get BIOS memory map) |
36 | ; |
37 | ; Note: we may have to scan this multiple times, because some (daft) BIOSes |
38 | ; report main memory as multiple contiguous ranges... |
39 | ; |
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 |
68 | |
69 | ; |
70 | ; Look for a memory block starting at <= 1 MB and continuing upward |
71 | ; |
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 |
88 | |
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 |
103 | |
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 |
113 | |
114 | ; |
115 | ; INT 15:E820 failed. Try INT 15:E801. |
116 | ; |
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 |
124 | |
125 | mov ax,bx |
126 | shl eax,16 ; 64K chunks |
127 | add eax,(16 << 20) ; Add first 16M |
128 | jmp short got_highmem |
129 | |
130 | ; |
131 | ; INT 15:E801 failed. Try INT 15:88. |
132 | ; |
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! |
152 | |
153 | section .bss |
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 resd 1 ; End of memory pointer (bytes) |