diff options
author | Michael Brown <mcb30@ipxe.org> | 2020-10-19 14:12:48 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2020-10-19 14:45:49 +0100 |
commit | 2d49ce6f08002d9e92c2ba819c65a8b093e975f4 (patch) | |
tree | ca536dc238814e80fa0f5096aa953769ff36bf55 | |
parent | 6154b1fb2003bafa56ce35365f681d0c2fb1a503 (diff) | |
download | ipxe-2d49ce6f08002d9e92c2ba819c65a8b093e975f4.tar.gz |
[efi] Provide utility function to concatenate 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 | 52 |
2 files changed, 54 insertions, 0 deletions
diff --git a/src/include/ipxe/efi/efi_path.h b/src/include/ipxe/efi/efi_path.h index d4d43852f..b27441d07 100644 --- a/src/include/ipxe/efi/efi_path.h +++ b/src/include/ipxe/efi/efi_path.h @@ -20,6 +20,8 @@ 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_paths ( EFI_DEVICE_PATH_PROTOCOL *first, + ... ); 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 3faf47617..3c8a3be57 100644 --- a/src/interface/efi/efi_path.c +++ b/src/interface/efi/efi_path.c @@ -18,6 +18,7 @@ */ #include <stdlib.h> +#include <stdarg.h> #include <string.h> #include <byteswap.h> #include <ipxe/netdevice.h> @@ -65,6 +66,57 @@ size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path ) { } /** + * Concatenate EFI device paths + * + * @v ... List of device paths (NULL terminated) + * @ret path Concatenated device path, or NULL on error + * + * The caller is responsible for eventually calling free() on the + * allocated device path. + */ +EFI_DEVICE_PATH_PROTOCOL * efi_paths ( EFI_DEVICE_PATH_PROTOCOL *first, ... ) { + EFI_DEVICE_PATH_PROTOCOL *path; + EFI_DEVICE_PATH_PROTOCOL *src; + EFI_DEVICE_PATH_PROTOCOL *dst; + EFI_DEVICE_PATH_PROTOCOL *end; + va_list args; + size_t len; + + /* Calculate device path length */ + va_start ( args, first ); + len = 0; + src = first; + while ( src ) { + len += efi_path_len ( src ); + src = va_arg ( args, EFI_DEVICE_PATH_PROTOCOL * ); + } + va_end ( args ); + + /* Allocate device path */ + path = zalloc ( len + sizeof ( *end ) ); + if ( ! path ) + return NULL; + + /* Populate device path */ + va_start ( args, first ); + dst = path; + src = first; + while ( src ) { + len = efi_path_len ( src ); + memcpy ( dst, src, len ); + dst = ( ( ( void * ) dst ) + len ); + src = va_arg ( args, EFI_DEVICE_PATH_PROTOCOL * ); + } + va_end ( args ); + end = dst; + 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 network device * * @v netdev Network device |