diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 057b70cd0..45b3b6e7b 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -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; +} - ifstat ( netdev ); +/** + * Boot from a network device + * + * @v netdev Network device + */ +void netboot ( struct net_device *netdev ) { - test_dhcp ( netdev ); - + /* Open device and display device status */ + if ( ifopen ( netdev ) != 0 ) + return; + 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; + + 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" ); }