From: Michael Brown Date: Mon, 19 Oct 2020 13:12:48 +0000 (+0100) Subject: [efi] Provide utility function to concatenate device paths X-Git-Tag: v1.21.1~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d49ce6f08002d9e92c2ba819c65a8b093e975f4;p=thirdparty%2Fipxe.git [efi] Provide utility function to concatenate device paths Signed-off-by: Michael Brown --- 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 +#include #include #include #include @@ -64,6 +65,57 @@ size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path ) { return ( ( ( void * ) end ) - ( ( void * ) 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 *