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
 	uint16_t magic;
261
 	uint16_t magic;
262
 } __attribute__ (( packed ));
262
 } __attribute__ (( packed ));
263
 
263
 
264
-/** Use natural BIOS drive number */
265
-#define INT13_USE_NATURAL_DRIVE 0xff
266
-
267
 #endif /* INT13_H */
264
 #endif /* INT13_H */

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

15
 #define SANBOOT_PREFIX_pcbios __pcbios_
15
 #define SANBOOT_PREFIX_pcbios __pcbios_
16
 #endif
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
 #endif /* _IPXE_BIOS_SANBOOT_H */
29
 #endif /* _IPXE_BIOS_SANBOOT_H */

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

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

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

38
 	return -EOPNOTSUPP;
38
 	return -EOPNOTSUPP;
39
 }
39
 }
40
 
40
 
41
+PROVIDE_SANBOOT_INLINE ( null, san_default_drive );
41
 PROVIDE_SANBOOT ( null, san_hook, null_san_hook );
42
 PROVIDE_SANBOOT ( null, san_hook, null_san_hook );
42
 PROVIDE_SANBOOT ( null, san_unhook, null_san_unhook );
43
 PROVIDE_SANBOOT ( null, san_unhook, null_san_unhook );
43
 PROVIDE_SANBOOT ( null, san_boot, null_san_boot );
44
 PROVIDE_SANBOOT ( null, san_boot, null_san_boot );

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

23
 #include <ipxe/command.h>
23
 #include <ipxe/command.h>
24
 #include <ipxe/parseopt.h>
24
 #include <ipxe/parseopt.h>
25
 #include <ipxe/uri.h>
25
 #include <ipxe/uri.h>
26
+#include <ipxe/sanboot.h>
26
 #include <usr/autoboot.h>
27
 #include <usr/autoboot.h>
27
 
28
 
28
 FILE_LICENCE ( GPL2_OR_LATER );
29
 FILE_LICENCE ( GPL2_OR_LATER );
34
  */
35
  */
35
 
36
 
36
 /** "sanboot" options */
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
 /** "sanboot" option list */
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
 /** "sanboot" command descriptor */
62
 /** "sanboot" command descriptor */
43
 static struct command_descriptor sanboot_cmd =
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
  * @v argc		Argument count
76
  * @v argc		Argument count
51
  * @v argv		Argument list
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
  * @ret rc		Return status code
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
 	struct sanboot_options opts;
85
 	struct sanboot_options opts;
56
 	const char *root_path;
86
 	const char *root_path;
57
 	struct uri *uri;
87
 	struct uri *uri;
88
+	int flags;
58
 	int rc;
89
 	int rc;
59
 
90
 
91
+	/* Initialise options */
92
+	memset ( &opts, 0, sizeof ( opts ) );
93
+	opts.drive = san_default_drive();
94
+
60
 	/* Parse options */
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
 		goto err_parse_options;
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
 	/* Boot from root path */
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
 		goto err_uriboot;
123
 		goto err_uriboot;
77
-	}
78
 
124
 
79
  err_uriboot:
125
  err_uriboot:
80
 	uri_put ( uri );
126
 	uri_put ( uri );
83
 	return rc;
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
 /** SAN commands */
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
 #define SANBOOT_PREFIX_null __null_
15
 #define SANBOOT_PREFIX_null __null_
16
 #endif
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
 #endif /* _IPXE_NULL_SANBOOT_H */
23
 #endif /* _IPXE_NULL_SANBOOT_H */

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

58
 /* Include all architecture-dependent sanboot API headers */
58
 /* Include all architecture-dependent sanboot API headers */
59
 #include <bits/sanboot.h>
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
  * Hook SAN device
69
  * Hook SAN device
63
  *
70
  *
64
  * @v uri		URI
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
 int san_hook ( struct uri *uri, unsigned int drive );
75
 int san_hook ( struct uri *uri, unsigned int drive );
69
 
76
 

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

14
 struct uri;
14
 struct uri;
15
 struct settings;
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
 extern struct uri *
