diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-10-19 13:44:43 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-10-19 14:45:49 +0100 |
commit | 6154b1fb2003bafa56ce35365f681d0c2fb1a503 (patch) | |
tree | e9818caf6e70a4063b637ff09f30d55c6110cd3e | |
parent | b50ad5f09ab11f7d5b61a9a5c21637ea139fda08 (diff) | |
download | ipxe-6154b1fb2003bafa56ce35365f681d0c2fb1a503.tar.gz |
[efi] Split efi_netdev_path() out to a separate function
Provide efi_netdev_path() as a standalone function, to allow for reuse
when constructing child device paths.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/include/ipxe/efi/efi_path.h | 2 | ||||
-rw-r--r-- | src/interface/efi/efi_path.c | 65 | ||||
-rw-r--r-- | src/interface/efi/efi_snp.c | 41 |
3 files changed, 71 insertions, 37 deletions
diff --git a/src/include/ipxe/efi/efi_path.h b/src/include/ipxe/efi/efi_path.h index f52410e36..d4d43852f 100644 --- a/src/include/ipxe/efi/efi_path.h +++ b/src/include/ipxe/efi/efi_path.h @@ -13,12 +13,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/efi/efi.h> #include <ipxe/efi/Protocol/DevicePath.h> +struct net_device; struct uri; struct usb_function; extern EFI_DEVICE_PATH_PROTOCOL * efi_path_end ( EFI_DEVICE_PATH_PROTOCOL *path ); extern size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path ); +extern EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev ); extern EFI_DEVICE_PATH_PROTOCOL * efi_uri_path ( struct uri *uri ); extern EFI_DEVICE_PATH_PROTOCOL * efi_usb_path ( struct usb_function *func ); diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c index 6201c023e..3faf47617 100644 --- a/src/interface/efi/efi_path.c +++ b/src/interface/efi/efi_path.c @@ -19,6 +19,9 @@ #include <stdlib.h> #include <string.h> +#include <byteswap.h> +#include <ipxe/netdevice.h> +#include <ipxe/vlan.h> #include <ipxe/uri.h> #include <ipxe/usb.h> #include <ipxe/efi/efi.h> @@ -62,6 +65,68 @@ size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path ) { } /** + * Construct EFI device path for network device + * + * @v netdev Network device + * @ret path EFI device path, or NULL on error + * + * The caller is responsible for eventually calling free() on the + * allocated device path. + */ +EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev ) { + struct efi_device *efidev; + EFI_DEVICE_PATH_PROTOCOL *path; + MAC_ADDR_DEVICE_PATH *macpath; + VLAN_DEVICE_PATH *vlanpath; + EFI_DEVICE_PATH_PROTOCOL *end; + unsigned int tag; + size_t prefix_len; + size_t len; + + /* Find parent EFI device */ + efidev = efidev_parent ( netdev->dev ); + if ( ! efidev ) + return NULL; + + /* Calculate device path length */ + prefix_len = efi_path_len ( efidev->path ); + len = ( prefix_len + sizeof ( *macpath ) + sizeof ( *vlanpath ) + + sizeof ( *end ) ); + + /* Allocate device path */ + path = zalloc ( len ); + if ( ! path ) + return NULL; + + /* Construct device path */ + memcpy ( path, efidev->path, prefix_len ); + macpath = ( ( ( void * ) path ) + prefix_len ); + macpath->Header.Type = MESSAGING_DEVICE_PATH; + macpath->Header.SubType = MSG_MAC_ADDR_DP; + macpath->Header.Length[0] = sizeof ( *macpath ); + assert ( netdev->ll_protocol->ll_addr_len < + sizeof ( macpath->MacAddress ) ); + memcpy ( &macpath->MacAddress, netdev->ll_addr, + netdev->ll_protocol->ll_addr_len ); + macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto ); + if ( ( tag = vlan_tag ( netdev ) ) ) { + vlanpath = ( ( ( void * ) macpath ) + sizeof ( *macpath ) ); + vlanpath->Header.Type = MESSAGING_DEVICE_PATH; + vlanpath->Header.SubType = MSG_VLAN_DP; + vlanpath->Header.Length[0] = sizeof ( *vlanpath ); + vlanpath->VlanId = tag; + end = ( ( ( void * ) vlanpath ) + sizeof ( *vlanpath ) ); + } else { + end = ( ( ( void * ) macpath ) + sizeof ( *macpath ) ); + } + end->Type = END_DEVICE_PATH_TYPE; + end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + end->Length[0] = sizeof ( *end ); + + return path; +} + +/** * Construct EFI device path for URI * * @v uri URI diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index f5c736a11..91e796a2e 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -1624,12 +1624,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_device *efidev; struct efi_snp_device *snpdev; - EFI_DEVICE_PATH_PROTOCOL *path_end; - MAC_ADDR_DEVICE_PATH *macpath; - VLAN_DEVICE_PATH *vlanpath; - size_t path_prefix_len = 0; unsigned int ifcnt; - unsigned int tag; void *interface; EFI_STATUS efirc; int rc; @@ -1714,41 +1709,13 @@ static int efi_snp_probe ( struct net_device *netdev ) { sizeof ( snpdev->name[0] ) ), "%s", netdev->name ); - /* Allocate the new device path */ - path_prefix_len = efi_path_len ( efidev->path ); - snpdev->path = zalloc ( path_prefix_len + sizeof ( *macpath ) + - sizeof ( *vlanpath ) + sizeof ( *path_end ) ); + /* Construct device path */ + snpdev->path = efi_netdev_path ( netdev ); if ( ! snpdev->path ) { rc = -ENOMEM; - goto err_alloc_device_path; + goto err_path; } - /* Populate the device path */ - memcpy ( snpdev->path, efidev->path, path_prefix_len ); - macpath = ( ( ( void * ) snpdev->path ) + path_prefix_len ); - memset ( macpath, 0, sizeof ( *macpath ) ); - macpath->Header.Type = MESSAGING_DEVICE_PATH; - macpath->Header.SubType = MSG_MAC_ADDR_DP; - macpath->Header.Length[0] = sizeof ( *macpath ); - memcpy ( &macpath->MacAddress, netdev->ll_addr, - netdev->ll_protocol->ll_addr_len ); - macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto ); - if ( ( tag = vlan_tag ( netdev ) ) ) { - vlanpath = ( ( ( void * ) macpath ) + sizeof ( *macpath ) ); - memset ( vlanpath, 0, sizeof ( *vlanpath ) ); - vlanpath->Header.Type = MESSAGING_DEVICE_PATH; - vlanpath->Header.SubType = MSG_VLAN_DP; - vlanpath->Header.Length[0] = sizeof ( *vlanpath ); - vlanpath->VlanId = tag; - path_end = ( ( ( void * ) vlanpath ) + sizeof ( *vlanpath ) ); - } else { - path_end = ( ( ( void * ) macpath ) + sizeof ( *macpath ) ); - } - memset ( path_end, 0, sizeof ( *path_end ) ); - path_end->Type = END_DEVICE_PATH_TYPE; - path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - path_end->Length[0] = sizeof ( *path_end ); - /* Install the SNP */ if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( &snpdev->handle, @@ -1847,7 +1814,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { NULL ); err_install_protocol_interface: free ( snpdev->path ); - err_alloc_device_path: + err_path: bs->CloseEvent ( snpdev->snp.WaitForPacket ); err_create_event: err_ll_addr_len: |