Annotation of /tags/mkinitrd-6_3_2/isolinux/highmem.inc
Parent Directory | Revision Log
Revision 1164 -
(hide annotations)
(download)
Tue Sep 14 20:33:28 2010 UTC (14 years ago) by niro
File size: 3938 byte(s)
Tue Sep 14 20:33:28 2010 UTC (14 years ago) by niro
File size: 3938 byte(s)
tagged 'mkinitrd-6_3_2'
1 | niro | 532 | ;; ----------------------------------------------------------------------- |
2 | ;; | ||
3 | niro | 1133 | ;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved |
4 | ;; | ||
5 | niro | 532 | ;; 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 | niro | 1133 | ;; |
16 | niro | 532 | ;; 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 | niro | 1133 | ; HighMemSize. All registers are preserved. |
25 | niro | 532 | ; |
26 | highmemsize: | ||
27 | push es | ||
28 | niro | 1133 | pushfd |
29 | niro | 532 | pushad |
30 | |||
31 | niro | 1133 | push cs |
32 | pop es | ||
33 | |||
34 | niro | 532 | ; |
35 | ; First, try INT 15:E820 (get BIOS memory map) | ||
36 | ; | ||
37 | niro | 1133 | ; Note: we may have to scan this multiple times, because some (daft) BIOSes |
38 | ; report main memory as multiple contiguous ranges... | ||
39 | ; | ||
40 | niro | 532 | get_e820: |
41 | niro | 1133 | 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 | niro | 532 | 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 | niro | 1133 | mov cl,20 ; ECX <- 20 (size of buffer) |
56 | niro | 532 | 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 | niro | 1133 | cmp cx,20 |
67 | jb no_e820 | ||
68 | |||
69 | niro | 532 | ; |
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 | niro | 1133 | 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 | niro | 532 | jmp .int_loop |
88 | |||
89 | niro | 1133 | .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 | niro | 532 | mov [E820Mem],eax |
102 | niro | 1133 | jmp .start_over ; Start over in case we find an adjacent range |
103 | niro | 532 | |
104 | .e820_done: | ||
105 | mov eax,[E820Mem] | ||
106 | niro | 1133 | cmp eax,[E820Max] |
107 | jna .not_limited | ||
108 | niro | 532 | mov eax,[E820Max] |
109 | niro | 1133 | .not_limited: |
110 | cmp eax,(1 << 20) | ||
111 | ja got_highmem ; Did we actually find memory? | ||
112 | ; otherwise fall through | ||
113 | niro | 532 | |
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 | niro | 1133 | jmp short got_highmem |
129 | niro | 532 | |
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 | niro | 1133 | popfd |
150 | niro | 532 | 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) |