Browse Source

[iSCSI] Support Windows Server 2008 direct iSCSI installation

Add yet another ugly hack to iscsiboot.c, this time to allow the user to
inhibit the shutdown/removal of the iSCSI INT13 device (and the network
devices, since they are required for the iSCSI device to function).

On the plus side, the fact that shutdown() now takes flags to
differentiate between shutdown-for-exit and shutdown-for-boot means that
another ugly hack (to allow returning via the PXE stack on BIOSes that
have broken INT 18 calls) will be easier.

I feel dirty.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
03c80c12b8

+ 1
- 1
src/arch/i386/firmware/pcbios/hidemem.c View File

128
  * Uninstalls the INT 15 handler installed by hide_etherboot(), if
128
  * Uninstalls the INT 15 handler installed by hide_etherboot(), if
129
  * possible.
129
  * possible.
130
  */
130
  */
131
-static void unhide_etherboot ( void ) {
131
+static void unhide_etherboot ( int flags __unused ) {
132
 
132
 
133
 	/* If we have more than one hooked interrupt at this point, it
133
 	/* If we have more than one hooked interrupt at this point, it
134
 	 * means that some other vector is still hooked, in which case
134
 	 * means that some other vector is still hooked, in which case

+ 1
- 1
src/arch/i386/image/bzimage.c View File

348
 		       sizeof ( bzhdr ) );
348
 		       sizeof ( bzhdr ) );
349
 
349
 
350
 	/* Prepare for exiting */
350
 	/* Prepare for exiting */
351
-	shutdown();
351
+	shutdown ( SHUTDOWN_BOOT );
352
 
352
 
353
 	DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
353
 	DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
354
 	       "(stack %04x:%04zx)\n", image,
354
 	       "(stack %04x:%04zx)\n", image,

+ 1
- 1
src/arch/i386/image/elfboot.c View File

46
 	/* An ELF image has no callback interface, so we need to shut
46
 	/* An ELF image has no callback interface, so we need to shut
47
 	 * down before invoking it.
47
 	 * down before invoking it.
48
 	 */
48
 	 */
49
-	shutdown();
49
+	shutdown ( SHUTDOWN_BOOT );
50
 
50
 
51
 	/* Jump to OS with flat physical addressing */
51
 	/* Jump to OS with flat physical addressing */
52
 	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
52
 	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )

+ 1
- 1
src/arch/i386/image/multiboot.c View File

277
 	/* Multiboot images may not return and have no callback
277
 	/* Multiboot images may not return and have no callback
278
 	 * interface, so shut everything down prior to booting the OS.
278
 	 * interface, so shut everything down prior to booting the OS.
279
 	 */
279
 	 */
280
-	shutdown();
280
+	shutdown ( SHUTDOWN_BOOT );
281
 
281
 
282
 	/* Jump to OS with flat physical addressing */
282
 	/* Jump to OS with flat physical addressing */
283
 	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
283
 	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )

+ 1
- 1
src/arch/i386/image/nbi.c View File

429
 	/* Shut down now if NBI image will not return */
429
 	/* Shut down now if NBI image will not return */
430
 	may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
430
 	may_return = NBI_PROGRAM_RETURNS ( imgheader.flags );
431
 	if ( ! may_return )
431
 	if ( ! may_return )
432
-		shutdown();
432
+		shutdown ( SHUTDOWN_BOOT );
433
 
433
 
434
 	/* Execute NBI image */
434
 	/* Execute NBI image */
