Try booting from the "boot" network device first (i.e. the one which we
authorMichael Brown <mcb30@etherboot.org>
Wed, 10 Jan 2007 20:21:42 +0000 (20:21 +0000)
committerMichael Brown <mcb30@etherboot.org>
Wed, 10 Jan 2007 20:21:42 +0000 (20:21 +0000)
were loaded from).  The code to identify this device isn't present yet,
but the code to act upon the knowledge is.

src/usr/autoboot.c

index 057b70c..45b3b6e 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <string.h>
+#include <errno.h>
 #include <vsprintf.h>
 #include <gpxe/netdevice.h>
 #include <usr/ifmgmt.h>
 
 void test_dhcp ( struct net_device *netdev );
 
-void autoboot ( void ) {
+/**
+ * Identify the boot network device
+ *
+ * @ret netdev         Boot network device
+ */
+static struct net_device * find_boot_netdev ( void ) {
+       return NULL;
+}
+
+/**
+ * Get the next network device to try
+ *
+ * @ret netdev         'Next' network device
+ *
+ * This function will cycle through all registered network devices in
+ * order, returning NULL.
+ *
+ * This function should be safe against registration/deregistration of
+ * net devices between calls to next_netdev().
+ */
+static struct net_device * next_netdev ( void ) {
+       static struct net_device *last_netdev = NULL;
        struct net_device *netdev;
-       int rc;
 
        for_each_netdev ( netdev ) {
+               if ( ! last_netdev ) {
+                       last_netdev = netdev;
+                       return netdev;
+               }
+               if ( last_netdev == netdev )
+                       last_netdev = NULL;
+       }
 
-               if ( ( rc = ifopen ( netdev ) ) != 0 )
-                       continue;
+       last_netdev = NULL;
+       return NULL;
+}
+
+/**
+ * Boot from a network device
+ *
+ * @v netdev           Network device
+ */
+void netboot ( struct net_device *netdev ) {
+
+       /* Open device and display device status */
+       if ( ifopen ( netdev ) != 0 )
+               return;
+       ifstat ( netdev );
 
-               ifstat ( netdev );
+       test_dhcp ( netdev );
+}
+
+/**
+ * Close all open net devices
+ *
+ * Called before a fresh boot attempt in order to free up memory.  We
+ * don't just close the device immediately after the boot fails,
+ * because there may still be TCP connections in the process of
+ * closing.
+ */
+static void close_all_netdevs ( void ) {
+       struct net_device *netdev;
 
-               test_dhcp ( netdev );
-               
+       for_each_netdev ( netdev ) {
                ifclose ( netdev );
        }
+}
+
+/**
+ * Boot the system
+ */
+void autoboot ( void ) {
+       struct net_device *boot_netdev;
+       struct net_device *netdev;
+
+       /* If we have an identifable boot device, try that first */
+       close_all_netdevs();
+       if ( ( boot_netdev = find_boot_netdev() ) )
+               netboot ( boot_netdev );
+
+       /* If that fails, try booting from any of the other devices */
+       for_each_netdev ( netdev ) {
+               if ( netdev == boot_netdev )
+                       continue;
+               close_all_netdevs();
+               netboot ( netdev );
+       }
 
        printf ( "No more network devices\n" );
 }