Browse Source

[vmware] Allow settings to be specified in the VMware .vmx file

Allow iPXE settings to be specified in the .vmx file via the VMware
GuestInfo mechanism.  For example:

    guestinfo.ipxe.filename = "http://boot.ipxe.org/demo/boot.php"
    guestinfo.ipxe.dns = "192.168.0.1"
    guestinfo.ipxe.net0.ip = "192.168.0.15"
    guestinfo.ipxe.net0.netmask = "255.255.255.0"
    guestinfo.ipxe.net0.gateway = "192.168.0.1"

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
a9cf527641

+ 1
- 0
src/arch/i386/include/bits/errfile.h View File

@@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
18 18
 #define ERRFILE_runtime		( ERRFILE_ARCH | ERRFILE_CORE | 0x00070000 )
19 19
 #define ERRFILE_vmware		( ERRFILE_ARCH | ERRFILE_CORE | 0x00080000 )
20 20
 #define ERRFILE_guestrpc	( ERRFILE_ARCH | ERRFILE_CORE | 0x00090000 )
21
+#define ERRFILE_guestinfo	( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
21 22
 
22 23
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
23 24
 #define ERRFILE_bzimage	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )

+ 281
- 0
src/arch/i386/interface/vmware/guestinfo.c View File

@@ -0,0 +1,281 @@
1
+/*
2
+ * Copyright (C) 2012 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
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+/** @file
22
+ *
23
+ * VMware GuestInfo settings
24
+ *
25
+ */
26
+
27
+#include <stdint.h>
28
+#include <stdlib.h>
29
+#include <stdio.h>
30
+#include <string.h>
31
+#include <errno.h>
32
+#include <ipxe/init.h>
33
+#include <ipxe/settings.h>
34
+#include <ipxe/netdevice.h>
35
+#include <ipxe/guestrpc.h>
36
+
37
+/** GuestInfo GuestRPC channel */
38
+static int guestinfo_channel;
39
+
40
+/**
41
+ * Fetch value of typed GuestInfo setting
42
+ *
43
+ * @v settings		Settings block
44
+ * @v setting		Setting to fetch
45
+ * @v type		Setting type to attempt (or NULL for default)
46
+ * @v data		Buffer to fill with setting data
47
+ * @v len		Length of buffer
48
+ * @ret found		Setting found in GuestInfo
49
+ * @ret len		Length of setting data, or negative error
50
+ */
51
+static int guestinfo_fetch_type ( struct settings *settings,
52
+				  struct setting *setting,
53
+				  struct setting_type *type,
54
+				  void *data, size_t len, int *found ) {
55
+	const char *parent_name = settings->parent->name;
56
+	char command[ 24 /* "info-get guestinfo.ipxe." */ +
57
+		      strlen ( parent_name ) + 1 /* "." */ +
58
+		      strlen ( setting->name ) + 1 /* "." */ +
59
+		      ( type ? strlen ( type->name ) : 0 ) + 1 /* NUL */ ];
60
+	struct setting *named_setting;
61
+	char *info;
62
+	int info_len;
63
+	int check_len;
64
+	int ret;
65
+
66
+	/* Construct info-get command */
67
+	snprintf ( command, sizeof ( command ),
68
+		   "info-get guestinfo.ipxe.%s%s%s%s%s",
69
+		   parent_name, ( parent_name[0] ? "." : "" ), setting->name,
70
+		   ( type ? "." : "" ), ( type ? type->name : "" ) );
71
+
72
+	/* Check for existence and obtain length of GuestInfo value */
73
+	info_len = guestrpc_command ( guestinfo_channel, command, NULL, 0 );
74
+	if ( info_len < 0 ) {
75
+		ret = info_len;
76
+		goto err_get_info_len;
77
+	}
78
+
79
+	/* Mark as found */
80
+	*found = 1;
81
+
82
+	/* Determine default type if necessary */
83
+	if ( ! type ) {
84
+		named_setting = find_setting ( setting->name );
85
+		type = ( named_setting ?
86
+			 named_setting->type : &setting_type_string );
87
+	}
88
+	assert ( type != NULL );
89
+
90
+	/* Allocate temporary block to hold GuestInfo value */
91
+	info = zalloc ( info_len + 1 /* NUL */ );
92
+	if ( ! info ) {
93
+		DBGC ( settings, "GuestInfo %p could not allocate %zd bytes\n",
94
+		       settings, info_len );
95
+		ret = -ENOMEM;
96
+		goto err_alloc;
97
+	}
98
+	info[info_len] = '\0';
99
+
100
+	/* Fetch GuestInfo value */
101
+	check_len = guestrpc_command ( guestinfo_channel, command,
102
+				       info, info_len );
103
+	if ( check_len < 0 ) {
104
+		ret = check_len;
105
+		goto err_get_info;
106
+	}
107
+	if ( check_len != info_len ) {
108
+		DBGC ( settings, "GuestInfo %p length mismatch (expected %d, "
109
+		       "got %d)\n", settings, info_len, check_len );
110
+		ret = -EIO;
111
+		goto err_get_info;
112
+	}
113
+	DBGC2 ( settings, "GuestInfo %p found %s = \"%s\"\n",
114
+		settings, &command[9] /* Skip "info-get " */, info );
115
+
116
+	/* Parse GuestInfo value according to type */
117
+	ret = type->parse ( info, data, len );
118
+	if ( ret < 0 ) {
119
+		DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: "
120
+		       "%s\n", settings, info, type->name, strerror ( ret ) );
121
+		goto err_parse;
122
+	}
123
+
124
+ err_parse:
125
+ err_get_info:
126
+	free ( info );
127
+ err_alloc:
128
+ err_get_info_len:
129
+	return ret;
130
+}
131
+
132
+/**
133
+ * Fetch value of GuestInfo setting
134
+ *
135
+ * @v settings		Settings block
136
+ * @v setting		Setting to fetch
137
+ * @v data		Buffer to fill with setting data
138
+ * @v len		Length of buffer
139
+ * @ret len		Length of setting data, or negative error
140
+ */
141
+static int guestinfo_fetch ( struct settings *settings,
142
+			     struct setting *setting,
143
+			     void *data, size_t len ) {
144
+	struct setting_type *type;
145
+	int found = 0;
146
+	int ret;
147
+
148
+	/* Try default type first */
149
+	ret = guestinfo_fetch_type ( settings, setting, NULL,
150
+				     data, len, &found );
151
+	if ( found )
152
+		return ret;
153
+
154
+	/* Otherwise, try all possible types */
155
+	for_each_table_entry ( type, SETTING_TYPES ) {
156
+		ret = guestinfo_fetch_type ( settings, setting, type,
157
+					     data, len, &found );
158
+		if ( found )
159
+			return ret;
160
+	}
161
+
162
+	/* Not found */
163
+	return -ENOENT;
164
+}
165
+
166
+/** GuestInfo settings operations */
167
+static struct settings_operations guestinfo_settings_operations = {
168
+	.fetch = guestinfo_fetch,
169
+};
170
+
171
+/** GuestInfo settings */
172
+static struct settings guestinfo_settings = {
173
+	.refcnt = NULL,
174
+	.siblings = LIST_HEAD_INIT ( guestinfo_settings.siblings ),
175
+	.children = LIST_HEAD_INIT ( guestinfo_settings.children ),
176
+	.op = &guestinfo_settings_operations,
177
+};
178
+
179
+/** Initialise GuestInfo settings */
180
+static void guestinfo_init ( void ) {
181
+	int rc;
182
+
183
+	/* Open GuestRPC channel */
184
+	guestinfo_channel = guestrpc_open();
185
+	if ( guestinfo_channel < 0 ) {
186
+		rc = guestinfo_channel;
187
+		DBG ( "GuestInfo could not open channel: %s\n",
188
+		      strerror ( rc ) );
189
+		return;
190
+	}
191
+
192
+	/* Register root GuestInfo settings */
193
+	if ( ( rc = register_settings ( &guestinfo_settings, NULL,
194
+					"vmware" ) ) != 0 ) {
195
+		DBG ( "GuestInfo could not register settings: %s\n",
196
+		      strerror ( rc ) );
197
+		return;
198
+	}
199
+}
200
+
201
+/** GuestInfo settings initialiser */
202
+struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
203
+	.initialise = guestinfo_init,
204
+};
205
+
206
+/**
207
+ * Create per-netdevice GuestInfo settings
208
+ *
209
+ * @v netdev		Network device
210
+ * @ret rc		Return status code
211
+ */
212
+static int guestinfo_net_probe ( struct net_device *netdev ) {
213
+	struct settings *settings;
214
+	int rc;
215
+
216
+	/* Do nothing unless we have a GuestInfo channel available */
217
+	if ( guestinfo_channel < 0 )
218
+		return 0;
219
+
220
+	/* Allocate and initialise settings block */
221
+	settings = zalloc ( sizeof ( *settings ) );
222
+	if ( ! settings ) {
223
+		rc = -ENOMEM;
224
+		goto err_alloc;
225
+	}
226
+	settings_init ( settings, &guestinfo_settings_operations, NULL, 0 );
227
+
228
+	/* Register settings */
229
+	if ( ( rc = register_settings ( settings, netdev_settings ( netdev ),
230
+					"vmware" ) ) != 0 ) {
231
+		DBGC ( settings, "GuestInfo %p could not register for %s: %s\n",
232
+		       settings, netdev->name, strerror ( rc ) );
233
+		goto err_register;
234
+	}
235
+	DBGC ( settings, "GuestInfo %p registered for %s\n",
236
+	       settings, netdev->name );
237
+
238
+	return 0;
239
+
240
+ err_register:
241
+	free ( settings );
242
+ err_alloc:
243
+	return rc;
244
+}
245
+
246
+/**
247
+ * Handle network device or link state change
248
+ *
249
+ * @v netdev		Network device
250
+ */
251
+static void guestinfo_net_notify ( struct net_device *netdev __unused ) {
252
+	/* Nothing to do */
253
+}
254
+
255
+/**
256
+ * Remove per-netdevice GuestInfo settings
257
+ *
258
+ * @v netdev		Network device
259
+ */
260
+static void guestinfo_net_remove ( struct net_device *netdev ) {
261
+	struct settings *parent = netdev_settings ( netdev );
262
+	struct settings *settings;
263
+
264
+	list_for_each_entry ( settings, &parent->children, siblings ) {
265
+		if ( settings->op == &guestinfo_settings_operations ) {
266
+			DBGC ( settings, "GuestInfo %p unregistered for %s\n",
267
+			       settings, netdev->name );
268
+			unregister_settings ( settings );
269
+			free ( settings );
270
+			return;
271
+		}
272
+	}
273
+}
274
+
275
+/** GuestInfo per-netdevice driver */
276
+struct net_driver guestinfo_net_driver __net_driver = {
277
+	.name = "GuestInfo",
278
+	.probe = guestinfo_net_probe,
279
+	.notify = guestinfo_net_notify,
280
+	.remove = guestinfo_net_remove,
281
+};

+ 4
- 1
src/config/config.c View File

@@ -280,13 +280,16 @@ REQUIRE_OBJECT ( tap );
280 280
 #endif
281 281
 
282 282
 /*
283
- * Drag in relevant BOFM entry points
283
+ * Drag in relevant sideband entry points
284 284
  */
285 285
 #ifdef CONFIG_BOFM
286 286
 #ifdef BOFM_EFI
287 287
 REQUIRE_OBJECT ( efi_bofm );
288 288
 #endif /* BOFM_EFI */
289 289
 #endif /* CONFIG_BOFM */
290
+#ifdef VMWARE_SETTINGS
291
+REQUIRE_OBJECT ( guestinfo );
292
+#endif /* VMWARE_SETTINGS */
290 293
 
291 294
 /*
292 295
  * Drag in selected keyboard map

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

@@ -10,5 +10,6 @@
10 10
 FILE_LICENCE ( GPL2_OR_LATER );
11 11
 
12 12
 //#define	CONFIG_BOFM	/* IBM's BladeCenter Open Fabric Manager */
13
+//#define	VMWARE_SETTINGS	/* VMware GuestInfo settings */
13 14
 
14 15
 #endif /* CONFIG_SIDEBAND_H */

Loading…
Cancel
Save