diff options
author | Michael Brown | 2020-10-19 14:44:43 +0200 |
---|---|---|
committer | Michael Brown | 2020-10-19 15:45:49 +0200 |
commit | 6154b1fb2003bafa56ce35365f681d0c2fb1a503 (patch) | |
tree | e9818caf6e70a4063b637ff09f30d55c6110cd3e /src/interface/efi/efi_path.c | |
parent | [http] Allow HTTP connection to be described using an EFI device path (diff) | |
download | ipxe-6154b1fb2003bafa56ce35365f681d0c2fb1a503.tar.gz ipxe-6154b1fb2003bafa56ce35365f681d0c2fb1a503.tar.xz ipxe-6154b1fb2003bafa56ce35365f681d0c2fb1a503.zip |
[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>
Diffstat (limited to 'src/interface/efi/efi_path.c')
-rw-r--r-- | src/interface/efi/efi_path.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c index 6201c023..3faf4761 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 |