diff options
author | Michael Brown <mcb30@ipxe.org> | 2014-07-07 23:55:55 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2014-07-08 00:37:31 +0100 |
commit | 00c745e5ffd6c6be9c8a31223955527a5aca6f92 (patch) | |
tree | 74cfea02fb340839c86bf8b272f1f6deb8c216fd /src/usr | |
parent | c7051d826b43954b1e191667a75b21b44ec02c35 (diff) | |
download | ipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.zip ipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.tar.gz ipxe-00c745e5ffd6c6be9c8a31223955527a5aca6f92.tar.bz2 |
[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.c | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 01c55ef..47476ae 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 */ |