|
@@ -1,235 +0,0 @@
|
1
|
|
-#include "stdint.h"
|
2
|
|
-#include "stddef.h"
|
3
|
|
-#include "realmode.h"
|
4
|
|
-#include <gpxe/init.h>
|
5
|
|
-#include "etherboot.h"
|
6
|
|
-#include "memsizes.h"
|
7
|
|
-
|
8
|
|
-#define CF ( 1 << 0 )
|
9
|
|
-
|
10
|
|
-/* by Eric Biederman */
|
11
|
|
-
|
12
|
|
-struct meminfo meminfo;
|
13
|
|
-
|
14
|
|
-/**************************************************************************
|
15
|
|
-BASEMEMSIZE - Get size of the conventional (base) memory
|
16
|
|
-**************************************************************************/
|
17
|
|
-static unsigned short basememsize ( void ) {
|
18
|
|
- uint16_t int12_basememsize, fbms_basememsize;
|
19
|
|
- uint16_t basememsize;
|
20
|
|
-
|
21
|
|
- /* There are two methods for retrieving the base memory size:
|
22
|
|
- * INT 12 and the BIOS FBMS counter at 40:13. We read both
|
23
|
|
- * and use the smaller value, to be paranoid.
|
24
|
|
- *
|
25
|
|
- * We then store the smaller value in the BIOS FBMS counter so
|
26
|
|
- * that other code (e.g. basemem.c) can rely on it and not
|
27
|
|
- * have to use INT 12. This is especially important because
|
28
|
|
- * basemem.c functions can be called in a context in which
|
29
|
|
- * there is no real-mode stack (e.g. when trying to allocate
|
30
|
|
- * memory for a real-mode stack...)
|
31
|
|
- */
|
32
|
|
-
|
33
|
|
- REAL_EXEC ( rm_basememsize,
|
34
|
|
- "int $0x12\n\t",
|
35
|
|
- 1,
|
36
|
|
- OUT_CONSTRAINTS ( "=a" ( int12_basememsize ) ),
|
37
|
|
- IN_CONSTRAINTS (),
|
38
|
|
- CLOBBER ( "ebx", "ecx", "edx", "ebp", "esi", "edi" ) );
|
39
|
|
-
|
40
|
|
- get_real ( fbms_basememsize, 0x40, 0x13 );
|
41
|
|
-
|
42
|
|
- basememsize = ( int12_basememsize < fbms_basememsize ?
|
43
|
|
- int12_basememsize : fbms_basememsize );
|
44
|
|
-
|
45
|
|
- put_real ( basememsize, 0x40, 0x13 );
|
46
|
|
-
|
47
|
|
- return basememsize;
|
48
|
|
-}
|
49
|
|
-
|
50
|
|
-/**************************************************************************
|
51
|
|
-MEMSIZE - Determine size of extended memory, in kB
|
52
|
|
-**************************************************************************/
|
53
|
|
-static unsigned int memsize ( void ) {
|
54
|
|
- uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k;
|
55
|
|
- uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k;
|
56
|
|
- uint16_t flags;
|
57
|
|
- int memsize;
|
58
|
|
-
|
59
|
|
- /* Try INT 15,e801 first
|
60
|
|
- *
|
61
|
|
- * Some buggy BIOSes don't clear/set carry on pass/error of
|
62
|
|
- * e801h memory size call or merely pass cx,dx through without
|
63
|
|
- * changing them, so we set carry and zero cx,dx before call.
|
64
|
|
- */
|
65
|
|
- REAL_EXEC ( rm_mem_e801,
|
66
|
|
- "stc\n\t"
|
67
|
|
- "int $0x15\n\t"
|
68
|
|
- "pushfw\n\t" /* flags -> %di */
|
69
|
|
- "popw %%di\n\t",
|
70
|
|
- 5,
|
71
|
|
- OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ),
|
72
|
|
- "=b" ( extmem_16m_plus_64k ),
|
73
|
|
- "=c" ( confmem_1m_to_16m_k ),
|
74
|
|
- "=d" ( confmem_16m_plus_64k ),
|
75
|
|
- "=D" ( flags ) ),
|
76
|
|
- IN_CONSTRAINTS ( "a" ( 0xe801 ),
|
77
|
|
- "c" ( 0 ),
|
78
|
|
- "d" ( 0 ) ),
|
79
|
|
- CLOBBER ( "ebp", "esi" ) );
|
80
|
|
-
|
81
|
|
- if ( ! ( flags & CF ) ) {
|
82
|
|
- /* INT 15,e801 succeeded */
|
83
|
|
- if ( confmem_1m_to_16m_k || confmem_16m_plus_64k ) {
|
84
|
|
- /* Use confmem (cx,dx) values */
|
85
|
|
- memsize = confmem_1m_to_16m_k +
|
86
|
|
- ( confmem_16m_plus_64k << 6 );
|
87
|
|
- } else {
|
88
|
|
- /* Use extmem (ax,bx) values */
|
89
|
|
- memsize = extmem_1m_to_16m_k +
|
90
|
|
- ( extmem_16m_plus_64k << 6 );
|
91
|
|
- }
|
92
|
|
- } else {
|
93
|
|
- /* INT 15,e801 failed; fall back to INT 15,88
|
94
|
|
- *
|
95
|
|
- * CF is apparently unreliable and should be ignored.
|
96
|
|
- */
|
97
|
|
- REAL_EXEC ( rm_mem_88,
|
98
|
|
- "int $0x15\n\t",
|
99
|
|
- 1,
|
100
|
|
- OUT_CONSTRAINTS ( "=a" ( extmem_1m_to_16m_k ) ),
|
101
|
|
- IN_CONSTRAINTS ( "a" ( 0x88 << 8 ) ),
|
102
|
|
- CLOBBER ( "ebx", "ecx", "edx",
|
103
|
|
- "ebp", "esi", "edi" ) );
|
104
|
|
- memsize = extmem_1m_to_16m_k;
|
105
|
|
- }
|
106
|
|
-
|
107
|
|
- return memsize;
|
108
|
|
-}
|
109
|
|
-
|
110
|
|
-/**************************************************************************
|
111
|
|
-MEME820 - Retrieve the E820 BIOS memory map
|
112
|
|
-**************************************************************************/
|
113
|
|
-#define SMAP ( 0x534d4150 ) /* "SMAP" */
|
114
|
|
-static int meme820 ( struct e820entry *buf, int count ) {
|
115
|
|
- int index;
|
116
|
|
- uint16_t basemem_entry;
|
117
|
|
- uint32_t smap, next;
|
118
|
|
- uint16_t flags;
|
119
|
|
- uint32_t discard_c, discard_d;
|
120
|
|
-
|
121
|
|
- index = 0;
|
122
|
|
- next = 0;
|
123
|
|
- do {
|
124
|
|
- basemem_entry = BASEMEM_PARAMETER_INIT ( buf[index] );
|
125
|
|
- REAL_EXEC ( rm_mem_e820,
|
126
|
|
- "int $0x15\n\t"
|
127
|
|
- "pushfw\n\t" /* flags -> %di */
|
128
|
|
- "popw %%di\n\t",
|
129
|
|
- 5,
|
130
|
|
- OUT_CONSTRAINTS ( "=a" ( smap ),
|
131
|
|
- "=b" ( next ),
|
132
|
|
- "=c" ( discard_c ),
|
133
|
|
- "=d" ( discard_d ),
|
134
|
|
- "=D" ( flags ) ),
|
135
|
|
- IN_CONSTRAINTS ( "a" ( 0xe820 ),
|
136
|
|
- "b" ( next ),
|
137
|
|
- "c" ( sizeof (struct e820entry) ),
|
138
|
|
- "d" ( SMAP ),
|
139
|
|
- "D" ( basemem_entry ) ),
|
140
|
|
- CLOBBER ( "ebp", "esi" ) );
|
141
|
|
- BASEMEM_PARAMETER_DONE ( buf[index] );
|
142
|
|
- if ( smap != SMAP ) return 0;
|
143
|
|
- if ( flags & CF ) break;
|
144
|
|
- index++;
|
145
|
|
- } while ( ( index < count ) && ( next != 0 ) );
|
146
|
|
-
|
147
|
|
- return index;
|
148
|
|
-}
|
149
|
|
-
|
150
|
|
-/**************************************************************************
|
151
|
|
-GET_MEMSIZES - Retrieve the system memory map via any available means
|
152
|
|
-**************************************************************************/
|
153
|
|
-void get_memsizes ( void ) {
|
154
|
|
- /* Ensure we don't stomp bios data structutres.
|
155
|
|
- * the interrupt table: 0x000 - 0x3ff
|
156
|
|
- * the bios data area: 0x400 - 0x502
|
157
|
|
- * Dos variables: 0x502 - 0x5ff
|
158
|
|
- */
|
159
|
|
- static const unsigned min_addr = 0x600;
|
160
|
|
- unsigned i;
|
161
|
|
- unsigned basemem;
|
162
|
|
-
|
163
|
|
- /* Retrieve memory information from the BIOS */
|
164
|
|
- meminfo.basememsize = basememsize();
|
165
|
|
- basemem = meminfo.basememsize << 10;
|
166
|
|
- meminfo.memsize = memsize();
|
167
|
|
-#ifndef IGNORE_E820_MAP
|
168
|
|
- meminfo.map_count = meme820 ( meminfo.map, E820MAX );
|
169
|
|
-#else
|
170
|
|
- meminfo.map_count = 0;
|
171
|
|
-#endif
|
172
|
|
-
|
173
|
|
- /* If we don't have an e820 memory map fake it */
|
174
|
|
- if ( meminfo.map_count == 0 ) {
|
175
|
|
- meminfo.map_count = 2;
|
176
|
|
- meminfo.map[0].addr = 0;
|
177
|
|
- meminfo.map[0].size = meminfo.basememsize << 10;
|
178
|
|
- meminfo.map[0].type = E820_RAM;
|
179
|
|
- meminfo.map[1].addr = 1024*1024;
|
180
|
|
- meminfo.map[1].size = meminfo.memsize << 10;
|
181
|
|
- meminfo.map[1].type = E820_RAM;
|
182
|
|
- }
|
183
|
|
-
|
184
|
|
- /* Scrub the e820 map */
|
185
|
|
- for ( i = 0; i < meminfo.map_count; i++ ) {
|
186
|
|
- if ( meminfo.map[i].type != E820_RAM ) {
|
187
|
|
- continue;
|
188
|
|
- }
|
189
|
|
-
|
190
|
|
- /* Reserve the bios data structures */
|
191
|
|
- if ( meminfo.map[i].addr < min_addr ) {
|
192
|
|
- unsigned long delta;
|
193
|
|
- delta = min_addr - meminfo.map[i].addr;
|
194
|
|
- if ( delta > meminfo.map[i].size ) {
|
195
|
|
- delta = meminfo.map[i].size;
|
196
|
|
- }
|
197
|
|
- meminfo.map[i].addr = min_addr;
|
198
|
|
- meminfo.map[i].size -= delta;
|
199
|
|
- }
|
200
|
|
-
|
201
|
|
- /* Ensure the returned e820 map is in sync with the
|
202
|
|
- * actual memory state
|
203
|
|
- */
|
204
|
|
- if ( ( meminfo.map[i].addr < 0xa0000 ) &&
|
205
|
|
- (( meminfo.map[i].addr+meminfo.map[i].size ) > basemem )){
|
206
|
|
- if ( meminfo.map[i].addr <= basemem ) {
|
207
|
|
- meminfo.map[i].size = basemem
|
208
|
|
- - meminfo.map[i].addr;
|
209
|
|
- } else {
|
210
|
|
- meminfo.map[i].addr = basemem;
|
211
|
|
- meminfo.map[i].size = 0;
|
212
|
|
- }
|
213
|
|
- }
|
214
|
|
- }
|
215
|
|
-
|
216
|
|
-#ifdef DEBUG_MEMSIZES
|
217
|
|
- printf ( "basememsize %d\n", meminfo.basememsize );
|
218
|
|
- printf ( "memsize %d\n", meminfo.memsize );
|
219
|
|
- printf ( "Memory regions(%d):\n", meminfo.map_count );
|
220
|
|
- for ( i = 0; i < meminfo.map_count; i++ ) {
|
221
|
|
- unsigned long long r_start, r_end;
|
222
|
|
- r_start = meminfo.map[i].addr;
|
223
|
|
- r_end = r_start + meminfo.map[i].size;
|
224
|
|
- printf ( "[%X%X, %X%X) type %d\n",
|
225
|
|
- ( unsigned long ) ( r_start >> 32 ),
|
226
|
|
- ( unsigned long ) r_start,
|
227
|
|
- ( unsigned long ) ( r_end >> 32 ),
|
228
|
|
- ( unsigned long ) r_end,
|
229
|
|
- meminfo.map[i].type );
|
230
|
|
- }
|
231
|
|
-#endif
|
232
|
|
-
|
233
|
|
-}
|
234
|
|
-
|
235
|
|
-INIT_FN ( INIT_MEMSIZES, get_memsizes, NULL, NULL );
|