ソースを参照

Replaced memsizes.c with smaller memmap.c, taking advantage of __data16,

and creating a memory map that's easier to work with than the E820 map.
tags/v0.9.3
Michael Brown 18年前
コミット
77a65075a6

+ 214
- 0
src/arch/i386/firmware/pcbios/memmap.c ファイルの表示

@@ -0,0 +1,214 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <errno.h>
21
+#include <realmode.h>
22
+#include <bios.h>
23
+#include <memmap.h>
24
+
25
+/**
26
+ * @file
27
+ *
28
+ * Memory mapping
29
+ *
30
+ */
31
+
32
+/** Magic value for INT 15,e820 calls */
33
+#define SMAP ( 0x534d4150 )
34
+
35
+/** An INT 15,e820 memory map entry */
36
+struct e820_entry {
37
+	/** Start of region */
38
+	uint64_t start;
39
+	/** Length of region */
40
+	uint64_t len;
41
+	/** Type of region */
42
+	uint32_t type;
43
+} __attribute__ (( packed ));
44
+
45
+#define E820_TYPE_RAM		1 /**< Normal memory */
46
+#define E820_TYPE_RESERVED	2 /**< Reserved and unavailable */
47
+#define E820_TYPE_ACPI		3 /**< ACPI reclaim memory */
48
+#define E820_TYPE_NVS		4 /**< ACPI NVS memory */
49
+
50
+/** Buffer for INT 15,e820 calls */
51
+static struct e820_entry __data16 ( e820buf );
52
+#define e820buf __use_data16 ( e820buf )
53
+
54
+/**
55
+ * Get size of base memory from BIOS free base memory counter
56
+ *
57
+ * @ret basemem		Base memory size, in kB
58
+ */
59
+static unsigned int basememsize ( void ) {
60
+	uint16_t basemem;
61
+
62
+	get_real ( basemem, BDA_SEG, 0x0013 );
63
+	DBG ( "Base memory size %dkB\n", basemem );
64
+	return basemem;
65
+}
66
+
67
+/**
68
+ * Get size of extended memory via INT 15,e801
69
+ *
70
+ * @ret extmem		Extended memory size, in kB, or 0
71
+ */
72
+static unsigned int extmemsize_e801 ( void ) {
73
+	uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k;
74
+	uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k;
75
+	unsigned int flags;
76
+	unsigned int extmem;
77
+
78
+	REAL_EXEC ( rm_mem_e801,
79
+		    "int $0x15\n\t"
80
+		    "pushfw\n\t"
81
+		    "popw %w0\n\t",
82
+		    5,
83
+		    OUT_CONSTRAINTS ( "=r" ( flags ),
84
+				      "=a" ( extmem_1m_to_16m_k ),
85
+				      "=b" ( extmem_16m_plus_64k ),
86
+				      "=c" ( confmem_1m_to_16m_k ),
87
+				      "=d" ( confmem_16m_plus_64k ) ),
88
+		    IN_CONSTRAINTS ( "a" ( 0xe801 ) ),
89
+		    CLOBBER ( "cc" ) );
90
+
91
+	if ( flags & CF )
92
+		return 0;
93
+
94
+	if ( ! ( extmem_1m_to_16m_k | extmem_16m_plus_64k ) ) {
95
+		extmem_1m_to_16m_k = confmem_1m_to_16m_k;
96
+		extmem_16m_plus_64k = confmem_16m_plus_64k;
97
+	}
98
+
99
+	extmem = ( extmem_1m_to_16m_k + ( extmem_16m_plus_64k * 64 ) );
100
+	DBG ( "Extended memory size %d+64*%d=%d kB\n",
101
+	      extmem_1m_to_16m_k, extmem_16m_plus_64k, extmem );
102
+	return extmem;
103
+}
104
+
105
+/**
106
+ * Get size of extended memory via INT 15,88
107
+ *
108
+ * @ret extmem		Extended memory size, in kB
109
+ */
110
+static unsigned int extmemsize_88 ( void ) {
111
+	uint16_t extmem;
112
+
113
+	REAL_EXEC ( rm_mem_88,
114
+		    "int $0x15\n\t"
115
+		    "jnc 1f\n\t"
116
+		    "xorw %%ax, %%ax\n\t"
117
+		    "\n1:\n\t",
118
+		    1,
119
+		    OUT_CONSTRAINTS ( "=a" ( extmem ) ),
120
+		    IN_CONSTRAINTS ( "a" ( 0x8800 ) ),
121
+		    CLOBBER ( "cc" ) );
122
+
123
+	DBG ( "Extended memory size %d kB\n", extmem );
124
+	return extmem;
125
+}
126
+
127
+/**
128
+ * Get size of extended memory
129
+ *
130
+ * @ret extmem		Extended memory size, in kB
131
+ */
132
+static unsigned int extmemsize ( void ) {
133
+	unsigned int extmem;
134
+
135
+	/* Try INT 15,e801 first, then fall back to INT 15,88 */
136
+	extmem = extmemsize_e801();
137
+	if ( ! extmem )
138
+		extmem = extmemsize_88();
139
+	return extmem;
140
+}
141
+
142
+/**
143
+ * Get e820 memory map
144
+ *
145
+ * @v memmap		Memory map to fill in
146
+ * @v entries		Maximum number of entries in memory map
147
+ * @ret rc		Return status code
148
+ */
149
+static int meme820 ( struct memory_region *memmap, unsigned int entries ) {
150
+	unsigned int index = 0;
151
+	uint32_t next = 0;
152
+	uint32_t smap;
153
+	unsigned int flags;
154
+	unsigned int discard_c, discard_d, discard_D;
155
+
156
+	do {
157
+		REAL_EXEC ( rm_mem_e820,
158
+			    "int $0x15\n\t"
159
+			    "pushfw\n\t"
160
+			    "popw %w0\n\t",
161
+			    6,
162
+			    OUT_CONSTRAINTS ( "=r" ( flags ),
163
+					      "=a" ( smap ),
164
+					      "=b" ( next ),
165
+					      "=D" ( discard_D ),
166
+					      "=c" ( discard_c ),
167
+					      "=d" ( discard_d ) ),
168
+			    IN_CONSTRAINTS ( "a" ( 0xe820 ),
169
+					     "b" ( next ),
170
+					     "D" ( &__from_data16 ( e820buf )),
171
+					     "c" ( sizeof ( e820buf ) ),
172
+					     "d" ( SMAP ) ),
173
+			    CLOBBER ( "memory" ) );
174
+		if ( smap != SMAP )
175
+			return -ENOTSUP;
176
+		if ( flags & CF )
177
+			break;
178
+		DBG ( "E820 region [%llx,%llx) type %d\n", e820buf.start,
179
+		      ( e820buf.start + e820buf.len ), ( int ) e820buf.type );
180
+		if ( e820buf.type != E820_TYPE_RAM )
181
+			continue;
182
+		memmap[index].start = e820buf.start;
183
+		memmap[index].end = e820buf.start + e820buf.len;
184
+		index++;
185
+	} while ( ( index < entries ) && ( next != 0 ) );
186
+	return 0;
187
+}
188
+
189
+/**
190
+ * Get memory map
191
+ *
192
+ * @v memmap		Memory map to fill in
193
+ * @v entries		Maximum number of entries in memory map (minimum 2)
194
+ */
195
+void get_memmap ( struct memory_region *memmap, unsigned int entries ) {
196
+	unsigned int basemem, extmem;
197
+	int rc;
198
+
199
+	/* Clear memory map */
200
+	memset ( memmap, 0, ( entries * sizeof ( *memmap ) ) );
201
+
202
+	/* Get base and extended memory sizes */
203
+	basemem = basememsize();
204
+	extmem = extmemsize();
205
+	
206
+	/* Try INT 15,e820 first */
207
+	if ( ( rc = meme820 ( memmap, entries ) ) == 0 )
208
+		return;
209
+
210
+	/* Fall back to constructing a map from basemem and extmem sizes */
211
+	memmap[0].end = ( basemem * 1024 );
212
+	memmap[1].start = 0x100000;
213
+	memmap[1].end = 0x100000 + ( extmem * 1024 );
214
+}