30
 extern struct uri *
19
 fetch_next_server_and_filename ( struct settings *settings );
31
 fetch_next_server_and_filename ( struct settings *settings );
20
 extern int netboot ( struct net_device *netdev );
32
 extern int netboot ( struct net_device *netdev );

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

119
  *
119
  *
120
  * @v filename		Filename
120
  * @v filename		Filename
121
  * @v root_path		Root path
121
  * @v root_path		Root path
122
+ * @v drive		SAN drive (if applicable)
123
+ * @v flags		Boot action flags
122
  * @ret rc		Return status code
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
 	int rc;
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
 	/* Hook SAN device, if applicable */
136
 	/* Hook SAN device, if applicable */
152
 	if ( root_path ) {
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
 			printf ( "Could not open SAN device: %s\n",
139
 			printf ( "Could not open SAN device: %s\n",
157
 				 strerror ( rc ) );
140
 				 strerror ( rc ) );
158
 			goto err_san_hook;
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
 	/* Describe SAN device, if applicable */
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
 	/* Allow a root-path-only boot with skip-san enabled to succeed */
155
 	/* Allow a root-path-only boot with skip-san enabled to succeed */
192
 	}
175
 	}
193
 
176
 
194
 	/* Attempt SAN boot if applicable */
177
 	/* Attempt SAN boot if applicable */
195
-	if ( root_path ) {
178
+	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_BOOT ) ) {
196
 		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
179
 		if ( fetch_intz_setting ( NULL, &skip_san_boot_setting) == 0 ) {
197
 			printf ( "Booting from SAN device %#02x\n", drive );
180
 			printf ( "Booting from SAN device %#02x\n", drive );
198
 			rc = san_boot ( drive );
181
 			rc = san_boot ( drive );
209
 
192
 
210
  err_san_describe:
193
  err_san_describe:
211
 	/* Unhook SAN device, if applicable */
194
 	/* Unhook SAN device, if applicable */
212
-	if ( drive >= 0 ) {
195
+	if ( ( drive >= 0 ) && ! ( flags & URIBOOT_NO_SAN_UNHOOK ) ) {
213
 		if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) {
196
 		if ( fetch_intz_setting ( NULL, &keep_san_setting ) == 0 ) {
214
-			printf ( "Unregistering SAN device %#02x\n", drive );
215
 			san_unhook ( drive );
197
 			san_unhook ( drive );
198
+			printf ( "Unregistered SAN device %#02x\n", drive );
216
 		} else {
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
  err_san_hook:
203
  err_san_hook:
222
- err_no_boot:
223
 	return rc;
204
 	return rc;
224
 }
205
 }
225
 
206
 
360
 		goto err_pxe_menu_boot;
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
 	filename = fetch_next_server_and_filename ( NULL );
345
 	filename = fetch_next_server_and_filename ( NULL );
365
 	if ( ! filename )
346
 	if ( ! filename )
366
 		goto err_filename;
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
 	root_path = fetch_root_path ( NULL );
355
 	root_path = fetch_root_path ( NULL );
368
 	if ( ! root_path )
356
 	if ( ! root_path )
369
 		goto err_root_path;
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
 	/* Boot using next server, filename and root path */
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
 		goto err_uriboot;
385
 		goto err_uriboot;
374
 
386
 
375
  err_uriboot:
387
  err_uriboot:
388
+ err_no_boot:
376
 	uri_put ( root_path );
389
 	uri_put ( root_path );
377
  err_root_path:
390
  err_root_path:
378
 	uri_put ( filename );
391
 	uri_put ( filename );

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

377
 		return -ENOMEM;
377
 		return -ENOMEM;
378
 
378
 
379
 	/* Attempt boot */
379
 	/* Attempt boot */
380
-	rc = uriboot ( uri, NULL );
380
+	rc = uriboot ( uri, NULL, 0, URIBOOT_NO_SAN );
381
 	uri_put ( uri );
381
 	uri_put ( uri );
382
 	return rc;
382
 	return rc;
383
 }
383
 }

Loading…
Cancel
Save