Quick hack to get AoE back in to the tree, on a par with the current
authorMichael Brown <mcb30@etherboot.org>
Sun, 29 Jul 2007 01:31:14 +0000 (02:31 +0100)
committerMichael Brown <mcb30@etherboot.org>
Sun, 29 Jul 2007 01:31:14 +0000 (02:31 +0100)
iSCSI hack.

src/drivers/ata/aoedev.c [deleted file]
src/include/gpxe/aoe.h
src/include/gpxe/ata.h
src/include/usr/aoeboot.h [new file with mode: 0644]
src/net/aoe.c
src/tests/aoeboot.c [deleted file]
src/usr/aoeboot.c [new file with mode: 0644]
src/usr/autoboot.c

diff --git a/src/drivers/ata/aoedev.c b/src/drivers/ata/aoedev.c
deleted file mode 100644 (file)
index ff047f1..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * 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 <stddef.h>
-#include <gpxe/async.h>
-#include <gpxe/aoe.h>
-
-/** @file
- *
- * AoE ATA device
- *
- */
-
-/**
- * Issue ATA command via AoE device
- *
- * @v ata              ATA device
- * @v command          ATA command
- * @ret rc             Return status code
- */
-static int aoe_command ( struct ata_device *ata,
-                        struct ata_command *command ) {
-       struct aoe_device *aoedev
-               = container_of ( ata, struct aoe_device, ata );
-       struct async async;
-
-       return async_block ( &async, aoe_issue ( &aoedev->aoe, command,
-                                                &async ) );
-}
-
-/**
- * Initialise AoE device
- *
- * @v aoedev           AoE device
- */
-int init_aoedev ( struct aoe_device *aoedev ) {
-       aoedev->ata.command = aoe_command;
-       aoe_open ( &aoedev->aoe );
-       return init_atadev ( &aoedev->ata );
-}
index eb5e113..8568338 100644 (file)
@@ -81,6 +81,9 @@ struct aoehdr {
 
 /** An AoE session */
 struct aoe_session {
+       /** Reference counter */
+       struct refcnt refcnt;
+
        /** List of all AoE sessions */
        struct list_head list;
 
@@ -103,8 +106,8 @@ struct aoe_session {
        unsigned int status;
        /** Byte offset within command's data buffer */
        unsigned int command_offset;
-       /** Asynchronous operation for this command */
-       struct async async;
+       /** Return status code for command */
+       int rc;
 
        /** Retransmission timer */
        struct retry_timer timer;
@@ -116,20 +119,8 @@ struct aoe_session {
 /** Maximum number of sectors per packet */
 #define AOE_MAX_COUNT 2
 
-extern void aoe_open ( struct aoe_session *aoe );
-extern void aoe_close ( struct aoe_session *aoe );
-extern int aoe_issue ( struct aoe_session *aoe,
-                      struct ata_command *command,
-                      struct async *parent );
-
-/** An AoE device */
-struct aoe_device {
-       /** ATA device interface */
-       struct ata_device ata;
-       /** AoE protocol instance */
-       struct aoe_session aoe;
-};
-
-extern int init_aoedev ( struct aoe_device *aoedev );
+extern void aoe_detach ( struct ata_device *ata );
+extern int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
+                       const char *root_path );
 
 #endif /* _GPXE_AOE_H */
index e0fca7a..b6da393 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdint.h>
 #include <gpxe/blockdev.h>
 #include <gpxe/uaccess.h>
+#include <gpxe/refcnt.h>
 
 /** @file
  *
@@ -195,6 +196,8 @@ struct ata_device {
         */
        int ( * command ) ( struct ata_device *ata,
                            struct ata_command *command );
+       /** Backing device */
+       struct refcnt *backend;
 };
 
 extern int init_atadev ( struct ata_device *ata );
diff --git a/src/include/usr/aoeboot.h b/src/include/usr/aoeboot.h
new file mode 100644 (file)
index 0000000..0421ebc
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _USR_AOEBOOT_H
+#define _USR_AOEBOOT_H
+
+extern int aoeboot ( const char *root_path );
+
+#endif /* _USR_AOEBOOT_H */
index 36721df..fd82665 100644 (file)
@@ -19,6 +19,7 @@
 #include <stddef.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <assert.h>
 #include <byteswap.h>
@@ -29,7 +30,7 @@
 #include <gpxe/uaccess.h>
 #include <gpxe/ata.h>
 #include <gpxe/netdevice.h>
-#include <gpxe/async.h>
+#include <gpxe/process.h>
 #include <gpxe/aoe.h>
 
 /** @file
@@ -43,6 +44,14 @@ struct net_protocol aoe_protocol;
 /** List of all AoE sessions */
 static LIST_HEAD ( aoe_sessions );
 
+static void aoe_free ( struct refcnt *refcnt ) {
+       struct aoe_session *aoe =
+               container_of ( refcnt, struct aoe_session, refcnt );
+
+       netdev_put ( aoe->netdev );
+       free ( aoe );
+}
+
 /**
  * Mark current AoE command complete
  *
@@ -55,8 +64,8 @@ static void aoe_done ( struct aoe_session *aoe, int rc ) {
        aoe->command->cb.cmd_stat = aoe->status;
        aoe->command = NULL;
 
-       /* Mark async operation as complete */
-       async_done ( &aoe->async, rc );
+       /* Mark operation as complete */
+       aoe->rc = rc;
 }
 
 /**
@@ -265,46 +274,99 @@ struct net_protocol aoe_protocol __net_protocol = {
        .rx = aoe_rx,
 };
 
-/**
- * Open AoE session
- *
- * @v aoe              AoE session
- */
-void aoe_open ( struct aoe_session *aoe ) {
-       memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
-                sizeof ( aoe->target ) );
-       aoe->tag = AOE_TAG_MAGIC;
-       aoe->timer.expired = aoe_timer_expired;
-       list_add ( &aoe->list, &aoe_sessions );
-}
-
-/**
- * Close AoE session
- *
- * @v aoe              AoE session
- */
-void aoe_close ( struct aoe_session *aoe ) {
-       list_del ( &aoe->list );
-}
-
 /**
  * Issue ATA command via an open AoE session
  *
- * @v aoe              AoE session
+ * @v ata              ATA device
  * @v command          ATA command
- * @v parent           Parent asynchronous operation
  * @ret rc             Return status code
- *
- * Only one command may be issued concurrently per session.  This call
- * is non-blocking; use async_wait() to wait for the command to
- * complete.
  */
