diff options
author | Michael Brown | 2020-10-16 16:07:14 +0200 |
---|---|---|
committer | Michael Brown | 2020-10-16 16:38:18 +0200 |
commit | 87e39a9c9345e177c46f74dc1e3d6d94136315be (patch) | |
tree | 79fc7328f739355631237fe0647d076ce7602135 /src/interface/efi/efi_path.c | |
parent | [efi] Define an interface operation to describe using an EFI device path (diff) | |
download | ipxe-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.c | 60 |
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 |