435
 	if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {
435
 	if ( NBI_LINEAR_EXEC_ADDR ( imgheader.flags ) ) {

+ 7
- 0
src/core/config.c View File

205
 REQUIRE_OBJECT ( gdbudp );
205
 REQUIRE_OBJECT ( gdbudp );
206
 REQUIRE_OBJECT ( gdbstub_cmd );
206
 REQUIRE_OBJECT ( gdbstub_cmd );
207
 #endif
207
 #endif
208
+
209
+/*
210
+ * Drag in objects that are always required, but not dragged in via
211
+ * symbol dependencies.
212
+ *
213
+ */
214
+REQUIRE_OBJECT ( device );

+ 13
- 5
src/core/device.c View File

20
 #include <gpxe/list.h>
20
 #include <gpxe/list.h>
21
 #include <gpxe/tables.h>
21
 #include <gpxe/tables.h>
22
 #include <gpxe/device.h>
22
 #include <gpxe/device.h>
23
+#include <gpxe/init.h>
23
 
24
 
24
 /**
25
 /**
25
  * @file
26
  * @file
68
 /**
69
 /**
69
  * Probe all devices
70
  * Probe all devices
70
  *
71
  *
71
- * @ret rc		Return status code
72
- *
73
  * This initiates probing for all devices in the system.  After this
72
  * This initiates probing for all devices in the system.  After this
74
  * call, the device hierarchy will be populated, and all hardware
73
  * call, the device hierarchy will be populated, and all hardware
75
  * should be ready to use.
74
  * should be ready to use.
76
  */
75
  */
77
-int probe_devices ( void ) {
76
+static void probe_devices ( void ) {
78
 	struct root_device *rootdev;
77
 	struct root_device *rootdev;
79
 	int rc;
78
 	int rc;
80
 
79
 
84
 		if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
83
 		if ( ( rc = rootdev_probe ( rootdev ) ) != 0 )
85
 			list_del ( &rootdev->dev.siblings );
84
 			list_del ( &rootdev->dev.siblings );
86
 	}
85
 	}
87
-	return 0;
88
 }
86
 }
89
 
87
 
90
 /**
88
 /**
91
  * Remove all devices
89
  * Remove all devices
92
  *
90
  *
93
  */
91
  */
94
-void remove_devices ( void ) {
92
+static void remove_devices ( int flags ) {
95
 	struct root_device *rootdev;
93
 	struct root_device *rootdev;
96
 	struct root_device *tmp;
94
 	struct root_device *tmp;
97
 
95
 
96
+	if ( flags & SHUTDOWN_KEEP_DEVICES ) {
97
+		DBG ( "Refusing to remove devices on shutdown\n" );
98
+		return;
99
+	}
100
+
98
 	list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
101
 	list_for_each_entry_safe ( rootdev, tmp, &devices, dev.siblings ) {
99
 		rootdev_remove ( rootdev );
102
 		rootdev_remove ( rootdev );
100
 		list_del ( &rootdev->dev.siblings );
103
 		list_del ( &rootdev->dev.siblings );
101
 	}
104
 	}
102
 }
105
 }
106
+
107
+struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
108
+	.startup = probe_devices,
109
+	.shutdown = remove_devices,
110
+};

+ 4
- 10
src/core/init.c View File

79
 			startup_fn->startup();
79
 			startup_fn->startup();
80
 	}
80
 	}
81
 
81
 
82
-	/* Probe for all devices.  Treated separately because nothing
83
-	 * else will drag in device.o
84
-	 */
85
-	probe_devices();
86
-
87
 	started = 1;
82
 	started = 1;
88
 }
83
 }
89
 
84
 
90
 /**
85
 /**
91
  * Shut down gPXE
86
  * Shut down gPXE
92
  *
87
  *
88
+ * @v flags		Shutdown behaviour flags
89
+ *
93
  * This function reverses the actions of startup(), and leaves gPXE in
90
  * This function reverses the actions of startup(), and leaves gPXE in
94
  * a state ready to be removed from memory.  You may call startup()
91
  * a state ready to be removed from memory.  You may call startup()
95
  * again after calling shutdown().
92
  * again after calling shutdown().
97
  * Call this function only once, before either exiting main() or
94
  * Call this function only once, before either exiting main() or
98
  * starting up a non-returnable image.
95
  * starting up a non-returnable image.
99
  */
96
  */
100
-void shutdown ( void ) {
97
+void shutdown ( int flags ) {
101
 	struct startup_fn *startup_fn;
98
 	struct startup_fn *startup_fn;
102
 
99
 
103
 	if ( ! started )
100
 	if ( ! started )
104
 		return;
101
 		return;
105
 
102
 
106
-	/* Remove all devices */
107
-	remove_devices();
108
-
109
 	/* Call registered shutdown functions (in reverse order) */
103
 	/* Call registered shutdown functions (in reverse order) */
110
 	for ( startup_fn = startup_fns_end - 1 ; startup_fn >= startup_fns ;
104
 	for ( startup_fn = startup_fns_end - 1 ; startup_fn >= startup_fns ;
111
 	      startup_fn-- ) {
105
 	      startup_fn-- ) {
112
 		if ( startup_fn->shutdown )
106
 		if ( startup_fn->shutdown )
113
-			startup_fn->shutdown();
107
+			startup_fn->shutdown ( flags );
114
 	}
108
 	}
115
 
109
 
116
 	started = 0;
110
 	started = 0;

+ 1
- 1
src/core/main.c View File

62
 			shell();
62
 			shell();
63
 	}
63
 	}
