Browse Source

[autoboot] Connect SAN disk during a filename boot, if applicable

For performing installations direct to a SAN target, it can be very
useful to hook a SAN disk and then proceed to perform a filename boot.
For example, the user may wish to hook the (empty) SAN installation
disk and then boot into the OS installer via TFTP.  This provides an
alternative mechanism to using "keep-san" and relying on the BIOS to
fall through to boot from the installation media, which is unreliable
on many BIOSes.

When a root-path is specified in addition to a boot filename, attempt
to hook the root-path as a SAN disk before booting from the specified
filename.  Since the root-path may be used for non-SAN purposes
(e.g. an NFS root mount point), ignore the root-path if it contains a
URI scheme that we do not support.

Originally-implemented-by: Jarrod Johnson <jarrod.b.johnson@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
e088892a81

+ 16
- 4
src/hci/commands/sanboot_cmd.c View File

18
 
18
 
19
 #include <stdio.h>
19
 #include <stdio.h>
20
 #include <string.h>
20
 #include <string.h>
21
+#include <errno.h>
21
 #include <getopt.h>
22
 #include <getopt.h>
22
 #include <ipxe/command.h>
23
 #include <ipxe/command.h>
23
 #include <ipxe/parseopt.h>
24
 #include <ipxe/parseopt.h>
25
+#include <ipxe/uri.h>
24
 #include <usr/autoboot.h>
26
 #include <usr/autoboot.h>
25
 
27
 
26
 FILE_LICENCE ( GPL2_OR_LATER );
28
 FILE_LICENCE ( GPL2_OR_LATER );
52
 static int sanboot_exec ( int argc, char **argv ) {
54
 static int sanboot_exec ( int argc, char **argv ) {
53
 	struct sanboot_options opts;
55
 	struct sanboot_options opts;
54
 	const char *root_path;
56
 	const char *root_path;
57
+	struct uri *uri;
55
 	int rc;
58
 	int rc;
56
 
59
 
57
 	/* Parse options */
60
 	/* Parse options */
58
 	if ( ( rc = parse_options ( argc, argv, &sanboot_cmd, &opts ) ) != 0 )
61
 	if ( ( rc = parse_options ( argc, argv, &sanboot_cmd, &opts ) ) != 0 )
59
-		return rc;
62
+		goto err_parse_options;
60
 
63
 
61
 	/* Parse root path */
64
 	/* Parse root path */
62
 	root_path = argv[optind];
65
 	root_path = argv[optind];
66
+	uri = parse_uri ( root_path );
67
+	if ( ! uri ) {
68
+		rc = -ENOMEM;
69
+		goto err_parse_uri;
70
+	}
63
 
71
 
64
 	/* Boot from root path */
72
 	/* Boot from root path */
65
-	if ( ( rc = boot_root_path ( root_path ) ) != 0 ) {
73
+	if ( ( rc = uriboot ( NULL, uri ) ) != 0 ) {
66
 		printf ( "Could not boot from %s: %s\n",
74
 		printf ( "Could not boot from %s: %s\n",
67
 			 root_path, strerror ( rc ) );
75
 			 root_path, strerror ( rc ) );
68
-		return rc;
76
+		goto err_uriboot;
69
 	}
77
 	}
70
 
78
 
71
-	return 0;
79
+ err_uriboot:
80
+	uri_put ( uri );
81
+ err_parse_uri:
82
+ err_parse_options:
83
+	return rc;
72
 }
84
 }
73
 
85
 
74
 /** SAN commands */
86
 /** SAN commands */

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

235
 #define ERRFILE_ifmgmt_cmd	      ( ERRFILE_OTHER | 0x001d0000 )
235
 #define ERRFILE_ifmgmt_cmd	      ( ERRFILE_OTHER | 0x001d0000 )
236
 #define ERRFILE_fcmgmt_cmd	      ( ERRFILE_OTHER | 0x001e0000 )
236
 #define ERRFILE_fcmgmt_cmd	      ( ERRFILE_OTHER | 0x001e0000 )
237
 #define ERRFILE_gdbstub_cmd	      ( ERRFILE_OTHER | 0x001f0000 )
237
 #define ERRFILE_gdbstub_cmd	      ( ERRFILE_OTHER | 0x001f0000 )
238
+#define ERRFILE_sanboot_cmd	      ( ERRFILE_OTHER | 0x00200000 )
238
 
239
 
239
 /** @} */
240
 /** @} */
240
 
241
 

+ 5
- 3
src/include/usr/autoboot.h View File

11
 
11
 
12
 #include <ipxe/in.h>
12
 #include <ipxe/in.h>
13
 struct net_device;
13
 struct net_device;
14
+struct uri;
15
+struct settings;
14
 
16
 
17
+extern int uriboot ( struct uri *filename, struct uri *root_path );
18
+extern struct uri *
19
+fetch_next_server_and_filename ( struct settings *settings );
15
 extern int netboot ( struct net_device *netdev );
20
 extern int netboot ( struct net_device *netdev );
16
 extern int autoboot ( void );
21
 extern int autoboot ( void );
17
-extern int boot_next_server_and_filename ( struct in_addr next_server,
18
-					   const char *filename );
19
-extern int boot_root_path ( const char *root_path );
20
 
22
 
21
 extern int pxe_menu_boot ( struct net_device *netdev );
23
 extern int pxe_menu_boot ( struct net_device *netdev );
22
 
24
 

+ 2
- 0
src/include/usr/imgmgmt.h View File

11
 
11
 
12
 struct image;
12
 struct image;
13
 
13
 
14
+extern int imgdownload ( struct image *image, struct uri *uri,
15
+			 int ( * image_register ) ( struct image *image ) );
14
 extern int imgfetch ( struct image *image, const char *uri_string,
16
 extern int imgfetch ( struct image *image, const char *uri_string,
15
 		      int ( * image_register ) ( struct image *image ) );
17
 		      int ( * image_register ) ( struct image *image ) );
16
 extern int imgload ( struct image *image );
18
 extern int imgload ( struct image *image );

+ 185
- 130
src/usr/autoboot.c View File

27
 #include <ipxe/image.h>
27
 #include <ipxe/image.h>
28
 #include <ipxe/sanboot.h>
28
 #include <ipxe/sanboot.h>
29
 #include <ipxe/uri.h>
29
 #include <ipxe/uri.h>
30
+#include <ipxe/open.h>
30
 #include <ipxe/init.h>
31
 #include <ipxe/init.h>
31
 #include <usr/ifmgmt.h>
32
 #include <usr/ifmgmt.h>
32
 #include <usr/route.h>
33
 #include <usr/route.h>
57
 }
58
 }
58
 
59
 
59
 /**
60
 /**
60
- * Boot using next-server and filename
61
+ * Parse next-server and filename into a URI
61
  *
62
  *
62
- * @v filename		Boot filename
63
- * @ret rc		Return status code
63
+ * @v next_server	Next-server address
64
+ * @v filename		Filename
65
+ * @ret uri		URI, or NULL on failure
64
  */
66
  */
65
-int boot_next_server_and_filename ( struct in_addr next_server,
66
-				    const char *filename ) {
67
+static struct uri * parse_next_server_and_filename ( struct in_addr next_server,
68
+						     const char *filename ) {
67
 	struct uri *uri;
69
 	struct uri *uri;
68
-	struct image *image;
69
-	char buf[ 23 /* tftp://xxx.xxx.xxx.xxx/ */ +
70
-		  ( 3 * strlen(filename) ) /* completely URI-encoded */
71
-		  + 1 /* NUL */ ];
72
-	int filename_is_absolute;
73
-	int rc;
70
+	struct uri *tmp;
74
 
71
 
75
-	/* Construct URI */
72
+	/* Parse filename */
76
 	uri = parse_uri ( filename );
73
 	uri = parse_uri ( filename );
77
-	if ( ! uri ) {
78
-		printf ( "Could not parse \"%s\"\n", filename );
79
-		rc = -ENOMEM;
80
-		goto err_parse_uri;
81
-	}
82
-	filename_is_absolute = uri_is_absolute ( uri );
83
-	uri_put ( uri );
74
+	if ( ! uri )
75
+		return NULL;
84
 
76
 
85
 	/* Construct a tftp:// URI for the filename, if applicable.
77
 	/* Construct a tftp:// URI for the filename, if applicable.
86
 	 * We can't just rely on the current working URI, because the
78
 	 * We can't just rely on the current working URI, because the
88
 	 * filenames with and without initial slashes, which is
80
 	 * filenames with and without initial slashes, which is
89
 	 * significant for TFTP.
81
 	 * significant for TFTP.
90
 	 */
82
 	 */
91
-	if ( ! filename_is_absolute ) {
92
-		snprintf ( buf, sizeof ( buf ), "tftp://%s/",
93
-			   inet_ntoa ( next_server ) );
94
-		uri_encode ( filename, buf + strlen ( buf ),
95
-			     sizeof ( buf ) - strlen ( buf ), URI_PATH );
96
-		filename = buf;
83
+	if ( ! uri_is_absolute ( uri ) ) {
84
+		tmp = uri;
85
+		tmp->scheme = "tftp";
86
+		tmp->host = inet_ntoa ( next_server );
87
+		uri = uri_dup ( tmp );
88
+		uri_put ( tmp );
89
+		if ( ! uri )
90
+			return NULL;
97
 	}
91
 	}
98
 
92
 
99
-	/* Download and boot image */
100
-	image = alloc_image();
101
-	if ( ! image ) {
102
-		printf ( "Could not allocate image\n" );
103
-		rc = -ENOMEM;
104
-		goto err_alloc_image;
105
-	}
106
-	if ( ( rc = imgfetch ( image, filename,
107
-			       register_and_autoload_image ) ) != 0 ) {
108
-		printf ( "Could not fetch image: %s\n", strerror ( rc ) );
109
-		goto err_imgfetch;
110
-	}
111
-	if ( ( rc = imgexec ( image ) ) != 0 ) {
112
-		printf ( "Could not execute image: %s\n", strerror ( rc ) );
113
-		goto err_imgexec;
114
-	}
115
-
116
-	/* Drop image reference */
117
-	image_put ( image );
118
-	return 0;
119
-
120
- err_imgexec:
121
- err_imgfetch:
122
-	image_put ( image );
123
- err_alloc_image:
124
- err_parse_uri:
125
-	return rc;
93
+	return uri;
126
 }
94
 }
127
 
95
 
128
 /** The "keep-san" setting */
96
 /** The "keep-san" setting */
142
 };
110
 };
143
 
111
 
144
 /**
112
 /**
145
- * Boot using root path
113
+ * Boot from filename and root-path URIs
146
  *
114
  *
115
+ * @v filename		Filename
147
  * @v root_path		Root path
116
  * @v root_path		Root path
148
  * @ret rc		Return status code
117
  * @ret rc		Return status code
149
  */
118
  */
150
-int boot_root_path ( const char *root_path ) {
151
-	struct uri *uri;
119
+int uriboot ( struct uri *filename, struct uri *root_path ) {
120
+	struct image *image;
152
 	int drive;
121
 	int drive;
153
 	int rc;
122
 	int rc;
154
 
123
 
155
-	/* Parse URI */
156
-	uri = parse_uri ( root_path );
157
-	if ( ! uri ) {
158
-		printf ( "Could not parse \"%s\"\n", root_path );
124
+	/* Allocate image */
125
+	image = alloc_image();
126
+	if ( ! image ) {
127
+		printf ( "Could not allocate image\n" );
159
 		rc = -ENOMEM;
128
 		rc = -ENOMEM;
160
-		goto err_parse_uri;
129
+		goto err_alloc_image;
130
+	}
131
+
132
+	/* Treat empty URIs as absent */
133
+	if ( filename && ( ! filename->path ) )
134
+		filename = NULL;
135
+	if ( root_path && ( ! uri_is_absolute ( root_path ) ) )
136
+		root_path = NULL;
137
+
138
+	/* If we have both a filename and a root path, ignore an
139
+	 * unsupported URI scheme in the root path, since it may
140
+	 * represent an NFS root.
141
+	 */
142
+	if ( filename && root_path &&
143
+	     ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) {
144
+		printf ( "Ignoring unsupported root path\n" );
145
+		root_path = NULL;
161
 	}
146
 	}
162
 
147
 
163
-	/* Hook SAN device */
164
-	if ( ( drive = san_hook ( uri, 0 ) ) < 0 ) {
165
-		rc = drive;
166
-		printf ( "Could not open SAN device: %s\n",
167
-			 strerror ( rc ) );
168
-		goto err_open;
148
+	/* Hook SAN device, if applicable */
149
+	if ( root_path ) {
150
+		drive = san_hook ( root_path, 0 );
151
+		if ( drive < 0 ) {
152
+			rc = drive;
153
+			printf ( "Could not open SAN device: %s\n",
154
+				 strerror ( rc ) );
155
+			goto err_san_hook;
156
+		}
157
+		printf ( "Registered as SAN device %#02x\n", drive );
158
+	} else {
159
+		drive = -ENODEV;
169
 	}
160
 	}
170
-	printf ( "Registered as SAN device %#02x\n", drive );
171
 
161
 
172
-	/* Describe SAN device */
173
-	if ( ( rc = san_describe ( drive ) ) != 0 ) {
162
+	/* Describe SAN device, if applicable */
163
+	if ( ( drive >= 0 ) && ( ( rc = san_describe ( drive ) ) != 0 ) ) {
174
 		printf ( "Could not describe SAN device %#02x: %s\n",
164
 		printf ( "Could not describe SAN device %#02x: %s\n",
175
 			 drive, strerror ( rc ) );
165
 			 drive, strerror ( rc ) );
176
-		goto err_describe;
166
+		goto err_san_describe;
177
 	}
167
 	}
178
 
168
 
179
-	/* Boot from SAN device */
180
-	if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) != 0 ) {
181
-		printf ( "Skipping boot from SAN device %#02x\n", drive );
169
+	/* Attempt filename or SAN boot as applicable */
170
+	if ( filename ) {
171
+		if ( ( rc = imgdownload ( image, filename,
172
+					  register_and_autoexec_image ) ) !=0){
173
+			printf ( "Could not chain image: %s\n",
174
+				 strerror ( rc ) );
175
+		}
176
+	} else if ( root_path ) {
177
+		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
178
+			printf ( "Booting from SAN device %#02x\n", drive );
179
+			rc = san_boot ( drive );
180
+			printf ( "Boot from SAN device %#02x failed: %s\n",
181
+				 drive, strerror ( rc ) );
182
+		} else {
183
+			printf ( "Skipping boot from SAN device %#02x\n",
184
+				 drive );
185
+			rc = 0;
186
+		}
182
 	} else {
187
 	} else {
183
-		printf ( "Booting from SAN device %#02x\n", drive );
184
-		rc = san_boot ( drive );
185
-		printf ( "Boot from SAN device %#02x failed: %s\n",
186
-			 drive, strerror ( rc ) );
188
+		printf ( "No filename or root path specified\n" );
189
+		rc = -ENOENT;
187
 	}
190
 	}
188
 
191
 
189
-	/* Leave drive registered, if instructed to do so */
190
-	if ( fetch_intz_setting ( NULL, &keep_san_setting ) != 0 ) {
191
-		printf ( "Preserving connection to SAN device %#02x\n",
192
-			 drive );
193
-		goto err_keep_san;
192
+ err_san_describe:
193
+	/* Unhook SAN device, if applicable */
194
+	if ( drive >= 0 ) {
195
+		if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) {
196
+			printf ( "Unregistering SAN device %#02x\n", drive );
197
+			san_unhook ( drive );
198
+		} else {
199
+			printf ( "Preserving connection to SAN device %#02x\n",
200
+				 drive );
201
+		}
194
 	}
202
 	}
195
-
196
-	/* Unhook SAN deivce */
197
-	printf ( "Unregistering SAN device %#02x\n", drive );
198
-	san_unhook ( drive );
199
-
200
-	/* Drop URI reference */
201
-	uri_put ( uri );
202
-
203
-	return 0;
204
-
205
- err_keep_san:
206
- err_describe:
207
- err_open:
208
-	uri_put ( uri );
209
- err_parse_uri:
203
+ err_san_hook:
204
+	image_put ( image );
205
+ err_alloc_image:
210
 	return rc;
206
 	return rc;
211
 }
207
 }
212
 
208
 
227
 }
223
 }
228
 
224
 
229
 /**
225
 /**
230
- * Boot from a network device
226
+ * Fetch next-server and filename settings into a URI
231
  *
227
  *
232
- * @v netdev		Network device
233
- * @ret rc		Return status code
228
+ * @v settings		Settings block
229
+ * @ret uri		URI, or NULL on failure
234
  */
230
  */
235
-int netboot ( struct net_device *netdev ) {
231
+struct uri * fetch_next_server_and_filename ( struct settings *settings ) {
232
+	struct in_addr next_server;
233
+	char filename[256];
234
+
235
+	/* Fetch next-server setting */
236
+	fetch_ipv4_setting ( settings, &next_server_setting, &next_server );
237
+	if ( next_server.s_addr )
238
+		printf ( "Next server: %s\n", inet_ntoa ( next_server ) );
239
+
240
+	/* Fetch filename setting */
241
+	fetch_string_setting ( settings, &filename_setting,
242
+			       filename, sizeof ( filename ) );
243
+	if ( filename[0] )
244
+		printf ( "Filename: %s\n", filename );
245
+
246
+	return parse_next_server_and_filename ( next_server, filename );
247
+}
248
+
249
+/**
250
+ * Fetch root-path setting into a URI
251
+ *
252
+ * @v settings		Settings block
253
+ * @ret uri		URI, or NULL on failure
254
+ */
255
+static struct uri * fetch_root_path ( struct settings *settings ) {
256
+	char root_path[256];
257
+
258
+	/* Fetch root-path setting */
259
+	fetch_string_setting ( settings, &root_path_setting,
260
+			       root_path, sizeof ( root_path ) );
261
+	if ( root_path[0] )
262
+		printf ( "Root path: %s\n", root_path );
263
+
264
+	return parse_uri ( root_path );
265
+}
266
+
267
+/**
268
+ * Check whether or not we have a usable PXE menu
269
+ *
270
+ * @ret have_menu	A usable PXE menu is present
271
+ */
272
+static int have_pxe_menu ( void ) {
236
 	struct setting vendor_class_id_setting
273
 	struct setting vendor_class_id_setting
237
 		= { .tag = DHCP_VENDOR_CLASS_ID };
274
 		= { .tag = DHCP_VENDOR_CLASS_ID };
238
 	struct setting pxe_discovery_control_setting
275
 	struct setting pxe_discovery_control_setting
240
 	struct setting pxe_boot_menu_setting
277
 	struct setting pxe_boot_menu_setting
241
 		= { .tag = DHCP_PXE_BOOT_MENU };
278
 		= { .tag = DHCP_PXE_BOOT_MENU };
242
 	char buf[256];
279
 	char buf[256];
243
-	struct in_addr next_server;
244
 	unsigned int pxe_discovery_control;
280
 	unsigned int pxe_discovery_control;
281
+
282
+	fetch_string_setting ( NULL, &vendor_class_id_setting,
283
+			       buf, sizeof ( buf ) );
284
+	pxe_discovery_control =
285
+		fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
286
+
287
+	return ( ( strcmp ( buf, "PXEClient" ) == 0 ) &&
288
+		 setting_exists ( NULL, &pxe_boot_menu_setting ) &&
289
+		 ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) &&
290
+		       setting_exists ( NULL, &filename_setting ) ) ) );
291
+}
292
+
293
+/**
294
+ * Boot from a network device
295
+ *
296
+ * @v netdev		Network device
297
+ * @ret rc		Return status code
298
+ */
299
+int netboot ( struct net_device *netdev ) {
300
+	struct uri *filename;
301
+	struct uri *root_path;
245
 	int rc;
302
 	int rc;
246
 
303
 
247
 	/* Close all other network devices */
304
 	/* Close all other network devices */
249
 
306
 
250
 	/* Open device and display device status */
307
 	/* Open device and display device status */
251
 	if ( ( rc = ifopen ( netdev ) ) != 0 )
308
 	if ( ( rc = ifopen ( netdev ) ) != 0 )
252
-		return rc;
309
+		goto err_ifopen;
253
 	ifstat ( netdev );
310
 	ifstat ( netdev );
254
 
311
 
255
 	/* Configure device via DHCP */
312
 	/* Configure device via DHCP */
256
 	if ( ( rc = dhcp ( netdev ) ) != 0 )
313
 	if ( ( rc = dhcp ( netdev ) ) != 0 )
257
-		return rc;
314
+		goto err_dhcp;
258
 	route();
315
 	route();
259
 
316
 
260
 	/* Try PXE menu boot, if applicable */
317
 	/* Try PXE menu boot, if applicable */
261
-	fetch_string_setting ( NULL, &vendor_class_id_setting,
262
-			       buf, sizeof ( buf ) );
263
-	pxe_discovery_control =
264
-		fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
265
-	if ( ( strcmp ( buf, "PXEClient" ) == 0 ) &&
266
-	     setting_exists ( NULL, &pxe_boot_menu_setting ) &&
267
-	     ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) &&
268
-		   setting_exists ( NULL, &filename_setting ) ) ) ) {
318
+	if ( have_pxe_menu() ) {
269
 		printf ( "Booting from PXE menu\n" );
319
 		printf ( "Booting from PXE menu\n" );
270
-		return pxe_menu_boot ( netdev );
320
+		rc = pxe_menu_boot ( netdev );
321
+		goto err_pxe_menu_boot;
271
 	}
322
 	}
272
 
323
 
273
-	/* Try to download and boot whatever we are given as a filename */
274
-	fetch_ipv4_setting ( NULL, &next_server_setting, &next_server );
275
-	fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) );
276
-	if ( buf[0] ) {
277
-		printf ( "Booting from filename \"%s\"\n", buf );
278
-		return boot_next_server_and_filename ( next_server, buf );
279
-	}
280
-	
281
-	/* No filename; try the root path */
282
-	fetch_string_setting ( NULL, &root_path_setting, buf, sizeof ( buf ) );
283
-	if ( buf[0] ) {
284
-		printf ( "Booting from root path \"%s\"\n", buf );
285
-		return boot_root_path ( buf );
286
-	}
287
-
288
-	printf ( "No filename or root path specified\n" );
289
-	return -ENOENT;
324
+	/* Fetch next server, filename and root path */
325
+	filename = fetch_next_server_and_filename ( NULL );
326
+	if ( ! filename )
327
+		goto err_filename;
328
+	root_path = fetch_root_path ( NULL );
329
+	if ( ! root_path )
330
+		goto err_root_path;
331
+
332
+	/* Boot using next server, filename and root path */
333
+	if ( ( rc = uriboot ( filename, root_path ) ) != 0 )
334
+		goto err_uriboot;
335
+
336
+ err_uriboot:
337
+	uri_put ( root_path );
338
+ err_root_path:
339
+	uri_put ( filename );
340
+ err_filename:
341
+ err_pxe_menu_boot:
342
+ err_dhcp:
343
+ err_ifopen:
344
+	return rc;
290
 }
345
 }
291
 
346
 
292
 /**
347
 /**

+ 37
- 14
src/usr/imgmgmt.c View File

36
  */
36
  */
37
 
37
 
38
 /**
38
 /**
39
- * Fetch an image
39
+ * Download an image
40
  *
40
  *
41
- * @v uri_string	URI as a string (e.g. "http://www.nowhere.com/vmlinuz")
42
- * @v name		Name for image, or NULL
43
- * @v register_image	Image registration routine
41
+ * @v image		Image
42
+ * @v uri		URI
43
+ * @v image_register	Action to take upon a successful download
44
  * @ret rc		Return status code
44
  * @ret rc		Return status code
45
  */
45
  */
46
-int imgfetch ( struct image *image, const char *uri_string,
47
-	       int ( * image_register ) ( struct image *image ) ) {
48
-	char uri_string_redacted[ strlen ( uri_string ) + 3 /* "***" */
49
-				  + 1 /* NUL */ ];
50
-	struct uri *uri;
46
+int imgdownload ( struct image *image, struct uri *uri,
47
+		  int ( * image_register ) ( struct image *image ) ) {
48
+	size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 );
49
+	char uri_string_redacted[len];
51
 	const char *password;
50
 	const char *password;
52
 	int rc;
51
 	int rc;
53
 
52
 
54
-	if ( ! ( uri = parse_uri ( uri_string ) ) )
55
-		return -ENOMEM;
56
-
53
+	/* Set image URI */
57
 	image_set_uri ( image, uri );
54
 	image_set_uri ( image, uri );
58
 
55
 
59
 	/* Redact password portion of URI, if necessary */
56
 	/* Redact password portion of URI, if necessary */
64
 		      uri, URI_ALL );
61
 		      uri, URI_ALL );
65
 	uri->password = password;
62
 	uri->password = password;
66
 
63
 
64
+	/* Create downloader */
67
 	if ( ( rc = create_downloader ( &monojob, image, image_register,
65
 	if ( ( rc = create_downloader ( &monojob, image, image_register,
68
-					LOCATION_URI, uri ) ) == 0 )
69
-		rc = monojob_wait ( uri_string_redacted );
66
+					LOCATION_URI, uri ) ) != 0 )
67
+		return rc;
68
+
69
+	/* Wait for download to complete */
70
+	if ( ( rc = monojob_wait ( uri_string_redacted ) ) != 0 )
71
+		return rc;
72
+
73
+	return 0;
74
+}
75
+
76
+/**
77
+ * Fetch an image
78
+ *
79
+ * @v image		Image
80
+ * @v uri_string	URI as a string (e.g. "http://www.nowhere.com/vmlinuz")
81
+ * @v image_register	Action to take upon a successful fetch
82
+ * @ret rc		Return status code
83
+ */
84
+int imgfetch ( struct image *image, const char *uri_string,
85
+	       int ( * image_register ) ( struct image *image ) ) {
86
+	struct uri *uri;
87
+	int rc;
88
+
89
+	if ( ! ( uri = parse_uri ( uri_string ) ) )
90
+		return -ENOMEM;
91
+
92
+	rc = imgdownload ( image, uri, image_register );
70
 
93
 
71
 	uri_put ( uri );
94
 	uri_put ( uri );
72
 	return rc;
95
 	return rc;

+ 11
- 8
src/usr/pxemenu.c View File

31
 #include <ipxe/keys.h>
31
 #include <ipxe/keys.h>
32
 #include <ipxe/timer.h>
32
 #include <ipxe/timer.h>
33
 #include <ipxe/process.h>
33
 #include <ipxe/process.h>
34
+#include <ipxe/uri.h>
34
 #include <usr/dhcpmgmt.h>
35
 #include <usr/dhcpmgmt.h>
35
 #include <usr/autoboot.h>
36
 #include <usr/autoboot.h>
36
 
37
 
346
 	struct pxe_menu *menu;
347
 	struct pxe_menu *menu;
347
 	unsigned int pxe_type;
348
 	unsigned int pxe_type;
348
 	struct settings *pxebs_settings;
349
 	struct settings *pxebs_settings;
349
-	struct in_addr next_server;
350
-	char filename[256];
350
+	struct uri *uri;
351
 	int rc;
351
 	int rc;
352
 
352
 
353
 	/* Parse and allocate boot menu */
353
 	/* Parse and allocate boot menu */
372
 	if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 )
372
 	if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 )
373
 		return rc;
373
 		return rc;
374
 
374
 
375
-	/* Attempt boot */
375
+	/* Fetch next server and filename */
376
 	pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
376
 	pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
377
 	assert ( pxebs_settings );
377
 	assert ( pxebs_settings );
378
-	fetch_ipv4_setting ( pxebs_settings, &next_server_setting,
379
-			     &next_server );
380
-	fetch_string_setting ( pxebs_settings, &filename_setting,
381
-			       filename, sizeof ( filename ) );
382
-	return boot_next_server_and_filename ( next_server, filename );
378
+	uri = fetch_next_server_and_filename ( pxebs_settings );
379
+	if ( ! uri )
380
+		return -ENOMEM;
381
+
382
+	/* Attempt boot */
383
+	rc = uriboot ( uri, NULL );
384
+	uri_put ( uri );
385
+	return rc;
383
 }
386
 }

Loading…
Cancel
Save