]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[autoboot] Allow autoboot device to be identified by link-layer address
authorMichael Brown <mcb30@ipxe.org>
Mon, 7 Jul 2014 22:55:55 +0000 (23:55 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Jul 2014 23:37:31 +0000 (00:37 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/core/pci_autoboot.c
src/include/usr/autoboot.h
src/usr/autoboot.c

index 5e6197e2e2515305c05847f64821a0aa4c98356c..a3eb1f97dda58644a3353f8fef946fe43631750e 100644 (file)
@@ -34,10 +34,8 @@ uint16_t __bss16 ( autoboot_busdevfn );
  */
 static void pci_autoboot_init ( void ) {
 
-       if ( autoboot_busdevfn ) {
-               autoboot_device.bus_type = BUS_TYPE_PCI;
-               autoboot_device.location = autoboot_busdevfn;
-       }
+       if ( autoboot_busdevfn )
+               set_autoboot_busloc ( BUS_TYPE_PCI, autoboot_busdevfn );
 }
 
 /** PCI autoboot device initialisation function */
index f562b2b12f2aae66af4e479ccb8940c3f4d2b5ed..bc51aae79c06ba3f4f3884bb4b39eb4562a250a6 100644 (file)
@@ -9,8 +9,8 @@
 
 FILE_LICENCE ( GPL2_OR_LATER );
 
-#include <ipxe/in.h>
 #include <ipxe/device.h>
+
 struct net_device;
 struct uri;
 struct settings;
@@ -26,7 +26,9 @@ enum uriboot_flags {
                         URIBOOT_NO_SAN_BOOT |     \
                         URIBOOT_NO_SAN_UNHOOK )
 
-extern struct device_description autoboot_device;
+extern void set_autoboot_busloc ( unsigned int bus_type,
+                                 unsigned int location );
+extern void set_autoboot_ll_addr ( const void *ll_addr, size_t len );
 
 extern int uriboot ( struct uri *filename, struct uri *root_path, int drive,
                     unsigned int flags );
index 01c55ef1510a64bd813f9a5c41f340b4c78f64c7..47476ae404d96a57d613fd2f170243c2dfee9c0d 100644 (file)
@@ -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 */