]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Split efi_usb_path() out to a separate function
authorMichael Brown <mcb30@ipxe.org>
Fri, 16 Oct 2020 14:07:14 +0000 (15:07 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 16 Oct 2020 14:38:18 +0000 (15:38 +0100)
Provide efi_usb_path() as a standalone function, to allow for reuse by
the USB mass storage driver.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_path.h
src/include/ipxe/efi/efi_usb.h
src/interface/efi/efi_path.c
src/interface/efi/efi_usb.c

index 0d5b902e545ccb2be56f80e26db103f13d9e0433..c1d53e7645abc77dbaaed664b6f99ce65aaf2862 100644 (file)
@@ -13,9 +13,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/efi/efi.h>
 #include <ipxe/efi/Protocol/DevicePath.h>
 
+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_usb_path ( struct usb_function *func );
 
 extern EFI_DEVICE_PATH_PROTOCOL * efi_describe ( struct interface *interface );
 #define efi_describe_TYPE( object_type ) \
index 41d9cc665f253745c61fc2c509b2a6844361f7d2..06baff5293675ad2280e0f33f24bd2dbd344980a 100644 (file)
 struct efi_usb_device {
        /** Name */
        const char *name;
-       /** The underlying USB device */
-       struct usb_device *usb;
-       /** The underlying EFI device */
-       struct efi_device *efidev;
+       /** The underlying USB function */
+       struct usb_function *func;
        /** Configuration descriptor */
        struct usb_configuration_descriptor *config;
        /** Supported languages */
index fa430602089c0e4dcf707e85a8c75e8c6c554859..162400a0f4faab73fb405173aa1410bcde4c8b92 100644 (file)
  * 02110-1301, USA.
  */
 
+#include <stdlib.h>
+#include <string.h>
+#include <ipxe/usb.h>
 #include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_driver.h>
 #include <ipxe/efi/efi_path.h>
 
 /** @file
@@ -56,6 +60,62 @@ size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *path ) {
        return ( ( ( void * ) end ) - ( ( void * ) path ) );
 }
 
+/**
+ * Construct EFI device path for USB function
+ *
+ * @v func             USB function
+ * @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_usb_path ( struct usb_function *func ) {
+       struct usb_device *usb = func->usb;
+       struct efi_device *efidev;
+       EFI_DEVICE_PATH_PROTOCOL *path;
+       EFI_DEVICE_PATH_PROTOCOL *end;
+       USB_DEVICE_PATH *usbpath;
+       unsigned int count;
+       size_t prefix_len;
+       size_t len;
+
+       /* Sanity check */
+       assert ( func->desc.count >= 1 );
+
+       /* Find parent EFI device */
+       efidev = efidev_parent ( &func->dev );
+       if ( ! efidev )
+               return NULL;
+
+       /* Calculate device path length */
+       count = ( usb_depth ( usb ) + 1 );
+       prefix_len = efi_path_len ( efidev->path );
+       len = ( prefix_len + ( count * sizeof ( *usbpath ) ) +
+               sizeof ( *end ) );
+
+       /* Allocate device path */
+       path = zalloc ( len );
+       if ( ! path )
+               return NULL;
+
+       /* Construct device path */
+       memcpy ( path, efidev->path, prefix_len );
+       end = ( ( ( void * ) path ) + len - sizeof ( *end ) );
+       end->Type = END_DEVICE_PATH_TYPE;
+       end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+       end->Length[0] = sizeof ( *end );
+       usbpath = ( ( ( void * ) end ) - sizeof ( *usbpath ) );
+       usbpath->InterfaceNumber = func->interface[0];
+       for ( ; usb ; usbpath--, usb = usb->port->hub->usb ) {
+               usbpath->Header.Type = MESSAGING_DEVICE_PATH;
+               usbpath->Header.SubType = MSG_USB_DP;
+               usbpath->Header.Length[0] = sizeof ( *usbpath );
+               usbpath->ParentPortNumber = ( usb->port->address - 1 );
+       }
+
+       return path;
+}
+
 /**
  * Describe object as an EFI device path
  *
index 7ffeb7ffa5fa6fbb6c371b66f4c3fce2a8cf039e..55b5bc8804996db0dbad984452a953fd3b48f5d1 100644 (file)
@@ -73,10 +73,10 @@ static const char * efi_usb_direction_name ( EFI_USB_DATA_DIRECTION direction ){
 static VOID EFIAPI efi_usb_timer ( EFI_EVENT event __unused,
                                   VOID *context ) {
        struct efi_usb_endpoint *usbep = context;
-       struct usb_bus *bus = usbep->usbintf->usbdev->usb->port->hub->bus;
+       struct usb_function *func = usbep->usbintf->usbdev->func;
 
        /* Poll bus */
-       usb_poll ( bus );
+       usb_poll ( func->usb->port->hub->bus );
 
        /* Refill endpoint */
        if ( usbep->ep.open )
@@ -179,7 +179,7 @@ static int efi_usb_open ( struct efi_usb_interface *usbintf,
        }
 
        /* Allocate and initialise structure */
-       usb_endpoint_init ( &usbep->ep, usbdev->usb, driver );
+       usb_endpoint_init ( &usbep->ep, usbdev->func->usb, driver );
        usb_endpoint_describe ( &usbep->ep, endpoint, attributes, mtu, 0,
                                ( interval << 3 /* microframes */ ) );
 
@@ -354,7 +354,7 @@ static int efi_usb_sync_transfer ( struct efi_usb_interface *usbintf,
        for ( i = 0 ; ( ( timeout == 0 ) || ( i < timeout ) ) ; i++ ) {
 
                /* Poll bus */
-               usb_poll ( usbdev->usb->port->hub->bus );
+               usb_poll ( usbdev->func->usb->port->hub->bus );
 
                /* Check for completion */
                if ( usbep->rc != -EINPROGRESS ) {
@@ -594,7 +594,7 @@ efi_usb_control_transfer ( EFI_USB_IO_PROTOCOL *usbio,
                efi_usb_close_all ( usbintf );
 
        /* Issue control transfer */
-       if ( ( rc = usb_control ( usbdev->usb, request, value, index,
+       if ( ( rc = usb_control ( usbdev->func->usb, request, value, index,
                                  data, len ) ) != 0 ) {
                DBGC ( usbdev, "USBDEV %s control %04x:%04x:%04x:%04x %p+%zx "
                       "failed: %s\n", usbintf->name, request, value, index,
@@ -841,7 +841,7 @@ efi_usb_get_device_descriptor ( EFI_USB_IO_PROTOCOL *usbio,
        DBGC2 ( usbdev, "USBDEV %s get device descriptor\n", usbintf->name );
 
        /* Copy cached device descriptor */
-       memcpy ( efidesc, &usbdev->usb->device, sizeof ( *efidesc ) );
+       memcpy ( efidesc, &usbdev->func->usb->device, sizeof ( *efidesc ) );
 
        return 0;
 }
@@ -972,8 +972,9 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
        saved_tpl = bs->RaiseTPL ( TPL_CALLBACK );
 
        /* Read descriptor header */
-       if ( ( rc = usb_get_descriptor ( usbdev->usb, 0, USB_STRING_DESCRIPTOR,
-                                        index, language, &header,
+       if ( ( rc = usb_get_descriptor ( usbdev->func->usb, 0,
+                                        USB_STRING_DESCRIPTOR, index,
+                                        language, &header,
                                         sizeof ( header ) ) ) != 0 ) {
                DBGC ( usbdev, "USBDEV %s could not get string %d:%d "
                       "descriptor header: %s\n", usbintf->name, language,
@@ -996,9 +997,9 @@ efi_usb_get_string_descriptor ( EFI_USB_IO_PROTOCOL *usbio, UINT16 language,
        }
 
        /* Read whole descriptor */
-       if ( ( rc = usb_get_descriptor ( usbdev->usb, 0, USB_STRING_DESCRIPTOR,
-                                        index, language, buffer,
-                                        len ) ) != 0 ) {
+       if ( ( rc = usb_get_descriptor ( usbdev->func->usb, 0,
+                                        USB_STRING_DESCRIPTOR, index,
+                                        language, buffer, len ) ) != 0 ) {
                DBGC ( usbdev, "USBDEV %s could not get string %d:%d "
                       "descriptor: %s\n", usbintf->name, language,
                       index, strerror ( rc ) );
@@ -1107,25 +1108,13 @@ static EFI_USB_IO_PROTOCOL efi_usb_io_protocol = {
 static int efi_usb_install ( struct efi_usb_device *usbdev,
                             unsigned int interface ) {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
-       struct efi_device *efidev = usbdev->efidev;
+       struct usb_function *func = usbdev->func;
        struct efi_usb_interface *usbintf;
-       struct usb_device *usb;
-       EFI_DEVICE_PATH_PROTOCOL *path_end;
-       USB_DEVICE_PATH *usbpath;
-       unsigned int path_count;
-       size_t path_prefix_len;
-       size_t path_len;
        EFI_STATUS efirc;
        int rc;
 
-       /* Calculate device path length */
-       path_count = ( usb_depth ( usbdev->usb ) + 1 );
-       path_prefix_len = efi_path_len ( efidev->path );
-       path_len = ( path_prefix_len + ( path_count * sizeof ( *usbpath ) ) +
-                    sizeof ( *path_end ) );
-
        /* Allocate and initialise structure */
-       usbintf = zalloc ( sizeof ( *usbintf ) + path_len );
+       usbintf = zalloc ( sizeof ( *usbintf ) );
        if ( ! usbintf ) {
                rc = -ENOMEM;
                goto err_alloc;
@@ -1136,22 +1125,12 @@ static int efi_usb_install ( struct efi_usb_device *usbdev,
        usbintf->interface = interface;
        memcpy ( &usbintf->usbio, &efi_usb_io_protocol,
                 sizeof ( usbintf->usbio ) );
-       usbintf->path = ( ( ( void * ) usbintf ) + sizeof ( *usbintf ) );
 
        /* Construct device path */
-       memcpy ( usbintf->path, efidev->path, path_prefix_len );
-       path_end = ( ( ( void * ) usbintf->path ) + path_len -
-                    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 );
-       usbpath = ( ( ( void * ) path_end ) - sizeof ( *usbpath ) );
-       usbpath->InterfaceNumber = interface;
-       for ( usb = usbdev->usb ; usb ; usbpath--, usb = usb->port->hub->usb ) {
-               usbpath->Header.Type = MESSAGING_DEVICE_PATH;
-               usbpath->Header.SubType = MSG_USB_DP;
-               usbpath->Header.Length[0] = sizeof ( *usbpath );
-               usbpath->ParentPortNumber = ( usb->port->address - 1 );
+       usbintf->path = efi_usb_path ( func );
+       if ( ! usbintf->path ) {
+               rc = -ENODEV;
+               goto err_path;
        }
 
        /* Add to list of interfaces */
@@ -1182,6 +1161,8 @@ static int efi_usb_install ( struct efi_usb_device *usbdev,
        efi_usb_close_all ( usbintf );
        efi_usb_free_all ( usbintf );
        list_del ( &usbintf->list );
+       free ( usbintf->path );
+ err_path:
        free ( usbintf );
  err_alloc:
        return rc;
@@ -1219,6 +1200,9 @@ static void efi_usb_uninstall ( struct efi_usb_interface *usbintf ) {
        /* Remove from list of interfaces */
        list_del ( &usbintf->list );
 
+       /* Free device path */
+       free ( usbintf->path );
+
        /* Free interface */
        free ( usbintf );
 }
@@ -1252,7 +1236,6 @@ static int efi_usb_probe ( struct usb_function *func,
        struct usb_device *usb = func->usb;
        struct efi_usb_device *usbdev;
        struct efi_usb_interface *usbintf;
-       struct efi_device *efidev;
        struct usb_descriptor_header header;
        struct usb_descriptor_header *lang;
        size_t config_len;
@@ -1260,13 +1243,6 @@ static int efi_usb_probe ( struct usb_function *func,
        unsigned int i;
        int rc;
 
-       /* Find parent EFI device */
-       efidev = efidev_parent ( &func->dev );
-       if ( ! efidev ) {
-               rc = -ENOTTY;
-               goto err_no_efidev;
-       }
-
        /* Get configuration length */
        config_len = le16_to_cpu ( config->len );
 
@@ -1288,8 +1264,7 @@ static int efi_usb_probe ( struct usb_function *func,
        }
        usb_func_set_drvdata ( func, usbdev );
        usbdev->name = func->name;
-       usbdev->usb = usb;
-       usbdev->efidev = efidev;
+       usbdev->func = func;
        usbdev->config = ( ( ( void * ) usbdev ) + sizeof ( *usbdev ) );
        memcpy ( usbdev->config, config, config_len );
        lang = ( ( ( void * ) usbdev->config ) + config_len );
@@ -1325,7 +1300,6 @@ static int efi_usb_probe ( struct usb_function *func,
  err_get_languages:
        free ( usbdev );
  err_alloc:
- err_no_efidev:
        return rc;
 }