summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorMichael Brown2008-07-17 18:45:17 +0200
committerMichael Brown2008-07-17 18:45:17 +0200
commit03c80c12b8e9019554c3bd4545cf68926ee1ce47 (patch)
treead2217eda5c315775a86708e166c85a9f04926ff /src/usr
parent[phantom] Guard against partially-written status descriptors (diff)
downloadipxe-03c80c12b8e9019554c3bd4545cf68926ee1ce47.tar.gz
ipxe-03c80c12b8e9019554c3bd4545cf68926ee1ce47.tar.xz
ipxe-03c80c12b8e9019554c3bd4545cf68926ee1ce47.zip
[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.
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/autoboot.c3
-rw-r--r--src/usr/iscsiboot.c71
2 files changed, 55 insertions, 19 deletions
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index cff6e95d..fdd502da 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -41,6 +41,9 @@
/** Time to wait for link-up */
#define LINK_WAIT_MS 15000
+/** Shutdown flags for exit */
+int shutdown_exit_flags = 0;
+
/**
* Identify the boot network device
*
diff --git a/src/usr/iscsiboot.c b/src/usr/iscsiboot.c
index 99edc879..84d77c45 100644
--- a/src/usr/iscsiboot.c
+++ b/src/usr/iscsiboot.c
@@ -1,13 +1,25 @@
#include <stdint.h>
#include <string.h>
+#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#include <gpxe/iscsi.h>
#include <gpxe/settings.h>
+#include <gpxe/dhcp.h>
#include <gpxe/netdevice.h>
#include <gpxe/ibft.h>
+#include <gpxe/init.h>
#include <int13.h>
+#include <usr/autoboot.h>
#include <usr/iscsiboot.h>
+struct setting keep_san_setting __setting = {
+ .name = "keep-san",
+ .description = "Preserve SAN connection",
+ .tag = DHCP_EB_KEEP_SAN,
+ .type = &setting_type_int8,
+};
+
/**
* Guess boot network device
*
@@ -25,45 +37,66 @@ static struct net_device * guess_boot_netdev ( void ) {
}
int iscsiboot ( const char *root_path ) {
- struct scsi_device scsi;
- struct int13_drive drive;
+ struct scsi_device *scsi;
+ struct int13_drive *drive;
+ int keep_san;
int rc;
- memset ( &scsi, 0, sizeof ( scsi ) );
- memset ( &drive, 0, sizeof ( drive ) );
+ scsi = zalloc ( sizeof ( *scsi ) );
+ if ( ! scsi ) {
+ rc = -ENOMEM;
+ goto err_alloc_scsi;
+ }
+ drive = zalloc ( sizeof ( *drive ) );
+ if ( ! drive ) {
+ rc = -ENOMEM;
+ goto err_alloc_drive;
+ }
printf ( "iSCSI booting from %s\n", root_path );
- if ( ( rc = iscsi_attach ( &scsi, root_path ) ) != 0 ) {
+ if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) {
printf ( "Could not attach iSCSI device: %s\n",
strerror ( rc ) );
- goto error_attach;
+ goto err_attach;
}
- if ( ( rc = init_scsidev ( &scsi ) ) != 0 ) {
+ if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
printf ( "Could not initialise iSCSI device: %s\n",
strerror ( rc ) );
- goto error_init;
+ goto err_init;
}
- drive.blockdev = &scsi.blockdev;
+ drive->blockdev = &scsi->blockdev;
/* FIXME: ugly, ugly hack */
struct net_device *netdev = guess_boot_netdev();
struct iscsi_session *iscsi =
- container_of ( scsi.backend, struct iscsi_session, refcnt );
+ container_of ( scsi->backend, struct iscsi_session, refcnt );
ibft_fill_data ( netdev, iscsi );
- register_int13_drive ( &drive );
- printf ( "Registered as BIOS drive %#02x\n", drive.drive );
- printf ( "Booting from BIOS drive %#02x\n", drive.drive );
- rc = int13_boot ( drive.drive );
+ register_int13_drive ( drive );
+ printf ( "Registered as BIOS drive %#02x\n", drive->drive );
+ printf ( "Booting from BIOS drive %#02x\n", drive->drive );
+ rc = int13_boot ( drive->drive );
printf ( "Boot failed\n" );
- printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
- unregister_int13_drive ( &drive );
+ /* Leave drive registered, if instructed to do so */
+ keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
+ if ( keep_san ) {
+ printf ( "Preserving connection to SAN disk\n" );
+ shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
+ return rc;
+ }
+
+ printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
+ unregister_int13_drive ( drive );
- error_init:
- iscsi_detach ( &scsi );
- error_attach:
+ err_init:
+ iscsi_detach ( scsi );
+ err_attach:
+ free ( drive );
+ err_alloc_drive:
+ free ( scsi );
+ err_alloc_scsi:
return rc;
}