]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Provide utility function to concatenate device paths
authorMichael Brown <mcb30@ipxe.org>
Mon, 19 Oct 2020 13:12:48 +0000 (14:12 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 19 Oct 2020 13:45:49 +0000 (14:45 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_path.h
src/interface/efi/efi_path.c

index d4d43852fb45a7f94e7f3bfae9ece359dfe4d2a4..b27441d07ccb5e350f03171a37865ce5cda82bc5 100644 (file)
@@ -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 );
index 3faf47617710a4edd89cd8c77274adc417defa29..3c8a3be573b7961c2fafffde534e7f982c37373e 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <byteswap.h>
 #include <ipxe/netdevice.h>
@@ -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
  *