Browse Source

[settings] Expose memory map via settings mechanism

Allow memory map entries to be read using the syntax

  ${memmap/<region>.<properties>.<scale>}

where <region> is the index of the memory region, <properties> is a
bitmask where bit 0 represents the start address and bit 1 represents
the length (allowing the end address to be encoded by having both bits
0 and 1 set), and <scale> is the number of bits by which to shift the
result.

This allows for several values of interest to be encoded.  For
example:

  ${memmap/<region>.1.0:hexraw}   # 64-bit start address of <region>
  ${memmap/<region>.2.0:hexraw}   # 64-bit length of <region>, in bytes
  ${memmap/<region>.3.0:hexraw}   # 64-bit end address of <region>
  ${memmap/<region>.2.10:int32}   # Length of <region>, in kB
  ${memmap/<region>.2.20:int32}   # Length of <region>, in MB

The numeric encoding is slightly more sophisticated than described
here, allowing a single encoding to cover multiple regions.  (See the
source code for details.)  The primary use case for this feature is to
provide the total system memory size (in MB) via the "memsize"
predefined setting.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
c692a690da
4 changed files with 247 additions and 0 deletions
  1. 3
    0
      src/config/config.c
  2. 1
    0
      src/config/settings.h
  3. 242
    0
      src/core/memmap_settings.c
  4. 1
    0
      src/include/ipxe/errfile.h

+ 3
- 0
src/config/config.c View File

@@ -316,6 +316,9 @@ REQUIRE_OBJECT ( guestinfo );
316 316
 #ifdef CPUID_SETTINGS
317 317
 REQUIRE_OBJECT ( cpuid_settings );
318 318
 #endif
319
+#ifdef MEMMAP_SETTINGS
320
+REQUIRE_OBJECT ( memmap_settings );
321
+#endif
319 322
 
320 323
 /*
321 324
  * Drag in selected keyboard map

+ 1
- 0
src/config/settings.h View File

@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 #define	PCI_SETTINGS	/* PCI device settings */
13 13
 //#define	CPUID_SETTINGS	/* CPUID settings */
14
+//#define	MEMMAP_SETTINGS	/* Memory map settings */
14 15
 //#define	VMWARE_SETTINGS	/* VMware GuestInfo settings */
15 16
 
16 17
 #include <config/local/settings.h>

+ 242
- 0
src/core/memmap_settings.c View File

