Annotation of /trunk/mkinitrd-magellan/isolinux/highmem.inc
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File size: 3992 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File size: 3992 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | ;; $Id: highmem.inc,v 1.1 2007-09-01 22:44:04 niro 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) |