summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_path.c
diff options
context:
space:
mode:
authorMichael Brown2020-10-16 16:07:14 +0200
committerMichael Brown2020-10-16 16:38:18 +0200
commit87e39a9c9345e177c46f74dc1e3d6d94136315be (patch)
tree79fc7328f739355631237fe0647d076ce7602135 /src/interface/efi/efi_path.c
parent[efi] Define an interface operation to describe using an EFI device path (diff)
downloadipxe-87e39a9c9345e177c46f74dc1e3d6d94136315be.tar.gz
ipxe-87e39a9c9345e177c46f74dc1e3d6d94136315be.tar.xz
ipxe-87e39a9c9345e177c46f74dc1e3d6d94136315be.zip
[efi] Split efi_usb_path() out to a separate function
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>
Diffstat (limited to 'src/interface/efi/efi_path.c')
-rw-r--r--src/interface/efi/efi_path.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/interface/efi/efi_path.c b/src/interface/efi/efi_path.c
index fa430602..162400a0 100644
--- a/src/interface/efi/efi_path.c
+++ b/src/interface/efi/efi_path.c
@@ -17,7 +17,11 @@
* 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
@@ -57,6 +61,62 @@ size_t efi_path_len ( EFI_DEVICE_PATH_PROTOCOL *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
*
* @v intf Interface