diff --git a/src/drivers/scsi/iscsidev.c b/src/drivers/scsi/iscsidev.c deleted file mode 100644 index aab99032..00000000 --- a/src/drivers/scsi/iscsidev.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -/** @file - * - * iSCSI SCSI device - * - */ - -/** - * Issue SCSI command via iSCSI device - * - * @v scsi SCSI device - * @v command SCSI command - * @ret rc Return status code - */ -static int iscsi_command ( struct scsi_device *scsi, - struct scsi_command *command ) { - struct iscsi_device *iscsidev - = container_of ( scsi, struct iscsi_device, scsi ); - struct async async; - - return async_block ( &async, iscsi_issue ( &iscsidev->iscsi, command, - &async ) ); -} - -/** - * Initialise iSCSI device - * - * @v iscsidev iSCSI device - */ -int init_iscsidev ( struct iscsi_device *iscsidev ) { - int rc; - - iscsidev->scsi.command = iscsi_command; - iscsidev->scsi.lun = iscsidev->iscsi.lun; - if ( ( rc = init_scsidev ( &iscsidev->scsi ) ) != 0 ) - goto err; - - return 0; - - err: - fini_iscsidev ( iscsidev ); - return rc; -} - -/** - * Shut down iSCSI device - * - * @v iscsidev iSCSI device - */ -void fini_iscsidev ( struct iscsi_device *iscsidev ) { - iscsi_shutdown ( &iscsidev->iscsi ); -} diff --git a/src/include/gpxe/iscsi.h b/src/include/gpxe/iscsi.h index 03fc0641..d9dd4307 100644 --- a/src/include/gpxe/iscsi.h +++ b/src/include/gpxe/iscsi.h @@ -639,4 +639,7 @@ struct iscsi_session { /** Maximum number of retries at connecting */ #define ISCSI_MAX_RETRIES 2 +extern int iscsi_attach ( struct scsi_device *scsi, const char *root_path ); +extern void iscsi_detach ( struct scsi_device *scsi ); + #endif /* _GPXE_ISCSI_H */ diff --git a/src/include/gpxe/scsi.h b/src/include/gpxe/scsi.h index 9d5952da..e820117b 100644 --- a/src/include/gpxe/scsi.h +++ b/src/include/gpxe/scsi.h @@ -4,6 +4,7 @@ #include #include #include +#include /** @file * @@ -229,7 +230,7 @@ struct scsi_command { * Must be zero if @c data_in is NULL */ size_t data_in_len; - /** SCSI statua code */ + /** SCSI status code */ uint8_t status; /** SCSI sense response code */ uint8_t sense_response; @@ -260,6 +261,8 @@ struct scsi_device { */ int ( * command ) ( struct scsi_device *scsi, struct scsi_command *command ); + /** Backing device */ + struct refcnt *backend; }; extern int init_scsidev ( struct scsi_device *scsi ); diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index f0f6db0b..0bfb19e1 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -1261,21 +1261,21 @@ static struct xfer_interface_operations iscsi_socket_operations = { /**************************************************************************** * - * iSCSI to SCSI interface + * iSCSI command issuing * */ /** * Issue SCSI command * - * @v scsi SCSI interface + * @v scsi SCSI device * @v command SCSI command * @ret rc Return status code */ -static int iscsi_scsi_issue ( struct scsi_interface *scsi, - struct scsi_command *command ) { +static int iscsi_command ( struct scsi_device *scsi, + struct scsi_command *command ) { struct iscsi_session *iscsi = - container_of ( scsi, struct iscsi_session, scsi ); + container_of ( scsi->backend, struct iscsi_session, refcnt ); int rc; /* Record SCSI command */ @@ -1306,25 +1306,26 @@ static int iscsi_scsi_issue ( struct scsi_interface *scsi, return rc; } -/** - * Detach SCSI interface - * - * @v scsi SCSI interface - * @v rc Reason for close - */ -static void iscsi_scsi_detach ( struct scsi_interface *scsi, int rc ) { - struct iscsi_session *iscsi = - container_of ( scsi, struct iscsi_session, scsi ); - - iscsi_close_connection ( iscsi, rc ); - process_del ( &iscsi->process ); +static int iscsi_detached_command ( struct scsi_device *scsi __unused, + struct scsi_command *command __unused ) { + return -ENODEV; } -/** iSCSI SCSI operations */ -struct scsi_operations iscsi_scsi_operations = { - .detach = iscsi_scsi_detach, - .issue = iscsi_scsi_issue, -}; +/** + * Shut down iSCSI interface + * + * @v scsi SCSI device + */ +void iscsi_detach ( struct scsi_device *scsi ) { + struct iscsi_session *iscsi = + container_of ( scsi->backend, struct iscsi_session, refcnt ); + + iscsi_close_connection ( iscsi, 0 ); + process_del ( &iscsi->process ); + scsi->command = iscsi_detached_command; + ref_put ( scsi->backend ); + scsi->backend = NULL; +} /**************************************************************************** * @@ -1430,11 +1431,11 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, /** * Attach iSCSI interface * - * @v scsi SCSI interface + * @v scsi SCSI device * @v root_path iSCSI root path (as per RFC4173) * @ret rc Return status code */ -int iscsi_attach ( struct scsi_interface *scsi, const char *root_path ) { +int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) { struct iscsi_session *iscsi; int rc; @@ -1442,6 +1443,7 @@ int iscsi_attach ( struct scsi_interface *scsi, const char *root_path ) { iscsi = zalloc ( sizeof ( *iscsi ) ); if ( ! iscsi ) return -ENOMEM; + iscsi->refcnt.free = iscsi_free; xfer_init ( &iscsi->socket, &iscsi_socket_operations, &iscsi->refcnt ); process_init ( &iscsi->process, iscsi_tx_step, &iscsi->refcnt ); @@ -1464,7 +1466,9 @@ int iscsi_attach ( struct scsi_interface *scsi, const char *root_path ) { } /* Attach parent interface, mortalise self, and return */ - scsi_plug_plug ( &iscsi->scsi, scsi ); + scsi->backend = ref_get ( &iscsi->refcnt ); + scsi->command = iscsi_command; + scsi->lun = iscsi->lun; ref_put ( &iscsi->refcnt ); return 0; diff --git a/src/tests/iscsiboot.c b/src/tests/iscsiboot.c index 22dccb1d..9331357d 100644 --- a/src/tests/iscsiboot.c +++ b/src/tests/iscsiboot.c @@ -1,48 +1,36 @@ #include #include #include -#include -#include #include -#include -#include +#include #include -static struct iscsi_device test_iscsidev; - -int test_iscsiboot ( const char *initiator_iqn, - struct sockaddr_tcpip *target, - const char *target_iqn, - unsigned int lun, - const char *username, - const char *password, - struct net_device *netdev, - unsigned int drivenum ) { +int iscsiboot ( const char *root_path ) { + struct scsi_device scsi; struct int13_drive drive; int rc; - memset ( &test_iscsidev, 0, sizeof ( test_iscsidev ) ); - memcpy ( &test_iscsidev.iscsi.target, target, - sizeof ( test_iscsidev.iscsi.target ) ); - test_iscsidev.iscsi.initiator_iqn = initiator_iqn; - test_iscsidev.iscsi.target_iqn = target_iqn; - test_iscsidev.iscsi.lun = lun; - test_iscsidev.iscsi.username = username; - test_iscsidev.iscsi.password = password; - - printf ( "Initialising %s\n", target_iqn ); - if ( ( rc = init_iscsidev ( &test_iscsidev ) ) != 0 ) { - printf ( "Could not reach %s: %s\n", target_iqn, - strerror ( rc ) ); - return rc; - } - ibft_fill_data ( netdev, &test_iscsidev.iscsi ); + memset ( &scsi, 0, sizeof ( scsi ) ); memset ( &drive, 0, sizeof ( drive ) ); - drive.drive = drivenum; - drive.blockdev = &test_iscsidev.scsi.blockdev; + + printf ( "iSCSI booting from %s\n", root_path ); + + if ( ( rc = iscsi_attach ( &scsi, root_path ) ) != 0 ) { + printf ( "Could not attach iSCSI device: %s\n", + strerror ( rc ) ); + goto error_attach; + } + if ( ( rc = init_scsidev ( &scsi ) ) != 0 ) { + printf ( "Could not initialise iSCSI device: %s\n", + strerror ( rc ) ); + goto error_init; + } + + drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE ); + drive.blockdev = &scsi.blockdev; + register_int13_drive ( &drive ); - printf ( "Registered %s as BIOS drive %#02x\n", - target_iqn, 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" ); @@ -50,7 +38,8 @@ int test_iscsiboot ( const char *initiator_iqn, printf ( "Unregistering BIOS drive %#02x\n", drive.drive ); unregister_int13_drive ( &drive ); - fini_iscsidev ( &test_iscsidev ); - + error_init: + iscsi_detach ( &scsi ); + error_attach: return rc; } diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 302e1891..277e8b09 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -44,56 +44,96 @@ static struct net_device * find_boot_netdev ( void ) { } /** - * Boot from a network device + * Boot using filename * - * @v netdev Network device + * @v filename Boot filename + * @ret rc Return status code */ -void netboot ( struct net_device *netdev ) { - char filename[256]; +static int boot_filename ( const char *filename ) { struct image *image; int rc; - /* Open device and display device status */ - if ( ( rc = ifopen ( netdev ) ) != 0 ) - return; - ifstat ( netdev ); - - /* Configure device via DHCP */ - if ( ( rc = dhcp ( netdev ) ) != 0 ) - return; - route(); - - /* Try to download and boot whatever we are given as a filename */ - dhcp_snprintf ( filename, sizeof ( filename ), - find_global_dhcp_option ( DHCP_BOOTFILE_NAME ) ); - if ( ! filename[0] ) { - printf ( "No boot filename\n" ); - return; - } - printf ( "Booting \"%s\"\n", filename ); image = alloc_image(); if ( ! image ) { printf ( "Out of memory\n" ); - return; + return -ENOMEM; } if ( ( rc = imgfetch ( image, filename, 0 ) ) != 0 ) { printf ( "Could not retrieve %s: %s\n", filename, strerror ( rc ) ); image_put ( image ); - return; + return rc; } if ( ( rc = imgload ( image ) ) != 0 ) { printf ( "Could not load %s: %s\n", image->name, strerror ( rc ) ); image_put ( image ); - return; + return rc; } if ( ( rc = imgexec ( image ) ) != 0 ) { printf ( "Could not execute %s: %s\n", image->name, strerror ( rc ) ); image_put ( image ); - return; + return rc; } + + return 0; +} + +/** + * Boot using root path + * + * @v root_path Root path + * @ret rc Return status code + */ +static int boot_root_path ( const char *root_path ) { + int rc; + + /* Quick hack */ + if ( ( rc = iscsiboot ( root_path ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Boot from a network device + * + * @v netdev Network device + * @ret rc Return status code + */ +int netboot ( struct net_device *netdev ) { + char buf[256]; + int rc; + + /* Open device and display device status */ + if ( ( rc = ifopen ( netdev ) ) != 0 ) + return rc; + ifstat ( netdev ); + + /* Configure device via DHCP */ + if ( ( rc = dhcp ( netdev ) ) != 0 ) + return rc; + route(); + + /* Try to download and boot whatever we are given as a filename */ + dhcp_snprintf ( buf, sizeof ( buf ), + find_global_dhcp_option ( DHCP_BOOTFILE_NAME ) ); + if ( buf[0] ) { + printf ( "Booting from filename \"%s\"\n", buf ); + return boot_filename ( buf ); + } + + /* No filename; try the root path */ + dhcp_snprintf ( buf, sizeof ( buf ), + find_global_dhcp_option ( DHCP_ROOT_PATH ) ); + if ( buf[0] ) { + printf ( "Booting from root path \"%s\"\n", buf ); + return boot_root_path ( buf ); + } + + printf ( "No filename or root path specified\n" ); + return -ENOENT; } /**