64
 
64
 
65
-	shutdown();
65
+	shutdown ( SHUTDOWN_EXIT | shutdown_exit_flags );
66
 
66
 
67
 	return 0;
67
 	return 0;
68
 }
68
 }

+ 2
- 2
src/core/serial.c View File

224
  *	Cleanup our use of the serial port, in particular flush the
224
  *	Cleanup our use of the serial port, in particular flush the
225
  *	output buffer so we don't accidentially lose characters.
225
  *	output buffer so we don't accidentially lose characters.
226
  */
226
  */
227
-static void serial_fini ( void ) {
227
+static void serial_fini ( int flags __unused ) {
228
 	int i, status;
228
 	int i, status;
229
 	/* Flush the output buffer to avoid dropping characters,
229
 	/* Flush the output buffer to avoid dropping characters,
230
 	 * if we are reinitializing the serial port.
230
 	 * if we are reinitializing the serial port.
247
 };
247
 };
248
 
248
 
249
 /** Serial driver startup function */
249
 /** Serial driver startup function */
250
-struct startup_fn serial_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
250
+struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
251
 	.shutdown = serial_fini,
251
 	.shutdown = serial_fini,
252
 };
252
 };

+ 0
- 3
src/include/gpxe/device.h View File

105
 /** Declare a root device */
105
 /** Declare a root device */
106
 #define __root_device __table ( struct root_device, root_devices, 01 )
106
 #define __root_device __table ( struct root_device, root_devices, 01 )
107
 
107
 
108
-extern int probe_devices ( void );
109
-extern void remove_devices ( void );
110
-
111
 #endif /* _GPXE_DEVICE_H */
108
 #endif /* _GPXE_DEVICE_H */

+ 12
- 3
src/include/gpxe/dhcp.h View File

164
  * priority of multiple option blocks (e.g. options from non-volatile
164
  * priority of multiple option blocks (e.g. options from non-volatile
165
  * storage versus options from a DHCP server).
165
  * storage versus options from a DHCP server).
166
  */
166
  */
167
-#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 1 )
167
+#define DHCP_EB_PRIORITY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x01 )
168
 
168
 
169
 /** "Your" IP address
169
 /** "Your" IP address
170
  *
170
  *
172
  * field, in order to provide a consistent approach to storing and
172
  * field, in order to provide a consistent approach to storing and
173
  * processing options.  It should never be present in a DHCP packet.
173
  * processing options.  It should never be present in a DHCP packet.
174
  */
174
  */
175
-#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 2 )
175
+#define DHCP_EB_YIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x02 )
176
 
176
 
177
 /** "Server" IP address
177
 /** "Server" IP address
178
  *
178
  *
180
  * field, in order to provide a consistent approach to storing and
180
  * field, in order to provide a consistent approach to storing and
181
  * processing options.  It should never be present in a DHCP packet.
181
  * processing options.  It should never be present in a DHCP packet.
182
  */
182
  */
183
-#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
183
+#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x03 )
184
+
185
+/** Keep SAN drive registered
186
+ *
187
+ * If set to a non-zero value, gPXE will not detach any SAN drive
188
+ * after failing to boot from it.  (This option is required in order
189
+ * to perform a Windows Server 2008 installation direct to an iSCSI
190
+ * target.)
191
+ */
192
+#define DHCP_EB_KEEP_SAN DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x08 )
184
 
193
 
185
 /*
194
 /*
186
  * Tags in the range 0x10-0x7f are reserved for feature markers
195
  * Tags in the range 0x10-0x7f are reserved for feature markers

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

155
 #define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
155
 #define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
156
 #define ERRFILE_tls		      ( ERRFILE_OTHER | 0x000d0000 )
156
 #define ERRFILE_tls		      ( ERRFILE_OTHER | 0x000d0000 )
157
 #define ERRFILE_ifmgmt		      ( ERRFILE_OTHER | 0x000e0000 )
157
 #define ERRFILE_ifmgmt		      ( ERRFILE_OTHER | 0x000e0000 )
158
+#define ERRFILE_iscsiboot	      ( ERRFILE_OTHER | 0x000f0000 )
158
 
159
 
159
 /** @} */
