diff options
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/usr')
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/autoboot.c | 233 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/dhcpmgmt.c | 78 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/ifmgmt.c | 147 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/imgmgmt.c | 144 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/iwmgmt.c | 244 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/pxemenu.c | 383 | ||||
-rw-r--r-- | contrib/syslinux-4.02/gpxe/src/usr/route.c | 45 |
7 files changed, 1274 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/usr/autoboot.c b/contrib/syslinux-4.02/gpxe/src/usr/autoboot.c new file mode 100644 index 0000000..2fa10e6 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/autoboot.c @@ -0,0 +1,233 @@ +/* + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <gpxe/netdevice.h> +#include <gpxe/dhcp.h> +#include <gpxe/settings.h> +#include <gpxe/image.h> +#include <gpxe/sanboot.h> +#include <gpxe/uri.h> +#include <usr/ifmgmt.h> +#include <usr/route.h> +#include <usr/dhcpmgmt.h> +#include <usr/imgmgmt.h> +#include <usr/autoboot.h> + +/** @file + * + * Automatic booting + * + */ + +/** Shutdown flags for exit */ +int shutdown_exit_flags = 0; + +/** + * Identify the boot network device + * + * @ret netdev Boot network device + */ +static struct net_device * find_boot_netdev ( void ) { + return NULL; +} + +/** + * Boot using next-server and filename + * + * @v filename Boot filename + * @ret rc Return status code + */ +int boot_next_server_and_filename ( struct in_addr next_server, + const char *filename ) { + struct uri *uri; + struct image *image; + char buf[ 23 /* tftp://xxx.xxx.xxx.xxx/ */ + + ( 3 * strlen(filename) ) /* completely URI-encoded */ + + 1 /* NUL */ ]; + int filename_is_absolute; + int rc; + + /* Construct URI */ + uri = parse_uri ( filename ); + if ( ! uri ) + return -ENOMEM; + filename_is_absolute = uri_is_absolute ( uri ); + uri_put ( uri ); + if ( ! filename_is_absolute ) { + /* Construct a tftp:// URI for the filename. We can't + * just rely on the current working URI, because the + * relative URI resolution will remove the distinction + * between filenames with and without initial slashes, + * which is significant for TFTP. + */ + snprintf ( buf, sizeof ( buf ), "tftp://%s/", + inet_ntoa ( next_server ) ); + uri_encode ( filename, buf + strlen ( buf ), + sizeof ( buf ) - strlen ( buf ), URI_PATH ); + filename = buf; + } + + image = alloc_image(); + if ( ! image ) + return -ENOMEM; + if ( ( rc = imgfetch ( image, filename, + register_and_autoload_image ) ) != 0 ) { + goto done; + } + if ( ( rc = imgexec ( image ) ) != 0 ) + goto done; + + done: + image_put ( image ); + return rc; +} + +/** + * Boot using root path + * + * @v root_path Root path + * @ret rc Return status code + */ +int boot_root_path ( const char *root_path ) { + struct sanboot_protocol *sanboot; + + /* Quick hack */ + for_each_table_entry ( sanboot, SANBOOT_PROTOCOLS ) { + if ( strncmp ( root_path, sanboot->prefix, + strlen ( sanboot->prefix ) ) == 0 ) { + return sanboot->boot ( root_path ); + } + } + + return -ENOTSUP; +} + +/** + * Boot from a network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int netboot ( struct net_device *netdev ) { + struct setting vendor_class_id_setting + = { .tag = DHCP_VENDOR_CLASS_ID }; + struct setting pxe_discovery_control_setting + = { .tag = DHCP_PXE_DISCOVERY_CONTROL }; + struct setting pxe_boot_menu_setting + = { .tag = DHCP_PXE_BOOT_MENU }; + char buf[256]; + struct in_addr next_server; + unsigned int pxe_discovery_control; + 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 PXE menu boot, if applicable */ + fetch_string_setting ( NULL, &vendor_class_id_setting, + buf, sizeof ( buf ) ); + pxe_discovery_control = + fetch_uintz_setting ( NULL, &pxe_discovery_control_setting ); + if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && pxe_menu_boot != NULL && + setting_exists ( NULL, &pxe_boot_menu_setting ) && + ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) && + setting_exists ( NULL, &filename_setting ) ) ) ) { + printf ( "Booting from PXE menu\n" ); + return pxe_menu_boot ( netdev ); + } + + /* Try to download and boot whatever we are given as a filename */ + fetch_ipv4_setting ( NULL, &next_server_setting, &next_server ); + fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) ); + if ( buf[0] ) { + printf ( "Booting from filename \"%s\"\n", buf ); + if ( ( rc = boot_next_server_and_filename ( next_server, + buf ) ) != 0 ) { + printf ( "Could not boot from filename \"%s\": %s\n", + buf, strerror ( rc ) ); + return rc; + } + return 0; + } + + /* No filename; try the root path */ + fetch_string_setting ( NULL, &root_path_setting, buf, sizeof ( buf ) ); + if ( buf[0] ) { + printf ( "Booting from root path \"%s\"\n", buf ); + if ( ( rc = boot_root_path ( buf ) ) != 0 ) { + printf ( "Could not boot from root path \"%s\": %s\n", + buf, strerror ( rc ) ); + return rc; + } + return 0; + } + + printf ( "No filename or root path specified\n" ); + return -ENOENT; +} + +/** + * 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" ); +} diff --git a/contrib/syslinux-4.02/gpxe/src/usr/dhcpmgmt.c b/contrib/syslinux-4.02/gpxe/src/usr/dhcpmgmt.c new file mode 100644 index 0000000..f82a3bb --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/dhcpmgmt.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <gpxe/netdevice.h> +#include <gpxe/dhcp.h> +#include <gpxe/monojob.h> +#include <gpxe/process.h> +#include <usr/ifmgmt.h> +#include <usr/dhcpmgmt.h> + +#define LINK_WAIT_MS 15000 + +/** @file + * + * DHCP management + * + */ + +int dhcp ( struct net_device *netdev ) { + uint8_t *chaddr; + uint8_t hlen; + uint16_t flags; + int rc; + + /* Check we can open the interface first */ + if ( ( rc = ifopen ( netdev ) ) != 0 ) + return rc; + + /* Wait for link-up */ + if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) + return rc; + + /* Perform DHCP */ + chaddr = dhcp_chaddr ( netdev, &hlen, &flags ); + printf ( "DHCP (%s ", netdev->name ); + while ( hlen-- ) + printf ( "%02x%c", *(chaddr++), ( hlen ? ':' : ')' ) ); + + if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) { + rc = monojob_wait ( "" ); + } else if ( rc > 0 ) { + printf ( " using cached\n" ); + rc = 0; + } + + return rc; +} + +int pxebs ( struct net_device *netdev, unsigned int pxe_type ) { + int rc; + + /* Perform PXE Boot Server Discovery */ + printf ( "PXEBS (%s type %d)", netdev->name, pxe_type ); + if ( ( rc = start_pxebs ( &monojob, netdev, pxe_type ) ) == 0 ) + rc = monojob_wait ( "" ); + + return rc; +} diff --git a/contrib/syslinux-4.02/gpxe/src/usr/ifmgmt.c b/contrib/syslinux-4.02/gpxe/src/usr/ifmgmt.c new file mode 100644 index 0000000..d4cc5a5 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/ifmgmt.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2007 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <console.h> +#include <gpxe/netdevice.h> +#include <gpxe/device.h> +#include <gpxe/process.h> +#include <gpxe/keys.h> +#include <usr/ifmgmt.h> + +/** @file + * + * Network interface management + * + */ + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +int ifopen ( struct net_device *netdev ) { + int rc; + + if ( ( rc = netdev_open ( netdev ) ) != 0 ) { + printf ( "Could not open %s: %s\n", + netdev->name, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Close network device + * + * @v netdev Network device + */ +void ifclose ( struct net_device *netdev ) { + netdev_close ( netdev ); +} + +/** + * Print network device error breakdown + * + * @v stats Network device statistics + * @v prefix Message prefix + */ +static void ifstat_errors ( struct net_device_stats *stats, + const char *prefix ) { + unsigned int i; + + for ( i = 0 ; i < ( sizeof ( stats->errors ) / + sizeof ( stats->errors[0] ) ) ; i++ ) { + if ( stats->errors[i].count ) + printf ( " [%s: %d x \"%s\"]\n", prefix, + stats->errors[i].count, + strerror ( stats->errors[i].rc ) ); + } +} + +/** + * Print status of network device + * + * @v netdev Network device + */ +void ifstat ( struct net_device *netdev ) { + printf ( "%s: %s on %s (%s)\n" + " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n", + netdev->name, netdev_addr ( netdev ), netdev->dev->name, + ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ), + ( netdev_link_ok ( netdev ) ? "up" : "down" ), + netdev->tx_stats.good, netdev->tx_stats.bad, + netdev->rx_stats.good, netdev->rx_stats.bad ); + if ( ! netdev_link_ok ( netdev ) ) { + printf ( " [Link status: %s]\n", + strerror ( netdev->link_rc ) ); + } + ifstat_errors ( &netdev->tx_stats, "TXE" ); + ifstat_errors ( &netdev->rx_stats, "RXE" ); +} + +/** + * Wait for link-up, with status indication + * + * @v netdev Network device + * @v max_wait_ms Maximum time to wait, in ms + */ +int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) { + int key; + int rc; + + if ( netdev_link_ok ( netdev ) ) + return 0; + + printf ( "Waiting for link-up on %s...", netdev->name ); + + while ( 1 ) { + if ( netdev_link_ok ( netdev ) ) { + rc = 0; + break; + } + if ( max_wait_ms-- == 0 ) { + rc = netdev->link_rc; + break; + } + step(); + if ( iskey() ) { + key = getchar(); + if ( key == CTRL_C ) { + rc = -ECANCELED; + break; + } + } + mdelay ( 1 ); + } + + if ( rc == 0 ) { + printf ( " ok\n" ); + } else { + printf ( " failed: %s\n", strerror ( rc ) ); + } + + return rc; +} diff --git a/contrib/syslinux-4.02/gpxe/src/usr/imgmgmt.c b/contrib/syslinux-4.02/gpxe/src/usr/imgmgmt.c new file mode 100644 index 0000000..023e3f0 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/imgmgmt.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <gpxe/image.h> +#include <gpxe/downloader.h> +#include <gpxe/monojob.h> +#include <gpxe/open.h> +#include <gpxe/uri.h> +#include <usr/imgmgmt.h> + +/** @file + * + * Image management + * + */ + +/** + * Fetch an image + * + * @v uri_string URI as a string (e.g. "http://www.nowhere.com/vmlinuz") + * @v name Name for image, or NULL + * @v register_image Image registration routine + * @ret rc Return status code + */ +int imgfetch ( struct image *image, const char *uri_string, + int ( * image_register ) ( struct image *image ) ) { + char uri_string_redacted[ strlen ( uri_string ) + 3 /* "***" */ + + 1 /* NUL */ ]; + struct uri *uri; + const char *password; + int rc; + + if ( ! ( uri = parse_uri ( uri_string ) ) ) + return -ENOMEM; + + image_set_uri ( image, uri ); + + /* Redact password portion of URI, if necessary */ + password = uri->password; + if ( password ) + uri->password = "***"; + unparse_uri ( uri_string_redacted, sizeof ( uri_string_redacted ), + uri, URI_ALL ); + uri->password = password; + + if ( ( rc = create_downloader ( &monojob, image, image_register, + LOCATION_URI, uri ) ) == 0 ) + rc = monojob_wait ( uri_string_redacted ); + + uri_put ( uri ); + return rc; +} + +/** + * Load an image + * + * @v image Image + * @ret rc Return status code + */ +int imgload ( struct image *image ) { + int rc; + + /* Try to load image */ + if ( ( rc = image_autoload ( image ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Execute an image + * + * @v image Image + * @ret rc Return status code + */ +int imgexec ( struct image *image ) { + return image_exec ( image ); +} + +/** + * Identify the only loaded image + * + * @ret image Image, or NULL if 0 or >1 images are loaded + */ +struct image * imgautoselect ( void ) { + struct image *image; + struct image *selected_image = NULL; + int flagged_images = 0; + + for_each_image ( image ) { + if ( image->flags & IMAGE_LOADED ) { + selected_image = image; + flagged_images++; + } + } + + return ( ( flagged_images == 1 ) ? selected_image : NULL ); +} + +/** + * Display status of an image + * + * @v image Executable/loadable image + */ +void imgstat ( struct image *image ) { + printf ( "%s: %zd bytes", image->name, image->len ); + if ( image->type ) + printf ( " [%s]", image->type->name ); + if ( image->flags & IMAGE_LOADED ) + printf ( " [LOADED]" ); + if ( image->cmdline ) + printf ( " \"%s\"", image->cmdline ); + printf ( "\n" ); +} + +/** + * Free an image + * + * @v image Executable/loadable image + */ +void imgfree ( struct image *image ) { + unregister_image ( image ); +} diff --git a/contrib/syslinux-4.02/gpxe/src/usr/iwmgmt.c b/contrib/syslinux-4.02/gpxe/src/usr/iwmgmt.c new file mode 100644 index 0000000..59ba103 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/iwmgmt.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>. + * + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdio.h> +#include <console.h> +#include <string.h> +#include <errno.h> +#include <gpxe/net80211.h> +#include <gpxe/ethernet.h> +#include <usr/ifmgmt.h> +#include <usr/iwmgmt.h> +#include <gpxe/errortab.h> + +/** @file + * + * Wireless network interface management + * + */ + +/** + * Print status of 802.11 device + * + * @v dev 802.11 device + */ +void iwstat ( struct net80211_device *dev ) { + + ifstat ( dev->netdev ); + + printf ( " [802.11 "); + if ( dev->state & NET80211_ASSOCIATED ) { + printf ( "SSID '%s', ", dev->essid ); + } else { + printf ( "not associated, " ); + } + if ( dev->channel < dev->nr_channels && dev->rate < dev->nr_rates ) { + printf ( "Ch:%d Sig:%d", dev->channels[dev->channel].channel_nr, + dev->last_signal ); + switch ( dev->hw->signal_type ) { + case NET80211_SIGNAL_NONE: + printf ( "?" ); + break; + case NET80211_SIGNAL_ARBITRARY: + printf ( "/%d", dev->hw->signal_max ); + break; + case NET80211_SIGNAL_DB: + printf ( "/%d dB", dev->hw->signal_max ); + break; + case NET80211_SIGNAL_DBM: + printf ( " dBm" ); + break; + } + printf ( ", Qual:%d%% Rate:%d Mbps]\n", + ( dev->rx_beacon_interval == 0 ? 0 : + 100 * dev->tx_beacon_interval / + dev->rx_beacon_interval ), + dev->rates[dev->rate] / 10 ); + } else { + printf ( "antenna off]\n" ); + } + + if ( dev->state & NET80211_WORKING ) { + printf ( " [associating" ); + if ( dev->associating ) + printf ( " to '%s'", dev->associating->essid ); + printf ( "...]\n" ); + } +} + +/** Identifiers for 802.11 cryptography types, indexed by type number */ +static const char *crypto_types[] = { + [NET80211_CRYPT_NONE] = "Open", + [NET80211_CRYPT_WEP] = "WEP ", + [NET80211_CRYPT_TKIP] = "WPA ", + [NET80211_CRYPT_CCMP] = "WPA2", + [NET80211_CRYPT_UNKNOWN] = "UNK ", +}; + +/** Number of 802.11 cryptography types defined */ +#define NR_CRYPTO_TYPES ( sizeof ( crypto_types ) / sizeof ( crypto_types[0] ) ) + +/** Identifiers for 802.11 authentication types, indexed by type number */ +static const char *auth_types[] = { + [NET80211_SECPROT_NONE] = "", + [NET80211_SECPROT_PSK] = "PSK", + [NET80211_SECPROT_EAP] = "802.1X", + [NET80211_SECPROT_UNKNOWN] = "UNK", +}; + +/** Number of 802.11 authentication types defined */ +#define NR_AUTH_TYPES ( sizeof ( auth_types ) / sizeof ( auth_types[0] ) ) + +/** + * Scan for wireless networks using 802.11 device + * + * @v dev 802.11 device + * @v active Whether to use active scanning + * + * The list of networks found will be printed in tabular format. + * + * This function is safe to call at all times, whether the 802.11 + * device is open or not, but if called while the auto-association + * task is running it will return an error indication. + */ +int iwlist ( struct net80211_device *dev ) { + struct net80211_probe_ctx *ctx; + struct list_head *networks; + struct net80211_wlan *wlan; + char ssid_buf[22]; + int rc; + unsigned i; + int was_opened = dev->netdev->state & NETDEV_OPEN; + int was_channel = dev->channels[dev->channel].channel_nr; + + if ( ! was_opened ) { + dev->state |= NET80211_NO_ASSOC; + rc = netdev_open ( dev->netdev ); + if ( rc < 0 ) + goto err; + } + + if ( dev->state & NET80211_WORKING ) { + rc = -EINVAL; + goto err_close_netdev; + } + + if ( ! was_opened ) { + rc = net80211_prepare_probe ( dev, dev->hw->bands, 0 ); + if ( rc < 0 ) + goto err_close_netdev; + } + + ctx = net80211_probe_start ( dev, "", 0 ); + if ( ! ctx ) { + rc = -ENOMEM; + goto err_close_netdev; + } + + while ( ! ( rc = net80211_probe_step ( ctx ) ) ) { + step(); + } + + networks = net80211_probe_finish_all ( ctx ); + + if ( list_empty ( networks ) ) { + goto err_free_networks; + } + + rc = 0; + + printf ( "Networks on %s:\n\n", dev->netdev->name ); + + /* Output format: + * 0 1 2 3 4 5 6 + * 0123456789012345678901234567890123456789012345678901234567890 + * [Sig] SSID BSSID Ch Crypt/Auth + * ------------------------------------------------------------- + * [ 15] abcdefghijklmnopqrst> 00:00:00:00:00:00 11 Open + * ... or WPA PSK etc. + */ + + /* Quoting the dashes and spaces verbatim uses less code space + than generating them programmatically. */ + printf ( "[Sig] SSID BSSID Ch Crypt/Auth\n" + "-------------------------------------------------------------\n" ); + + list_for_each_entry ( wlan, networks, list ) { + + /* Format SSID into 22-character string, space-padded, + with '>' indicating truncation */ + + snprintf ( ssid_buf, sizeof ( ssid_buf ), "%s", wlan->essid ); + for ( i = strlen ( ssid_buf ); i < sizeof ( ssid_buf ) - 1; + i++ ) + ssid_buf[i] = ' '; + if ( ssid_buf[sizeof ( ssid_buf ) - 2] != ' ' ) + ssid_buf[sizeof ( ssid_buf ) - 2] = '>'; + ssid_buf[sizeof ( ssid_buf ) - 1] = 0; + + /* Sanity check */ + if ( wlan->crypto >= NR_CRYPTO_TYPES || + wlan->handshaking >= NR_AUTH_TYPES ) + continue; + + printf ( "[%3d] %s %s %2d %s %s\n", + wlan->signal < 0 ? 100 + wlan->signal : wlan->signal, + ssid_buf, eth_ntoa ( wlan->bssid ), wlan->channel, + crypto_types[wlan->crypto], + auth_types[wlan->handshaking] ); + } + printf ( "\n" ); + + err_free_networks: + net80211_free_wlanlist ( networks ); + + err_close_netdev: + if ( ! was_opened ) { + dev->state &= ~NET80211_NO_ASSOC; + netdev_close ( dev->netdev ); + } else { + net80211_change_channel ( dev, was_channel ); + } + + if ( ! rc ) + return 0; + + err: + printf ( "Scanning for networks on %s: %s\n", + dev->netdev->name, strerror ( rc ) ); + return rc; +} + + +/* Record error codes as though they come from the 802.11 stack */ +#undef ERRFILE +#define ERRFILE ERRFILE_net80211 + +/** Common 802.11 errors */ +struct errortab common_wireless_errors[] __errortab = { + { EINVAL | EUNIQ_06, "Packet decryption error" }, + { ECONNRESET | EUNIQ_01, "Unspecified reason" }, + { ECONNRESET | EUNIQ_04, "Disassociated due to inactivity" }, + { ECONNRESET | EUNIQ_0F, "4-Way Handshake timeout" }, + { ECONNRESET | EUNIQ_17, "IEEE 802.1X authentication failed" }, + { ECONNREFUSED | EUNIQ_01, "Unspecified failure" }, + { ECONNREFUSED | EUNIQ_0C, "Association denied" }, + { ECONNREFUSED | EUNIQ_0D, "Authentication method not supported" }, +}; diff --git a/contrib/syslinux-4.02/gpxe/src/usr/pxemenu.c b/contrib/syslinux-4.02/gpxe/src/usr/pxemenu.c new file mode 100644 index 0000000..519c200 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/pxemenu.c @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2009 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <byteswap.h> +#include <curses.h> +#include <console.h> +#include <gpxe/dhcp.h> +#include <gpxe/keys.h> +#include <gpxe/timer.h> +#include <gpxe/process.h> +#include <usr/dhcpmgmt.h> +#include <usr/autoboot.h> + +/** @file + * + * PXE Boot Menus + * + */ + +/* Colour pairs */ +#define CPAIR_NORMAL 1 +#define CPAIR_SELECT 2 + +/** A PXE boot menu item */ +struct pxe_menu_item { + /** Boot Server type */ + unsigned int type; + /** Description */ + char *desc; +}; + +/** + * A PXE boot menu + * + * This structure encapsulates the menu information provided via DHCP + * options. + */ +struct pxe_menu { + /** Prompt string (optional) */ + const char *prompt; + /** Timeout (in seconds) + * + * Negative indicates no timeout (i.e. wait indefinitely) + */ + int timeout; + /** Number of menu items */ + unsigned int num_items; + /** Selected menu item */ + unsigned int selection; + /** Menu items */ + struct pxe_menu_item items[0]; +}; + +/** + * Parse and allocate PXE boot menu + * + * @v menu PXE boot menu to fill in + * @ret rc Return status code + * + * It is the callers responsibility to eventually free the allocated + * boot menu. + */ +static int pxe_menu_parse ( struct pxe_menu **menu ) { + struct setting pxe_boot_menu_prompt_setting = + { .tag = DHCP_PXE_BOOT_MENU_PROMPT }; + struct setting pxe_boot_menu_setting = + { .tag = DHCP_PXE_BOOT_MENU }; + uint8_t raw_menu[256]; + int raw_prompt_len; + int raw_menu_len; + struct dhcp_pxe_boot_menu *raw_menu_item; + struct dhcp_pxe_boot_menu_prompt *raw_menu_prompt; + void *raw_menu_end; + unsigned int num_menu_items; + unsigned int i; + int rc; + + /* Fetch raw menu */ + memset ( raw_menu, 0, sizeof ( raw_menu ) ); + if ( ( raw_menu_len = fetch_setting ( NULL, &pxe_boot_menu_setting, + raw_menu, + sizeof ( raw_menu ) ) ) < 0 ) { + rc = raw_menu_len; + DBG ( "Could not retrieve raw PXE boot menu: %s\n", + strerror ( rc ) ); + return rc; + } + if ( raw_menu_len >= ( int ) sizeof ( raw_menu ) ) { + DBG ( "Raw PXE boot menu too large for buffer\n" ); + return -ENOSPC; + } + raw_menu_end = ( raw_menu + raw_menu_len ); + + /* Fetch raw prompt length */ + raw_prompt_len = fetch_setting_len ( NULL, + &pxe_boot_menu_prompt_setting ); + if ( raw_prompt_len < 0 ) + raw_prompt_len = 0; + + /* Count menu items */ + num_menu_items = 0; + raw_menu_item = ( ( void * ) raw_menu ); + while ( 1 ) { + if ( ( ( ( void * ) raw_menu_item ) + + sizeof ( *raw_menu_item ) ) > raw_menu_end ) + break; + if ( ( ( ( void * ) raw_menu_item ) + + sizeof ( *raw_menu_item ) + + raw_menu_item->desc_len ) > raw_menu_end ) + break; + num_menu_items++; + raw_menu_item = ( ( ( void * ) raw_menu_item ) + + sizeof ( *raw_menu_item ) + + raw_menu_item->desc_len ); + } + + /* Allocate space for parsed menu */ + *menu = zalloc ( sizeof ( **menu ) + + ( num_menu_items * sizeof ( (*menu)->items[0] ) ) + + raw_menu_len + 1 /* NUL */ + + raw_prompt_len + 1 /* NUL */ ); + if ( ! *menu ) { + DBG ( "Could not allocate PXE boot menu\n" ); + return -ENOMEM; + } + + /* Fill in parsed menu */ + (*menu)->num_items = num_menu_items; + raw_menu_item = ( ( ( void * ) (*menu) ) + sizeof ( **menu ) + + ( num_menu_items * sizeof ( (*menu)->items[0] ) ) ); + memcpy ( raw_menu_item, raw_menu, raw_menu_len ); + for ( i = 0 ; i < num_menu_items ; i++ ) { + (*menu)->items[i].type = le16_to_cpu ( raw_menu_item->type ); + (*menu)->items[i].desc = raw_menu_item->desc; + /* Set type to 0; this ensures that the description + * for the previous menu item is NUL-terminated. + * (Final item is NUL-terminated anyway.) + */ + raw_menu_item->type = 0; + raw_menu_item = ( ( ( void * ) raw_menu_item ) + + sizeof ( *raw_menu_item ) + + raw_menu_item->desc_len ); + } + if ( raw_prompt_len ) { + raw_menu_prompt = ( ( ( void * ) raw_menu_item ) + + 1 /* NUL */ ); + fetch_setting ( NULL, &pxe_boot_menu_prompt_setting, + raw_menu_prompt, raw_prompt_len ); + (*menu)->timeout = + ( ( raw_menu_prompt->timeout == 0xff ) ? + -1 : raw_menu_prompt->timeout ); + (*menu)->prompt = raw_menu_prompt->prompt; + } else { + (*menu)->timeout = -1; + } + + return 0; +} + +/** + * Draw PXE boot menu item + * + * @v menu PXE boot menu + * @v index Index of item to draw + * @v selected Item is selected + */ +static void pxe_menu_draw_item ( struct pxe_menu *menu, + unsigned int index, int selected ) { + char buf[COLS+1]; + size_t len; + unsigned int row; + + /* Prepare space-padded row content */ + len = snprintf ( buf, sizeof ( buf ), " %c. %s", + ( 'A' + index ), menu->items[index].desc ); + while ( len < ( sizeof ( buf ) - 1 ) ) + buf[len++] = ' '; + buf[ sizeof ( buf ) - 1 ] = '\0'; + + /* Draw row */ + row = ( LINES - menu->num_items + index ); + color_set ( ( selected ? CPAIR_SELECT : CPAIR_NORMAL ), NULL ); + mvprintw ( row, 0, "%s", buf ); + move ( row, 1 ); +} + +/** + * Make selection from PXE boot menu + * + * @v menu PXE boot menu + * @ret rc Return status code + */ +static int pxe_menu_select ( struct pxe_menu *menu ) { + int key; + unsigned int key_selection; + unsigned int i; + int rc = 0; + + /* Initialise UI */ + initscr(); + start_color(); + init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK ); + init_pair ( CPAIR_SELECT, COLOR_BLACK, COLOR_WHITE ); + color_set ( CPAIR_NORMAL, NULL ); + + /* Draw initial menu */ + for ( i = 0 ; i < menu->num_items ; i++ ) + printf ( "\n" ); + for ( i = 0 ; i < menu->num_items ; i++ ) + pxe_menu_draw_item ( menu, ( menu->num_items - i - 1 ), 0 ); + + while ( 1 ) { + + /* Highlight currently selected item */ + pxe_menu_draw_item ( menu, menu->selection, 1 ); + + /* Wait for keyboard input */ + while ( ! iskey() ) + step(); + key = getkey(); + + /* Unhighlight currently selected item */ + pxe_menu_draw_item ( menu, menu->selection, 0 ); + + /* Act upon key */ + if ( ( key == CR ) || ( key == LF ) ) { + pxe_menu_draw_item ( menu, menu->selection, 1 ); + break; + } else if ( ( key == CTRL_C ) || ( key == ESC ) ) { + rc = -ECANCELED; + break; + } else if ( key == KEY_UP ) { + if ( menu->selection > 0 ) + menu->selection--; + } else if ( key == KEY_DOWN ) { + if ( menu->selection < ( menu->num_items - 1 ) ) + menu->selection++; + } else if ( ( key < KEY_MIN ) && + ( ( key_selection = ( toupper ( key ) - 'A' ) ) + < menu->num_items ) ) { + menu->selection = key_selection; + pxe_menu_draw_item ( menu, menu->selection, 1 ); + break; + } + } + + /* Shut down UI */ + endwin(); + + return rc; +} + +/** + * Prompt for (and make selection from) PXE boot menu + * + * @v menu PXE boot menu + * @ret rc Return status code + */ +static int pxe_menu_prompt_and_select ( struct pxe_menu *menu ) { + unsigned long start = currticks(); + unsigned long now; + unsigned long elapsed; + size_t len = 0; + int key; + int rc = 0; + + /* Display menu immediately, if specified to do so */ + if ( menu->timeout < 0 ) { + if ( menu->prompt ) + printf ( "%s\n", menu->prompt ); + return pxe_menu_select ( menu ); + } + + /* Display prompt, if specified */ + if ( menu->prompt ) + printf ( "%s", menu->prompt ); + + /* Wait for timeout, if specified */ + while ( menu->timeout > 0 ) { + if ( ! len ) + len = printf ( " (%d)", menu->timeout ); + if ( iskey() ) { + key = getkey(); + if ( key == KEY_F8 ) { + /* Display menu */ + printf ( "\n" ); + return pxe_menu_select ( menu ); + } else if ( ( key == CTRL_C ) || ( key == ESC ) ) { + /* Abort */ + rc = -ECANCELED; + break; + } else { + /* Stop waiting */ + break; + } + } + now = currticks(); + elapsed = ( now - start ); + if ( elapsed >= TICKS_PER_SEC ) { + menu->timeout -= 1; + do { + printf ( "\b \b" ); + } while ( --len ); + start = now; + } + } + + /* Return with default option selected */ + printf ( "\n" ); + return rc; +} + +/** + * Boot using PXE boot menu + * + * @ret rc Return status code + * + * Note that a success return status indicates that a PXE boot menu + * item has been selected, and that the DHCP session should perform a + * boot server request/ack. + */ +int pxe_menu_boot ( struct net_device *netdev ) { + struct pxe_menu *menu; + unsigned int pxe_type; + struct settings *pxebs_settings; + struct in_addr next_server; + char filename[256]; + int rc; + + /* Parse and allocate boot menu */ + if ( ( rc = pxe_menu_parse ( &menu ) ) != 0 ) + return rc; + + /* Make selection from boot menu */ + if ( ( rc = pxe_menu_prompt_and_select ( menu ) ) != 0 ) { + free ( menu ); + return rc; + } + pxe_type = menu->items[menu->selection].type; + + /* Free boot menu */ + free ( menu ); + + /* Return immediately if local boot selected */ + if ( ! pxe_type ) + return 0; + + /* Attempt PXE Boot Server Discovery */ + if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) + return rc; + + /* Attempt boot */ + pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME ); + assert ( pxebs_settings ); + fetch_ipv4_setting ( pxebs_settings, &next_server_setting, + &next_server ); + fetch_string_setting ( pxebs_settings, &filename_setting, + filename, sizeof ( filename ) ); + return boot_next_server_and_filename ( next_server, filename ); +} diff --git a/contrib/syslinux-4.02/gpxe/src/usr/route.c b/contrib/syslinux-4.02/gpxe/src/usr/route.c new file mode 100644 index 0000000..1875741 --- /dev/null +++ b/contrib/syslinux-4.02/gpxe/src/usr/route.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdio.h> +#include <gpxe/netdevice.h> +#include <gpxe/ip.h> +#include <usr/route.h> + +/** @file + * + * Routing table management + * + */ + +void route ( void ) { + struct ipv4_miniroute *miniroute; + + list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { + printf ( "%s: %s/", miniroute->netdev->name, + inet_ntoa ( miniroute->address ) ); + printf ( "%s", inet_ntoa ( miniroute->netmask ) ); + if ( miniroute->gateway.s_addr ) + printf ( " gw %s", inet_ntoa ( miniroute->gateway ) ); + if ( ! ( miniroute->netdev->state & NETDEV_OPEN ) ) + printf ( " (inaccessible)" ); + printf ( "\n" ); + } +} |