summaryrefslogtreecommitdiffstats
path: root/src/usr/autoboot.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-10 21:21:42 +0100
committerMichael Brown2007-01-10 21:21:42 +0100
commit78ded6604a49c5b39a813984b780b83a0fa08b94 (patch)
tree5924d8435c0acdfcec996a4f0fbdbf497ba5d676 /src/usr/autoboot.c
parentAdd find_pci_netdev() (diff)
downloadipxe-78ded6604a49c5b39a813984b780b83a0fa08b94.tar.gz
ipxe-78ded6604a49c5b39a813984b780b83a0fa08b94.tar.xz
ipxe-78ded6604a49c5b39a813984b780b83a0fa08b94.zip
Try booting from the "boot" network device first (i.e. the one which we
were loaded from). The code to identify this device isn't present yet, but the code to act upon the knowledge is.
Diffstat (limited to 'src/usr/autoboot.c')
-rw-r--r--src/usr/autoboot.c87
1 files changed, 80 insertions, 7 deletions
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index 057b70cd..45b3b6e7 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -17,6 +17,7 @@
*/
#include <string.h>
+#include <errno.h>
#include <vsprintf.h>
#include <gpxe/netdevice.h>
#include <usr/ifmgmt.h>
@@ -30,21 +31,93 @@
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" );
}