160
 /** @} */
160
 
161
 

+ 12
- 2
src/include/gpxe/init.h View File

28
 
28
 
29
 /** @} */
29
 /** @} */
30
 
30
 
31
+/** Shutdown flags */
32
+enum shutdown_flags {
33
+	/** Shutdown is in order to exit (return to gPXE's caller) */
34
+	SHUTDOWN_EXIT = 0x0001,
35
+	/** Shutdown is in order to boot an OS */
36
+	SHUTDOWN_BOOT = 0x0002,
37
+	/** Do not remove devices */
38
+	SHUTDOWN_KEEP_DEVICES = 0x0004,
39
+};
40
+
31
 /**
41
 /**
32
  * A startup/shutdown function
42
  * A startup/shutdown function
33
  *
43
  *
36
  */
46
  */
37
 struct startup_fn {
47
 struct startup_fn {
38
 	void ( * startup ) ( void );
48
 	void ( * startup ) ( void );
39
-	void ( * shutdown ) ( void );
49
+	void ( * shutdown ) ( int flags );
40
 };
50
 };
41
 
51
 
42
 /** Declare a startup/shutdown function */
52
 /** Declare a startup/shutdown function */
58
 
68
 
59
 extern void initialise ( void );
69
 extern void initialise ( void );
60
 extern void startup ( void );
70
 extern void startup ( void );
61
-extern void shutdown ( void );
71
+extern void shutdown ( int flags );
62
 
72
 
63
 #endif /* _GPXE_INIT_H */
73
 #endif /* _GPXE_INIT_H */

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

7
  *
7
  *
8
  */
8
  */
9
 
9
 
10
+extern int shutdown_exit_flags;
11
+
10
 extern void autoboot ( void );
12
 extern void autoboot ( void );
11
 extern int boot_root_path ( const char *root_path );
13
 extern int boot_root_path ( const char *root_path );
12
 
14
 

+ 1
- 1
src/interface/pxe/pxe_preboot.c View File

318
 	pxe_set_netdev ( NULL );
318
 	pxe_set_netdev ( NULL );
319
 
319
 
320
 	/* Prepare for unload */
320
 	/* Prepare for unload */
321
-	shutdown();
321
+	shutdown ( SHUTDOWN_BOOT );
322
 
322
 
323
 	stop_undi->Status = PXENV_STATUS_SUCCESS;
323
 	stop_undi->Status = PXENV_STATUS_SUCCESS;
324
 	return PXENV_EXIT_SUCCESS;
324
 	return PXENV_EXIT_SUCCESS;

+ 3
- 0
src/usr/autoboot.c View File

41
 /** Time to wait for link-up */
41
 /** Time to wait for link-up */
42
 #define LINK_WAIT_MS 15000
42
 #define LINK_WAIT_MS 15000
43
 
43
 