-int aoe_issue ( struct aoe_session *aoe, struct ata_command *command,
-               struct async *parent ) {
+static int aoe_command ( struct ata_device *ata,
+                        struct ata_command *command ) {
+       struct aoe_session *aoe =
+               container_of ( ata->backend, struct aoe_session, refcnt );
+       int rc;
+
        aoe->command = command;
        aoe->status = 0;
        aoe->command_offset = 0;
        aoe_send_command ( aoe );
-       async_init ( &aoe->async, &default_async_operations, parent );
+
+       aoe->rc = -EINPROGRESS;
+       while ( aoe->rc == -EINPROGRESS )
+               step();
+       rc = aoe->rc;
+
+       return rc;
+}
+
+static int aoe_detached_command ( struct ata_device *ata __unused,
+                                 struct ata_command *command __unused ) {
+       return -ENODEV;
+}
+
+void aoe_detach ( struct ata_device *ata ) {
+       struct aoe_session *aoe =
+               container_of ( ata->backend, struct aoe_session, refcnt );
+
+       stop_timer ( &aoe->timer );
+       ata->command = aoe_detached_command;
+       list_del ( &aoe->list );
+       ref_put ( ata->backend );
+       ata->backend = NULL;
+}
+
+static int aoe_parse_root_path ( struct aoe_session *aoe,
+                                const char *root_path ) {
+       char *ptr;
+
+       if ( strncmp ( root_path, "aoe:", 4 ) != 0 )
+               return -EINVAL;
+       ptr = ( ( char * ) root_path + 4 );
+
+       if ( *ptr++ != 'e' )
+               return -EINVAL;
+
+       aoe->major = strtoul ( ptr, &ptr, 10 );
+       if ( *ptr++ != '.' )
+               return -EINVAL;
+
+       aoe->minor = strtoul ( ptr, &ptr, 10 );
+       if ( *ptr )
+               return -EINVAL;
+
        return 0;
 }
+
+int aoe_attach ( struct ata_device *ata, struct net_device *netdev,
+                const char *root_path ) {
+       struct aoe_session *aoe;
+       int rc;
+
+       /* Allocate and initialise structure */
+       aoe = zalloc ( sizeof ( *aoe ) );
+       if ( ! aoe )
+               return -ENOMEM;
+       aoe->refcnt.free = aoe_free;
+       aoe->netdev = netdev_get ( netdev );
+       memcpy ( aoe->target, ethernet_protocol.ll_broadcast,
+                sizeof ( aoe->target ) );
+       aoe->tag = AOE_TAG_MAGIC;
+       aoe->timer.expired = aoe_timer_expired;
+
+       /* Parse root path */
+       if ( ( rc = aoe_parse_root_path ( aoe, root_path ) ) != 0 )
+               goto err;
+
+       /* Attach parent interface, transfer reference to connection
+        * list, and return
+        */
+       ata->backend = ref_get ( &aoe->refcnt );
+       ata->command = aoe_command;
+       list_add ( &aoe->list, &aoe_sessions );
+       return 0;
+
+ err:
+       ref_put ( &aoe->refcnt );
+       return rc;
+}
diff --git a/src/tests/aoeboot.c b/src/tests/aoeboot.c
deleted file mode 100644 (file)
index 17fda2c..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <console.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/aoe.h>
-#include <int13.h>
-
-static struct aoe_device test_aoedev = {
-       .aoe = {
-               .major = 0,
-               .minor = 0,
-       },
-};
-
-static int aoe_parse ( const char *aoename, struct aoe_session *aoe ) {
-       char *ptr = ( ( char * ) aoename );
-
-       if ( *ptr++ != 'e' )
-               return -EINVAL;
-
-       aoe->major = strtoul ( ptr, &ptr, 10 );
-       if ( *ptr++ != '.' )
-               return -EINVAL;
-
-       aoe->minor = strtoul ( ptr, &ptr, 10 );
-       if ( *ptr )
-               return -EINVAL;
-
-       return 0;
-}
-
-int test_aoeboot ( struct net_device *netdev, const char *aoename,
-                  unsigned int drivenum ) {
-       struct int13_drive drive;
-       int rc;
-
-       printf ( "Attempting to boot from AoE device %s via %s\n",
-                aoename, netdev->name );
-
-       if ( ( rc = aoe_parse ( aoename, &test_aoedev.aoe ) ) != 0 ) {
-               printf ( "Invalid AoE device name \"%s\"\n", aoename );
-               return rc;
-       }
-
-       printf ( "Initialising AoE device e%d.%d\n",
-                test_aoedev.aoe.major, test_aoedev.aoe.minor );
-       test_aoedev.aoe.netdev = netdev;
-       if ( ( rc = init_aoedev ( &test_aoedev ) ) != 0 ) {
-               printf ( "Could not reach AoE device e%d.%d\n",
-                        test_aoedev.aoe.major, test_aoedev.aoe.minor );
-               return rc;
-       }
-
-       memset ( &drive, 0, sizeof ( drive ) );
-       drive.drive = drivenum;
-       drive.blockdev = &test_aoedev.ata.blockdev;
-       register_int13_drive ( &drive );
-       printf ( "Registered AoE device e%d.%d as BIOS drive %#02x\n",
-                test_aoedev.aoe.major, test_aoedev.aoe.minor, 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 );
-
-       return rc;
-}
diff --git a/src/usr/aoeboot.c b/src/usr/aoeboot.c
new file mode 100644 (file)
index 0000000..54bb5d4
--- /dev/null
@@ -0,0 +1,67 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <gpxe/aoe.h>
+#include <gpxe/ata.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/dhcp.h>
+#include <int13.h>
+#include <usr/aoeboot.h>
+
+/**
+ * Guess boot network device
+ *
+ * @ret netdev         Boot network device
+ */
+static struct net_device * guess_boot_netdev ( void ) {
+       struct net_device *boot_netdev;
+
+       /* Just use the first network device */
+       for_each_netdev ( boot_netdev ) {
+               return boot_netdev;
+       }
+
+       return NULL;
+}
+
+int aoeboot ( const char *root_path ) {
+       struct ata_device ata;
+       struct int13_drive drive;
+       int rc;
+
+       memset ( &ata, 0, sizeof ( ata ) );
+       memset ( &drive, 0, sizeof ( drive ) );
+
+       printf ( "AoE booting from %s\n", root_path );
+
+       /* FIXME: ugly, ugly hack */
+       struct net_device *netdev = guess_boot_netdev();
+
+       if ( ( rc = aoe_attach ( &ata, netdev, root_path ) ) != 0 ) {
+               printf ( "Could not attach AoE device: %s\n",
+                        strerror ( rc ) );
+               goto error_attach;
+       }
+       if ( ( rc = init_atadev ( &ata ) ) != 0 ) {
+               printf ( "Could not initialise AoE device: %s\n",
+                        strerror ( rc ) );
+               goto error_init;
+       }
+
+       drive.drive = find_global_dhcp_num_option ( DHCP_EB_BIOS_DRIVE );
+       drive.blockdev = &ata.blockdev;
+
+       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 );
+
+ error_init:
+       aoe_detach ( &ata );
+ error_attach:
+       return rc;
+}
index 4bc43d5..53283d1 100644 (file)
@@ -27,6 +27,7 @@
 #include <usr/dhcpmgmt.h>
 #include <usr/imgmgmt.h>
 #include <usr/iscsiboot.h>
+#include <usr/aoeboot.h>
 #include <usr/autoboot.h>
 
 /** @file
@@ -88,13 +89,15 @@ static int boot_filename ( const char *filename ) {
  * @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;
+       if ( strncmp ( root_path, "iscsi:", 6 ) == 0 ) {
+               return iscsiboot ( root_path );
+       } else if ( strncmp ( root_path, "aoe:", 4 ) == 0 ) {
+               return aoeboot ( root_path );
+       }
 
-       return 0;
+       return -ENOTSUP;
 }
 
 /**