+ 0
- 235
src/arch/i386/firmware/pcbios/memsizes.c ファイルの表示

@@ -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 );

+ 23
- 0
src/arch/i386/include/memmap.h ファイルの表示

@@ -0,0 +1,23 @@
1
+#ifndef _MEMMAP_H
2
+#define _MEMMAP_H
3
+
4
+#include <stdint.h>
5
+
6
+/**
7
+ * @file
8
+ *
9
+ * Memory mapping
10
+ *
11
+ */
12
+
13
+/** A usable memory region */
14
+struct memory_region {
15
+	/** Physical start address */
16
+	uint64_t start;
17
+	/** Physical end address */
18
+	uint64_t end;
19
+};
20
+
21
+extern void get_memmap ( struct memory_region *memmap, unsigned int entries );
22
+
23
+#endif /* _MEMMAP_H */

+ 2
- 0
src/arch/i386/include/memsizes.h ファイルの表示

@@ -1,6 +1,8 @@
1 1
 #ifndef MEMSIZES_H
2 2
 #define MEMSIZES_H
3 3
 
4
+#warning "This header is no longer functional; use memmap.h instead"
5
+
4 6
 /*
5 7
  * These structures seem to be very i386 (and, in fact, PCBIOS)
6 8
  * specific, so I've moved them out of etherboot.h.

読み込み中…
キャンセル
保存