mirror of https://github.com/ipxe/ipxe.git
[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>pull/171/head
parent
2091288eaa
commit
87e39a9c93
|
@ -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 ) \
|
||||
|
|
|
@ -17,10 +17,8 @@
|
|||
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 */
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue