Browse Source

[sanboot] Add "sanhook" and "sanunhook" commands

Expose the multiple-SAN-drive capability of the iPXE core via the iPXE
command line by adding commands to hook and unhook additional drives.

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

+ 0
- 3
src/arch/i386/include/int13.h View File

@@ -261,7 +261,4 @@ struct master_boot_record {
261 261
 	uint16_t magic;
262 262
 } __attribute__ (( packed ));
263 263
 
264
-/** Use natural BIOS drive number */
265
-#define INT13_USE_NATURAL_DRIVE 0xff
266
-
267 264
 #endif /* INT13_H */

+ 11
- 0
src/arch/i386/include/ipxe/bios_sanboot.h View File

@@ -15,4 +15,15 @@ FILE_LICENCE ( GPL2_OR_LATER );
15 15
 #define SANBOOT_PREFIX_pcbios __pcbios_
16 16
 #endif
17 17
 
18
+/**
19
+ * Get default SAN drive number
20
+ *
21
+ * @ret drive		Default drive number
22
+ */
23
+static inline __always_inline unsigned int
24
+SANBOOT_INLINE ( pcbios, san_default_drive ) ( void ) {
25
+	/* Default to booting from first hard disk */
26
+	return 0x80;
27
+}
28
+
18 29
 #endif /* _IPXE_BIOS_SANBOOT_H */

+ 5
- 7
src/arch/i386/interface/pcbios/int13.c View File

@@ -1164,8 +1164,8 @@ static void int13_free ( struct refcnt *refcnt ) {
1164 1164
  * Hook INT 13 emulated drive
1165 1165
  *
1166 1166
  * @v uri		URI
1167
- * @v drive		Requested drive number
1168
- * @ret drive		Assigned drive number, or negative error
1167
+ * @v drive		Drive number
1168
+ * @ret rc		Return status code
1169 1169
  *
1170 1170
  * Registers the drive with the INT 13 emulation subsystem, and hooks
1171 1171
  * the INT 13 interrupt vector (if not already hooked).
@@ -1176,12 +1176,9 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
1176 1176
 	unsigned int natural_drive;
1177 1177
 	int rc;
1178 1178
 
1179
-	/* Calculate drive number */
1179
+	/* Calculate natural drive number */
1180 1180
 	get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
1181 1181
 	natural_drive = ( num_drives | 0x80 );
1182
-	if ( drive == INT13_USE_NATURAL_DRIVE )
1183
-		drive = natural_drive;
1184
-	drive |= 0x80;
1185 1182
 
1186 1183
 	/* Check that drive number is not in use */
1187 1184
 	list_for_each_entry ( int13, &int13s, list ) {
@@ -1231,7 +1228,7 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
1231 1228
 	/* Update BIOS drive count */
1232 1229
 	int13_set_num_drives();
1233 1230
 
1234
-	return int13->drive;
1231
+	return 0;
1235 1232
 
1236 1233
  err_guess_geometry:
1237 1234
  err_reopen_block:
@@ -1428,6 +1425,7 @@ static int int13_describe ( unsigned int drive ) {
1428 1425
 	return 0;
1429 1426
 }
1430 1427
 
1428
+PROVIDE_SANBOOT_INLINE ( pcbios, san_default_drive );
1431 1429
 PROVIDE_SANBOOT ( pcbios, san_hook, int13_hook );
1432 1430
 PROVIDE_SANBOOT ( pcbios, san_unhook, int13_unhook );
1433 1431
 PROVIDE_SANBOOT ( pcbios, san_boot, int13_boot );

+ 1
- 0
src/core/null_sanboot.c View File

@@ -38,6 +38,7 @@ static int null_san_describe ( unsigned int drive __unused ) {
38 38
 	return -EOPNOTSUPP;
39 39
 }
40 40
 
41
+PROVIDE_SANBOOT_INLINE ( null, san_default_drive );
41 42
 PROVIDE_SANBOOT ( null, san_hook, null_san_hook );
42 43
 PROVIDE_SANBOOT ( null, san_unhook, null_san_unhook );
43 44
 PROVIDE_SANBOOT ( null, san_boot, null_san_boot );

+ 114
- 20
src/hci/commands/sanboot_cmd.c View File

@@ -23,6 +23,7 @@
23 23
 #include <ipxe/command.h>
24 24
 #include <ipxe/parseopt.h>
25 25
 #include <ipxe/uri.h>
26
+#include <ipxe/sanboot.h>
26 27
 #include <usr/autoboot.h>
27 28
 
28 29
 FILE_LICENCE ( GPL2_OR_LATER );
@@ -34,47 +35,92 @@ FILE_LICENCE ( GPL2_OR_LATER );
34 35
  */
35 36
 
36 37
 /** "sanboot" options */
37
-struct sanboot_options {};
38
+struct sanboot_options {
39
+	/** Drive number */
40
+	unsigned int drive;
41
+	/** Do not describe SAN device */
42
+	int no_describe;
43
+	/** Keep SAN device */
44
+	int keep;
45
+};
38 46
 
39 47
 /** "sanboot" option list */
40
-static struct option_descriptor sanboot_opts[] = {};
48
+static struct option_descriptor sanboot_opts[] = {
49
+	OPTION_DESC ( "drive", 'd', required_argument,
50
+		      struct sanboot_options, drive, parse_integer ),
51
+	OPTION_DESC ( "no-describe", 'n', no_argument,
52
+		      struct sanboot_options, no_describe, parse_flag ),
53
+	OPTION_DESC ( "keep", 'k', no_argument,
54
+		      struct sanboot_options, keep, parse_flag ),
55
+};
56
+
57
+/** "sanhook" command descriptor */
58
+static struct command_descriptor sanhook_cmd =
59
+	COMMAND_DESC ( struct sanboot_options, sanboot_opts, 1, 1,
60
+		       "[--drive <drive>] [--no-describe] <root-path>" );
41 61
 
42 62
 /** "sanboot" command descriptor */
43 63
 static struct command_descriptor sanboot_cmd =
44
-	COMMAND_DESC ( struct sanboot_options, sanboot_opts, 1, 1,
45
-		       "<root-path>" );
64
+	COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 1,
65
+		       "[--drive <drive>] [--no-describe] [--keep] "
66
+		       "[<root-path>]" );
67
+
68
+/** "sanunhook" command descriptor */
69
+static struct command_descriptor sanunhook_cmd =
70
+	COMMAND_DESC ( struct sanboot_options, sanboot_opts, 0, 0,
71
+		       "[--drive <drive>]" );
46 72
 
47 73
 /**
48
- * The "sanboot" command
74
+ * The "sanboot", "sanhook" and "sanunhook" commands
49 75
  *
50 76
  * @v argc		Argument count
51 77
  * @v argv		Argument list
78
+ * @v default_flags	Default set of flags for uriboot()
79
+ * @v no_root_path_flags Additional flags to apply if no root path is present
52 80
  * @ret rc		Return status code
53 81
  */
54
-static int sanboot_exec ( int argc, char **argv ) {
82
+static int sanboot_core_exec ( int argc, char **argv,
83
+			       struct command_descriptor *cmd,
84
+			       int default_flags, int no_root_path_flags ) {
55 85
 	struct sanboot_options opts;
56 86
 	const char *root_path;
57 87
 	struct uri *uri;
88
+	int flags;
58 89
 	int rc;
59 90
 
91
+	/* Initialise options */
92
+	memset ( &opts, 0, sizeof ( opts ) );
93
+	opts.drive = san_default_drive();
94
+
60 95
 	/* Parse options */
61
-	if ( ( rc = parse_options ( argc, argv, &sanboot_cmd, &opts ) ) != 0 )
96
+	if ( ( rc = reparse_options ( argc, argv, cmd, &opts ) ) != 0 )
62 97
 		goto err_parse_options;
63 98
 
64
-	/* Parse root path */
65
-	root_path = argv[optind];
66
-	uri = parse_uri ( root_path );
67
-	if ( ! uri ) {
68
-		rc = -ENOMEM;
69
-		goto err_parse_uri;
99
+	/* Parse root path, if present */
100
+	if ( argc > optind ) {
101
+		root_path = argv[optind];
102
+		uri = parse_uri ( root_path );
103
+		if ( ! uri ) {
104
+			rc = -ENOMEM;
105
+			goto err_parse_uri;
106
+		}
107
+	} else {
108
+		root_path = NULL;
109
+		uri = NULL;
70 110
 	}
71 111
 
112
+	/* Construct flags */
113
+	flags = default_flags;
114
+	if ( opts.no_describe )
115
+		flags |= URIBOOT_NO_SAN_DESCRIBE;
116
+	if ( opts.keep )
117
+		flags |= URIBOOT_NO_SAN_UNHOOK;
118
+	if ( ! root_path )
119
+		flags |= no_root_path_flags;
120
+
72 121
 	/* Boot from root path */
73
-	if ( ( rc = uriboot ( NULL, uri ) ) != 0 ) {
74
-		printf ( "Could not boot from %s: %s\n",
75
-			 root_path, strerror ( rc ) );
122
+	if ( ( rc = uriboot ( NULL, uri, opts.drive, flags ) ) != 0 )
76 123
 		goto err_uriboot;
77
-	}
78 124
 
79 125
  err_uriboot:
80 126
 	uri_put ( uri );
@@ -83,8 +129,56 @@ static int sanboot_exec ( int argc, char **argv ) {
83 129
 	return rc;
84 130
 }
85 131
 
132
+/**
133
+ * The "sanhook" command
134
+ *
135
+ * @v argc		Argument count
136
+ * @v argv		Argument list
137
+ * @ret rc		Return status code
138
+ */
139
+static int sanhook_exec ( int argc, char **argv ) {
140
+	return sanboot_core_exec ( argc, argv, &sanhook_cmd,
141
+				   ( URIBOOT_NO_SAN_BOOT |
142
+				     URIBOOT_NO_SAN_UNHOOK ), 0 );
143
+}
144
+
145
+/**
146
+ * The "sanboot" command
147
+ *
148
+ * @v argc		Argument count
149
+ * @v argv		Argument list
150
+ * @ret rc		Return status code
151
+ */
152
+static int sanboot_exec ( int argc, char **argv ) {
153
+	return sanboot_core_exec ( argc, argv, &sanboot_cmd,
154
+				   0, URIBOOT_NO_SAN_UNHOOK );
155
+}
156
+
157
+/**
158
+ * The "sanunhook" command
159
+ *
160
+ * @v argc		Argument count
161
+ * @v argv		Argument list
162
+ * @ret rc		Return status code
163
+ */
164
+static int sanunhook_exec ( int argc, char **argv ) {
165
+	return sanboot_core_exec ( argc, argv, &sanunhook_cmd,
166
+				   ( URIBOOT_NO_SAN_DESCRIBE |
167
+				     URIBOOT_NO_SAN_BOOT ), 0 );
168
+}
169
+
86 170
 /** SAN commands */
87
-struct command sanboot_command __command = {
88
-	.name = "sanboot",
89
-	.exec = sanboot_exec,
171
+struct command sanboot_commands[] __command = {
172
+	{
173
+		.name = "sanhook",
174
+		.exec = sanhook_exec,
175
+	},
176
+	{
177
+		.name = "sanboot",
178
+		.exec = sanboot_exec,
179
+	},
180
+	{
181
+		.name = "sanunhook",
182
+		.exec = sanunhook_exec,
183
+	},
90 184
 };

+ 5
- 0
src/include/ipxe/null_sanboot.h View File

@@ -15,4 +15,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
15 15
 #define SANBOOT_PREFIX_null __null_
16 16
 #endif
17 17
 
18
+static inline __always_inline unsigned int
19
+SANBOOT_INLINE ( null, san_default_drive ) ( void ) {
20
+	return 0;
21
+}
22
+
18 23
 #endif /* _IPXE_NULL_SANBOOT_H */

+ 9
- 2
src/include/ipxe/sanboot.h View File

@@ -58,12 +58,19 @@ struct uri;
58 58
 /* Include all architecture-dependent sanboot API headers */
59 59
 #include <bits/sanboot.h>
60 60
 
61
+/**
62
+ * Get default SAN drive number
63
+ *
64
+ * @ret drive		Default drive number
65
+ */
66
+unsigned int san_default_drive ( void );
67
+
61 68
 /**
62 69
  * Hook SAN device
63 70
  *
64 71
  * @v uri		URI
65
- * @v drive		Requested drive number
66
- * @ret drive		Assigned drive number, or negative error
72
+ * @v drive		Drive number
73
+ * @ret rc		Return status code
67 74
  */
68 75
 int san_hook ( struct uri *uri, unsigned int drive );
69 76
 

+ 13
- 1
src/include/usr/autoboot.h View File

@@ -14,7 +14,19 @@ struct net_device;
14 14
 struct uri;
15 15
 struct settings;
16 16
 
17
-extern int uriboot ( struct uri *filename, struct uri *root_path );
17
+/** uriboot() flags */
18
+enum uriboot_flags {
19
+	URIBOOT_NO_SAN_DESCRIBE = 0x0001,
20
+	URIBOOT_NO_SAN_BOOT = 0x0002,
21
+	URIBOOT_NO_SAN_UNHOOK = 0x0004,
22
+};
23
+
24
+#define URIBOOT_NO_SAN ( URIBOOT_NO_SAN_DESCRIBE | \
25
+			 URIBOOT_NO_SAN_BOOT |	   \
26
+			 URIBOOT_NO_SAN_UNHOOK )
27
+
28
+extern int uriboot ( struct uri *filename, struct uri *root_path, int drive,
29
+		     unsigned int flags );
18 30
 extern struct uri *
19 31
 fetch_next_server_and_filename ( struct settings *settings );
20 32
 extern int netboot ( struct net_device *netdev );

+ 56
- 43
src/usr/autoboot.c View File

@@ -119,54 +119,37 @@ struct setting skip_san_boot_setting __setting ( SETTING_SANBOOT_EXTRA ) = {
119 119
  *
120 120
  * @v filename		Filename
121 121
  * @v root_path		Root path
122
+ * @v drive		SAN drive (if applicable)
123
+ * @v flags		Boot action flags
122 124
  * @ret rc		Return status code
125
+ *
126
+ * The somewhat tortuous flow of control in this function exists in
127
+ * order to ensure that the "sanboot" command remains identical in
128
+ * function to a SAN boot via a DHCP-specified root path, and to
129
+ * provide backwards compatibility for the "keep-san" and
130
+ * "skip-san-boot" options.
123 131
  */
124
-int uriboot ( struct uri *filename, struct uri *root_path ) {
125
-	int drive;
132
+int uriboot ( struct uri *filename, struct uri *root_path, int drive,
133
+	      unsigned int flags ) {
126 134
 	int rc;
127 135
 
128
-	/* Treat empty URIs as absent */
129
-	if ( filename && ( ! uri_has_path ( filename ) ) )
130
-		filename = NULL;
131
-	if ( root_path && ( ! uri_is_absolute ( root_path ) ) )
132
-		root_path = NULL;
133
-
134
-	/* If we have both a filename and a root path, ignore an
135
-	 * unsupported URI scheme in the root path, since it may
136
-	 * represent an NFS root.
137
-	 */
138
-	if ( filename && root_path &&
139
-	     ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) {
140
-		printf ( "Ignoring unsupported root path\n" );
141
-		root_path = NULL;
142
-	}
143
-
144
-	/* Check that we have something to boot */
145
-	if ( ! ( filename || root_path ) ) {
146
-		rc = -ENOENT_BOOT;
147
-		printf ( "Nothing to boot: %s\n", strerror ( rc ) );
148
-		goto err_no_boot;
149
-	}
150
-
151 136
 	/* Hook SAN device, if applicable */
152 137
 	if ( root_path ) {
153
-		drive = san_hook ( root_path, 0 );
154
-		if ( drive < 0 ) {
155
-			rc = drive;
138
+		if ( ( rc = san_hook ( root_path, drive ) ) != 0 ) {
156 139
 			printf ( "Could not open SAN device: %s\n",
157 140
 				 strerror ( rc ) );
158 141
 			goto err_san_hook;
159 142
 		}
160
-		printf ( "Registered as SAN device %#02x\n", drive );
161
-	} else {
162
-		drive = -ENODEV;
143
+		printf ( "Registered SAN device %#02x\n", drive );
163 144
 	}
164 145
 
165 146
 	/* Describe SAN device, if applicable */
166
-	if ( ( drive >= 0 ) && ( ( rc = san_describe ( drive ) ) != 0 ) ) {
167
-		printf ( "Could not describe SAN device %#02x: %s\n",
168
-			 drive, strerror ( rc ) );
169
-		goto err_san_describe;
147
+	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_DESCRIBE ) ) {
148
+		if ( ( rc = san_describe ( drive ) ) != 0 ) {
149
+			printf ( "Could not describe SAN device %#02x: %s\n",
150
+				 drive, strerror ( rc ) );
151
+			goto err_san_describe;
152
+		}
170 153
 	}
171 154
 
172 155
 	/* Allow a root-path-only boot with skip-san enabled to succeed */
@@ -192,7 +175,7 @@ int uriboot ( struct uri *filename, struct uri *root_path ) {
192 175
 	}
193 176
 
194 177
 	/* Attempt SAN boot if applicable */
195
-	if ( root_path ) {
178
+	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
196 179
 		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
197 180
 			printf ( "Booting from SAN device %#02x\n", drive );
198 181
 			rc = san_boot ( drive );
@@ -209,17 +192,15 @@ int uriboot ( struct uri *filename, struct uri *root_path ) {
209 192
 
210 193
  err_san_describe:
211 194
 	/* Unhook SAN device, if applicable */
212
-	if ( drive >= 0 ) {
195
+	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) {
213 196
 		if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) {
214
-			printf ( "Unregistering SAN device %#02x\n", drive );
215 197
 			san_unhook ( drive );
198
+			printf ( "Unregistered SAN device %#02x\n", drive );
216 199
 		} else {
217
-			printf ( "Preserving connection to SAN device %#02x\n",
218
-				 drive );
200
+			printf ( "Preserving SAN device %#02x\n", drive );
219 201
 		}
220 202
 	}
221 203
  err_san_hook:
222
- err_no_boot:
223 204
 	return rc;
224 205
 }
225 206
 
@@ -360,19 +341,51 @@ int netboot ( struct net_device *netdev ) {
360 341
 		goto err_pxe_menu_boot;
361 342
 	}
362 343
 
363
-	/* Fetch next server, filename and root path */
344
+	/* Fetch next server and filename */
364 345
 	filename = fetch_next_server_and_filename ( NULL );
365 346
 	if ( ! filename )
366 347
 		goto err_filename;
348
+	if ( ! uri_has_path ( filename ) ) {
349
+		/* Ignore empty filename */
350
+		uri_put ( filename );
351
+		filename = NULL;
352
+	}
353
+
354
+	/* Fetch root path */
367 355
 	root_path = fetch_root_path ( NULL );
368 356
 	if ( ! root_path )
369 357
 		goto err_root_path;
358
+	if ( ! uri_is_absolute ( root_path ) ) {
359
+		/* Ignore empty root path */
360
+		uri_put ( root_path );
361
+		root_path = NULL;
362
+	}
363
+
364
+	/* If we have both a filename and a root path, ignore an
365
+	 * unsupported URI scheme in the root path, since it may
366
+	 * represent an NFS root.
367
+	 */
368
+	if ( filename && root_path &&
369
+	     ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) {
370
+		printf ( "Ignoring unsupported root path\n" );
371
+		uri_put ( root_path );
372
+		root_path = NULL;
373
+	}
374
+
375
+	/* Check that we have something to boot */
376
+	if ( ! ( filename || root_path ) ) {
377
+		rc = -ENOENT_BOOT;
378
+		printf ( "Nothing to boot: %s\n", strerror ( rc ) );
379
+		goto err_no_boot;
380
+	}
370 381
 
371 382
 	/* Boot using next server, filename and root path */
372
-	if ( ( rc = uriboot ( filename, root_path ) ) != 0 )
383
+	if ( ( rc = uriboot ( filename, root_path, san_default_drive(),
384
+			      ( root_path ? 0 : URIBOOT_NO_SAN ) ) ) != 0 )
373 385
 		goto err_uriboot;
374 386
 
375 387
  err_uriboot:
388
+ err_no_boot:
376 389
 	uri_put ( root_path );
377 390
  err_root_path:
378 391
 	uri_put ( filename );

+ 1
- 1
src/usr/pxemenu.c View File

@@ -377,7 +377,7 @@ int pxe_menu_boot ( struct net_device *netdev ) {
377 377
 		return -ENOMEM;
378 378
 
379 379
 	/* Attempt boot */
380
-	rc = uriboot ( uri, NULL );
380
+	rc = uriboot ( uri, NULL, 0, URIBOOT_NO_SAN );
381 381
 	uri_put ( uri );
382 382
 	return rc;
383 383
 }

Loading…
Cancel
Save