summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorMichael Brown2014-07-08 00:55:55 +0200
committerMichael Brown2014-07-08 01:37:31 +0200
commit00c745e5ffd6c6be9c8a31223955527a5aca6f92 (patch)
tree74cfea02fb340839c86bf8b272f1f6deb8c216fd /src/usr
parent[efi] Allow network devices to be created on top of arbitrary SNP devices (diff)
downloadipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.tar.gz
ipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.tar.xz
ipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.zip
[autoboot] Allow autoboot device to be identified by link-layer address
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/autoboot.c68
1 files changed, 59 insertions, 9 deletions
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index 01c55ef1..47476ae4 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -49,8 +49,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
*/
-/** Device location of preferred autoboot device */
-struct device_description autoboot_device;
+/** Link-layer address of preferred autoboot device, if known */
+static uint8_t autoboot_ll_addr[MAX_LL_ADDR_LEN];
+
+/** Device location of preferred autoboot device, if known */
+static struct device_description autoboot_desc;
+
+/** Autoboot device tester */
+static int ( * is_autoboot_device ) ( struct net_device *netdev );
/* Disambiguate the various error causes */
#define ENOENT_BOOT __einfo_error ( EINFO_ENOENT_BOOT )
@@ -422,15 +428,60 @@ int netboot ( struct net_device *netdev ) {
}
/**
- * Test if network device matches the autoboot device location
+ * Test if network device matches the autoboot device bus type and location
*
* @v netdev Network device
- * @ret is_autoboot Network device matches the autoboot device location
+ * @ret is_autoboot Network device matches the autoboot device
+ */
+static int is_autoboot_busloc ( struct net_device *netdev ) {
+
+ return ( ( netdev->dev->desc.bus_type == autoboot_desc.bus_type ) &&
+ ( netdev->dev->desc.location == autoboot_desc.location ) );
+}
+
+/**
+ * Identify autoboot device by bus type and location
+ *
+ * @v bus_type Bus type
+ * @v location Location
*/
-static int is_autoboot_device ( struct net_device *netdev ) {
+void set_autoboot_busloc ( unsigned int bus_type, unsigned int location ) {
+
+ /* Record autoboot device description */
+ autoboot_desc.bus_type = bus_type;
+ autoboot_desc.location = location;
+
+ /* Mark autoboot device as present */
+ is_autoboot_device = is_autoboot_busloc;
+}
+
+/**
+ * Test if network device matches the autoboot device link-layer address
+ *
+ * @v netdev Network device
+ * @ret is_autoboot Network device matches the autoboot device
+ */
+static int is_autoboot_ll_addr ( struct net_device *netdev ) {
+
+ return ( memcmp ( netdev->ll_addr, autoboot_ll_addr,
+ netdev->ll_protocol->ll_addr_len ) == 0 );
+}
+
+/**
+ * Identify autoboot device by link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v len Length of link-layer address
+ */
+void set_autoboot_ll_addr ( const void *ll_addr, size_t len ) {
+
+ /* Record autoboot link-layer address (truncated if necessary) */
+ if ( len > sizeof ( autoboot_ll_addr ) )
+ len = sizeof ( autoboot_ll_addr );
+ memcpy ( autoboot_ll_addr, ll_addr, len );
- return ( ( netdev->dev->desc.bus_type == autoboot_device.bus_type ) &&
- ( netdev->dev->desc.location == autoboot_device.location ) );
+ /* Mark autoboot device as present */
+ is_autoboot_device = is_autoboot_ll_addr;
}
/**
@@ -447,8 +498,7 @@ static int autoboot ( void ) {
for_each_netdev ( netdev ) {
/* Skip any non-matching devices, if applicable */
- if ( autoboot_device.bus_type &&
- ( ! is_autoboot_device ( netdev ) ) )
+ if ( is_autoboot_device && ( ! is_autoboot_device ( netdev ) ) )
continue;
/* Attempt booting from this device */