@@ -0,0 +1,242 @@
1
+/*
2
+ * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <string.h>
23
+#include <errno.h>
24
+#include <byteswap.h>
25
+#include <ipxe/init.h>
26
+#include <ipxe/settings.h>
27
+#include <ipxe/io.h>
28
+
29
+/** @file
30
+ *
31
+ * Memory map settings
32
+ *
33
+ * Memory map settings are numerically encoded as:
34
+ *
35
+ *  Bits 31-24	Number of regions, minus one
36
+ *  Bits 23-16	Starting region
37
+ *  Bits 15-11	Unused
38
+ *  Bit  10	Ignore non-existent regions (rather than generating an error)
39
+ *  Bit  9	Include length
40
+ *  Bit  8	Include start address
41
+ *  Bits 7-6	Unused
42
+ *  Bits 5-0	Scale factor (i.e. right shift count)
43
+ */
44
+
45
+/**
46
+ * Construct memory map setting tag
47
+ *
48
+ * @v start		Starting region
49
+ * @v count		Number of regions
50
+ * @v include_start	Include start address
51
+ * @v include_length	Include length
52
+ * @v ignore		Ignore non-existent regions
53
+ * @v scale		Scale factor
54
+ * @ret tag		Setting tag
55
+ */
56
+#define MEMMAP_TAG( start, count, include_start, include_length,	\
57
+		    ignore, scale )					\
58
+	( ( (start) << 16 ) | ( ( (count) - 1 ) << 24 ) |		\
59
+	  ( (ignore) << 10 ) | ( (include_length) << 9 ) |		\
60
+	  ( (include_start) << 8 ) | (scale) )
61
+
62
+/**
63
+ * Extract number of regions from setting tag
64
+ *
65
+ * @v tag		Setting tag
66
+ * @ret count		Number of regions
67
+ */
68
+#define MEMMAP_COUNT( tag ) ( ( ( (tag) >> 24 ) & 0xff ) + 1 )
69
+
70
+/**
71
+ * Extract starting region from setting tag
72
+ *
73
+ * @v tag		Setting tag
74
+ * @ret start		Starting region
75
+ */
76
+#define MEMMAP_START( tag ) ( ( (tag) >> 16 ) & 0xff )
77
+
78
+/**
79
+ * Extract ignore flag from setting tag
80
+ *
81
+ * @v tag		Setting tag
82
+ * @ret ignore		Ignore non-existent regions
83
+ */
84
+#define MEMMAP_IGNORE_NONEXISTENT( tag ) ( (tag) & 0x00000400UL )
85
+
86
+/**
87
+ * Extract length inclusion flag from setting tag
88
+ *
89
+ * @v tag		Setting tag
90
+ * @ret include_length	Include length
91
+ */
92
+#define MEMMAP_INCLUDE_LENGTH( tag ) ( (tag) & 0x00000200UL )
93
+
94
+/**
95
+ * Extract start address inclusion flag from setting tag
96
+ *
97
+ * @v tag		Setting tag
98
+ * @ret include_start	Include start address
99
+ */
100
+#define MEMMAP_INCLUDE_START( tag ) ( (tag) & 0x00000100UL )
101
+
102
+/**
103
+ * Extract scale factor from setting tag
104
+ *
105
+ * @v tag		Setting tag
106
+ * @v scale		Scale factor
107
+ */
108
+#define MEMMAP_SCALE( tag ) ( (tag) & 0x3f )
109
+
110
+/** Memory map settings scope */
111
+static struct settings_scope memmap_settings_scope;
112
+
113
+/**
114
+ * Check applicability of memory map setting
115
+ *
116
+ * @v settings		Settings block
117
+ * @v setting		Setting
118
+ * @ret applies		Setting applies within this settings block
119
+ */
120
+static int memmap_settings_applies ( struct settings *settings __unused,
121
+				     struct setting *setting ) {
122
+
123
+	return ( setting->scope == &memmap_settings_scope );
124
+}
125
+
126
+/**
127
+ * Fetch value of memory map setting
128
+ *
129
+ * @v settings		Settings block
130
+ * @v setting		Setting to fetch
131
+ * @v data		Buffer to fill with setting data
132
+ * @v len		Length of buffer
133
+ * @ret len		Length of setting data, or negative error
134
+ */
135
+static int memmap_settings_fetch ( struct settings *settings,
136
+				   struct setting *setting,
137
+				   void *data, size_t len ) {
138
+	struct memory_map memmap;
139
+	struct memory_region *region;
140
+	uint64_t result = 0;
141
+	unsigned int i;
142
+	unsigned int count;
143
+
144
+	DBGC ( settings, "MEMMAP start %d count %d %s%s%s%s scale %d\n",
145
+	       MEMMAP_START ( setting->tag ), MEMMAP_COUNT ( setting->tag ),
146
+	       ( MEMMAP_INCLUDE_START ( setting->tag ) ? "start" : "" ),
147
+	       ( ( MEMMAP_INCLUDE_START ( setting->tag ) &&
148
+		   MEMMAP_INCLUDE_LENGTH ( setting->tag ) ) ? "+" : "" ),
149
+	       ( MEMMAP_INCLUDE_LENGTH ( setting->tag ) ? "length" : "" ),
150
+	       ( MEMMAP_IGNORE_NONEXISTENT ( setting->tag ) ? " ignore" : "" ),
151
+	       MEMMAP_SCALE ( setting->tag ) );
152
+
153
+	/* Fetch memory map */
154
+	get_memmap ( &memmap );
155
+
156
+	/* Extract results from memory map */
157
+	count = MEMMAP_COUNT ( setting->tag );
158
+	for ( i = MEMMAP_START ( setting->tag ) ; count-- ; i++ ) {
159
+
160
+		/* Check that region exists */
161
+		if ( i >= memmap.count ) {
162
+			if ( MEMMAP_IGNORE_NONEXISTENT ( setting->tag ) ) {
163
+				continue;
164
+			} else {
165
+				DBGC ( settings, "MEMMAP region %d does not "
166
+				       "exist\n", i );
167
+				return -ENOENT;
168
+			}
169
+		}
170
+
171
+		/* Extract results from this region */
172
+		region = &memmap.regions[i];
173
+		if ( MEMMAP_INCLUDE_START ( setting->tag ) ) {
174
+			result += region->start;
175
+			DBGC ( settings, "MEMMAP %d start %08llx\n",
176
+			       i, region->start );
177
+		}
178
+		if ( MEMMAP_INCLUDE_LENGTH ( setting->tag ) ) {
179
+			result += ( region->end - region->start );
180
+			DBGC ( settings, "MEMMAP %d length %08llx\n",
181
+			       i, ( region->end - region->start ) );
182
+		}
183
+	}
184
+
185
+	/* Scale result */
186
+	result >>= MEMMAP_SCALE ( setting->tag );
187
+
188
+	/* Return result */
189
+	result = cpu_to_be64 ( result );
190
+	if ( len > sizeof ( result ) )
191
+		len = sizeof ( result );
192
+	memcpy ( data, &result, len );
193
+
194
+	/* Set type if not already specified */
195
+	if ( ! setting->type )
196
+		setting->type = &setting_type_hexraw;
197
+
198
+	return sizeof ( result );
199
+}
200
+
201
+/** Memory map settings operations */
202
+static struct settings_operations memmap_settings_operations = {
203
+	.applies = memmap_settings_applies,
204
+	.fetch = memmap_settings_fetch,
205
+};
206
+
207
+/** Memory map settings */
208
+static struct settings memmap_settings = {
209
+	.refcnt = NULL,
210
+	.siblings = LIST_HEAD_INIT ( memmap_settings.siblings ),
211
+	.children = LIST_HEAD_INIT ( memmap_settings.children ),
212
+	.op = &memmap_settings_operations,
213
+	.default_scope = &memmap_settings_scope,
214
+};
215
+
216
+/** Initialise memory map settings */
217
+static void memmap_settings_init ( void ) {
218
+	int rc;
219
+
220
+	if ( ( rc = register_settings ( &memmap_settings, NULL,
221
+					"memmap" ) ) != 0 ) {
222
+		DBG ( "MEMMAP could not register settings: %s\n",
223
+		      strerror ( rc ) );
224
+		return;
225
+	}
226
+}
227
+
228
+/** Memory map settings initialiser */
229
+struct init_fn memmap_settings_init_fn __init_fn ( INIT_NORMAL ) = {
230
+	.initialise = memmap_settings_init,
231
+};
232
+
233
+/** Memory map predefined settings */
234
+struct setting memmap_predefined_settings[] __setting ( SETTING_MISC ) = {
235
+	{
236
+		.name = "memsize",
237
+		.description = "Memory size (in MB)",
238
+		.tag = MEMMAP_TAG ( 0, 0x100, 0, 1, 1, 20 ),
239
+		.type = &setting_type_int32,
240
+		.scope = &memmap_settings_scope,
241
+	},
242
+};

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -285,6 +285,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
285 285
 #define ERRFILE_linux_pci	      ( ERRFILE_OTHER | 0x003c0000 )
286 286
 #define ERRFILE_pci_settings	      ( ERRFILE_OTHER | 0x003d0000 )
287 287
 #define ERRFILE_efi_reboot	      ( ERRFILE_OTHER | 0x003e0000 )
288
+#define ERRFILE_memmap_settings	      ( ERRFILE_OTHER | 0x003f0000 )
288 289
 
289 290
 /** @} */
290 291
 

Loading…
Cancel
Save