44
+/** Shutdown flags for exit */
45
+int shutdown_exit_flags = 0;
46
+
44
 /**
47
 /**
45
  * Identify the boot network device
48
  * Identify the boot network device
46
  *
49
  *

+ 52
- 19
src/usr/iscsiboot.c View File

1
 #include <stdint.h>
1
 #include <stdint.h>
2
 #include <string.h>
2
 #include <string.h>
3
+#include <stdlib.h>
3
 #include <stdio.h>
4
 #include <stdio.h>
5
+#include <errno.h>
4
 #include <gpxe/iscsi.h>
6
 #include <gpxe/iscsi.h>
5
 #include <gpxe/settings.h>
7
 #include <gpxe/settings.h>
8
+#include <gpxe/dhcp.h>
6
 #include <gpxe/netdevice.h>
9
 #include <gpxe/netdevice.h>
7
 #include <gpxe/ibft.h>
10
 #include <gpxe/ibft.h>
11
+#include <gpxe/init.h>
8
 #include <int13.h>
12
 #include <int13.h>
13
+#include <usr/autoboot.h>
9
 #include <usr/iscsiboot.h>
14
 #include <usr/iscsiboot.h>
10
 
15
 
16
+struct setting keep_san_setting __setting = {
17
+	.name = "keep-san",
18
+	.description = "Preserve SAN connection",
19
+	.tag = DHCP_EB_KEEP_SAN,
20
+	.type = &setting_type_int8,
21
+};
22
+
11
 /**
23
 /**
12
  * Guess boot network device
24
  * Guess boot network device
13
  *
25
  *
25
 }
37
 }
26
 
38
 
27
 int iscsiboot ( const char *root_path ) {
39
 int iscsiboot ( const char *root_path ) {
28
-	struct scsi_device scsi;
29
-	struct int13_drive drive;
40
+	struct scsi_device *scsi;
41
+	struct int13_drive *drive;
42
+	int keep_san;
30
 	int rc;
43
 	int rc;
31
 
44
 
32
-	memset ( &scsi, 0, sizeof ( scsi ) );
33
-	memset ( &drive, 0, sizeof ( drive ) );
45
+	scsi = zalloc ( sizeof ( *scsi ) );
46
+	if ( ! scsi ) {
47
+		rc = -ENOMEM;
48
+		goto err_alloc_scsi;
49
+	}
50
+	drive = zalloc ( sizeof ( *drive ) );
51
+	if ( ! drive ) {
52
+		rc = -ENOMEM;
53
+		goto err_alloc_drive;
54
+	}
34
 
55
 
35
 	printf ( "iSCSI booting from %s\n", root_path );
56
 	printf ( "iSCSI booting from %s\n", root_path );
36
 
57
 
37
-	if ( ( rc = iscsi_attach ( &scsi, root_path ) ) != 0 ) {
58
+	if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) {
38
 		printf ( "Could not attach iSCSI device: %s\n",
59
 		printf ( "Could not attach iSCSI device: %s\n",
39
 			 strerror ( rc ) );
60
 			 strerror ( rc ) );
40
-		goto error_attach;
61
+		goto err_attach;
41
 	}
62
 	}
42
-	if ( ( rc = init_scsidev ( &scsi ) ) != 0 ) {
63
+	if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
43
 		printf ( "Could not initialise iSCSI device: %s\n",
64
 		printf ( "Could not initialise iSCSI device: %s\n",
44
 			 strerror ( rc ) );
65
 			 strerror ( rc ) );
45
-		goto error_init;
66
+		goto err_init;
46
 	}
67
 	}
47
 
68
 
48
-	drive.blockdev = &scsi.blockdev;
69
+	drive->blockdev = &scsi->blockdev;
49
 
70
 
50
 	/* FIXME: ugly, ugly hack */
71
 	/* FIXME: ugly, ugly hack */
51
 	struct net_device *netdev = guess_boot_netdev();
72
 	struct net_device *netdev = guess_boot_netdev();
52
 	struct iscsi_session *iscsi =
73
 	struct iscsi_session *iscsi =
53
-		container_of ( scsi.backend, struct iscsi_session, refcnt );
74
+		container_of ( scsi->backend, struct iscsi_session, refcnt );
54
 	ibft_fill_data ( netdev, iscsi );
75
 	ibft_fill_data ( netdev, iscsi );
55
 
76
 
56
-	register_int13_drive ( &drive );
57
-	printf ( "Registered as BIOS drive %#02x\n", drive.drive );
58
-	printf ( "Booting from BIOS drive %#02x\n", drive.drive );
59
-	rc = int13_boot ( drive.drive );
77
+	register_int13_drive ( drive );
78
+	printf ( "Registered as BIOS drive %#02x\n", drive->drive );
79
+	printf ( "Booting from BIOS drive %#02x\n", drive->drive );
80
+	rc = int13_boot ( drive->drive );
60
 	printf ( "Boot failed\n" );
81
 	printf ( "Boot failed\n" );
61
 
82
 
62
-	printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
63
-	unregister_int13_drive ( &drive );
83
+	/* Leave drive registered, if instructed to do so */
84
+	keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
85
+	if ( keep_san ) {
86
+		printf ( "Preserving connection to SAN disk\n" );
87
+		shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
88
+		return rc;
89
+	}
90
+
91
+	printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
92
+	unregister_int13_drive ( drive );
64
 
93
 
65
- error_init:
66
-	iscsi_detach ( &scsi );
67
- error_attach:
94
+ err_init:
95
+	iscsi_detach ( scsi );
96
+ err_attach:
97
+	free ( drive );
98
+ err_alloc_drive:
99
+	free ( scsi );
100
+ err_alloc_scsi:
68
 	return rc;
101
 	return rc;
69
 }
102
 }

Loading…
Cancel
Save