|
| | FILE_LICENCE (GPL2_OR_LATER_OR_UBDL) |
| static int | usbio_interface (struct usbio_device *usbio, struct usb_endpoint *ep) |
| | Determine endpoint interface number.
|
| static int | usbio_open (struct usbio_device *usbio, unsigned int interface) |
| | Open USB I/O interface.
|
| static void | usbio_close (struct usbio_device *usbio, unsigned int interface) |
| | Close USB I/O interface.
|
| static int | usbio_control_open (struct usbio_endpoint *endpoint __unused) |
| | Open control endpoint.
|
| static void | usbio_control_close (struct usbio_endpoint *endpoint __unused) |
| | Close control endpoint.
|
| static void | usbio_control_poll (struct usbio_endpoint *endpoint) |
| | Poll control endpoint.
|
| static int | usbio_bulk_in_open (struct usbio_endpoint *endpoint __unused) |
| | Open bulk IN endpoint.
|
| static void | usbio_bulk_in_close (struct usbio_endpoint *endpoint __unused) |
| | Close bulk IN endpoint.
|
| static void | usbio_bulk_in_poll (struct usbio_endpoint *endpoint) |
| | Poll bulk IN endpoint.
|
| static int | usbio_bulk_out_open (struct usbio_endpoint *endpoint __unused) |
| | Open bulk OUT endpoint.
|
| static void | usbio_bulk_out_close (struct usbio_endpoint *endpoint __unused) |
| | Close bulk OUT endpoint.
|
| static void | usbio_bulk_out_poll (struct usbio_endpoint *endpoint) |
| | Poll bulk OUT endpoint.
|
| static EFI_STATUS EFIAPI | usbio_interrupt_callback (VOID *data, UINTN len, VOID *context, UINT32 status) |
| | Interrupt endpoint callback.
|
| static int | usbio_interrupt_open (struct usbio_endpoint *endpoint) |
| | Open interrupt endpoint.
|
| static void | usbio_interrupt_close (struct usbio_endpoint *endpoint) |
| | Close interrupt endpoint.
|
| static void | usbio_interrupt_poll (struct usbio_endpoint *endpoint) |
| | Poll interrupt endpoint.
|
| static int | usbio_endpoint_open (struct usb_endpoint *ep) |
| | Open endpoint.
|
| static void | usbio_endpoint_close (struct usb_endpoint *ep) |
| | Close endpoint.
|
| static int | usbio_endpoint_reset (struct usb_endpoint *ep __unused) |
| | Reset endpoint.
|
| static int | usbio_endpoint_mtu (struct usb_endpoint *ep __unused) |
| | Update MTU.
|
| static int | usbio_endpoint_enqueue (struct usb_endpoint *ep, struct io_buffer *iobuf, unsigned int flags) |
| | Enqueue transfer.
|
| static int | usbio_endpoint_message (struct usb_endpoint *ep, struct io_buffer *iobuf) |
| | Enqueue message transfer.
|
| static int | usbio_endpoint_stream (struct usb_endpoint *ep, struct io_buffer *iobuf, int zlp) |
| | Enqueue stream transfer.
|
| static void | usbio_endpoint_poll (struct usbio_endpoint *endpoint) |
| | Poll for completions.
|
| static int | usbio_device_open (struct usb_device *usb) |
| | Open device.
|
| static void | usbio_device_close (struct usb_device *usb __unused) |
| | Close device.
|
| static int | usbio_device_address (struct usb_device *usb __unused) |
| | Assign device address.
|
| static int | usbio_hub_open (struct usb_hub *hub) |
| | Open hub.
|
| static void | usbio_hub_close (struct usb_hub *hub __unused) |
| | Close hub.
|
| static int | usbio_root_open (struct usb_hub *hub __unused) |
| | Open root hub.
|
| static void | usbio_root_close (struct usb_hub *hub __unused) |
| | Close root hub.
|
| static int | usbio_root_enable (struct usb_hub *hub __unused, struct usb_port *port __unused) |
| | Enable port.
|
| static int | usbio_root_disable (struct usb_hub *hub __unused, struct usb_port *port __unused) |
| | Disable port.
|
| static int | usbio_root_speed (struct usb_hub *hub __unused, struct usb_port *port) |
| | Update root hub port speed.
|
| static int | usbio_root_clear_tt (struct usb_hub *hub __unused, struct usb_port *port __unused, struct usb_endpoint *ep __unused) |
| | Clear transaction translator buffer.
|
| static int | usbio_bus_open (struct usb_bus *bus __unused) |
| | Open USB bus.
|
| static void | usbio_bus_close (struct usb_bus *bus __unused) |
| | Close USB bus.
|
| static void | usbio_bus_poll (struct usb_bus *bus) |
| | Poll USB bus.
|
| static int | usbio_supported (EFI_HANDLE handle) |
| | Check to see if driver supports a device.
|
| static int | usbio_config (struct usbio_device *usbio) |
| | Fetch configuration descriptor.
|
| static int | usbio_path (struct usbio_device *usbio) |
| | Construct device path for opening other interfaces.
|
| static int | usbio_interfaces (struct usbio_device *usbio) |
| | Construct interface list.
|
| static int | usbio_exclude (EFI_HANDLE device) |
| | Exclude existing drivers.
|
| static int | usbio_start (struct efi_device *efidev) |
| | Attach driver to device.
|
| static void | usbio_stop (struct efi_device *efidev) |
| | Detach driver from device.
|
| struct efi_driver usbio_driver | __efi_driver (EFI_DRIVER_HARDWARE) |
| | EFI USB I/O driver.
|
EFI_USB_IO_PROTOCOL pseudo Host Controller Interface driver.
The EFI_USB_IO_PROTOCOL is an almost unbelievably poorly designed abstraction of a USB device. It would be just about forgivable for an API to support only synchronous operation for bulk OUT endpoints. It is imbecilic to support only synchronous operation for bulk IN endpoints. This apparently intern-designed API throttles a typical NIC down to 1.5% of its maximum throughput. That isn't a typo. It really is that slow.
We can't even work around this stupidity by talking to the host controller abstraction directly, because an identical limitation exists in the EFI_USB2_HC_PROTOCOL.
Unless you derive therapeutic value from watching download progress indicators lethargically creep through every single integer from 0 to 100, you should use iPXE's native USB host controller drivers instead. (Or just upgrade from UEFI to "legacy" BIOS, which will produce a similar speed increase.)
For added excitement, the EFI_USB_IO_PROTOCOL makes the (demonstrably incorrect) assumption that a USB driver needs to attach to exactly one interface within a USB device, and provides a helper method to retrieve "the" interface descriptor. Since pretty much every USB network device requires binding to a pair of control+data interfaces, this aspect of EFI_USB_IO_PROTOCOL is of no use to us.
We have our own existing code for reading USB descriptors, so we don't actually care that the UsbGetInterfaceDescriptor() method provided by EFI_USB_IO_PROTOCOL is useless for network devices. We can read the descriptors ourselves (via UsbControlTransfer()) and get all of the information we need this way. We can even work around the fact that EFI_USB_IO_PROTOCOL provides separate handles for each of the two interfaces comprising our network device.
However, if we discover that we need to select an alternative device configuration (e.g. for devices exposing both RNDIS and ECM), then all hell breaks loose. EFI_USB_IO_PROTOCOL starts to panic because its cached interface and endpoint descriptors will no longer be valid. As mentioned above, the cached descriptors are useless for network devices anyway so we really don't care about this, but EFI_USB_IO_PROTOCOL certainly cares. It prints out a manic warning message containing no fewer than six exclamation marks and then literally commits seppuku in the middle of the UsbControlTransfer() method by attempting to uninstall itself. Quite how the caller is supposed to react when asked to stop using the EFI_USB_IO_PROTOCOL instance while in the middle of an uninterruptible call to said instance is left as an exercise for the interested reader.
There is no sensible way to work around this, so we just preemptively fail if asked to change the device configuration, on the basis that reporting a sarcastic error message is often preferable to jumping through a NULL pointer and crashing the system.
Definition in file usbio.c.
Poll control endpoint.
- Parameters
-
Definition at line 298 of file usbio.c.
298 {
303 union {
304 struct usb_setup_packet setup;
311 unsigned int recipient;
319
320
321 if ( endpoint->
cons == endpoint->
prod )
322 return;
323
324
328
329
331 DBGC ( usbio,
"USBIO %s %s non-message transfer\n",
334 goto err_not_message;
335 }
336
337
346 } else {
349 }
350
351
354
356 } else {
357
358 interface = 0;
359 }
360
361
363 goto err_open;
365
366
367
368
369
373 DBGC ( usbio,
"USBIO %s cannot change configuration: %s\n",
375 goto err_moronic_specification;
376 }
377
378
382 DBGC ( usbio,
"USBIO %s %s could not submit control transfer ",
384 DBGC ( usbio,
"via %s: %s (status %04x)\n",
387 goto err_transfer;
388 }
389
390
392
393
395
396 return;
397
398 err_transfer:
399 err_moronic_specification:
401 err_open:
402 err_not_message:
404}
unsigned int UINT32
4-byte unsigned value.
#define NULL
NULL pointer (VOID *).
EFI_USB_DATA_DIRECTION
USB data transfer direction.
struct _EFI_USB_IO_PROTOCOL EFI_USB_IO_PROTOCOL
USB_DEVICE_REQUEST EFI_USB_DEVICE_REQUEST
uint8_t direction
Direction.
uint8_t data[48]
Additional event data.
#define ENOTSUP
Operation not supported.
u8 request[0]
List of IEs requested.
#define le16_to_cpu(value)
#define USB_DIR_IN
Data transfer is from device to host.
static void usb_complete(struct usb_endpoint *ep, struct io_buffer *iobuf)
Complete transfer (without error).
#define USB_RECIP_MASK
Request recipient mask.
#define USB_SET_CONFIGURATION
Set configuration.
#define USB_RECIP_INTERFACE
Request recipient is an interface.
#define iob_push(iobuf, len)
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
#define iob_pull(iobuf, len)
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
EFI_USB_IO_CONTROL_TRANSFER UsbControlTransfer
void * data
Start of data.
A USB I/O protocol device.
unsigned int cons
Consumer counter.
struct usb_endpoint * ep
USB endpoint.
struct io_buffer * iobuf[USBIO_RING_COUNT]
I/O buffers.
struct usbio_device * usbio
USB I/O device.
unsigned int prod
Producer counter.
uint8_t flags[USBIO_RING_COUNT]
Flags.
void usb_complete_err(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete transfer (possibly with error).
static void usbio_close(struct usbio_device *usbio, unsigned int interface)
Close USB I/O interface.
static int usbio_open(struct usbio_device *usbio, unsigned int interface)
Open USB I/O interface.
#define ENOTSUP_MORONIC_SPECIFICATION
@ USBIO_MESSAGE
This is a message transfer.
#define USBIO_RING_COUNT
USB I/O ring buffer size.
References usb_configuration_descriptor::config, usbio_device::config, usbio_endpoint::cons, data, io_buffer::data, DBGC, direction, EEFI, EFI_HANDLE, efi_handle_name(), EfiUsbDataIn, EfiUsbDataOut, EfiUsbNoData, ENOTSUP, ENOTSUP_MORONIC_SPECIFICATION, usbio_endpoint::ep, flags, usbio_endpoint::flags, handle, usbio_device::handle, usbio_interface::handle, index, usbio_device::interface, usbio_interface::io, iob_len(), iob_pull, iob_push, usbio_endpoint::iobuf, le16_to_cpu, len, msg(), NULL, usbio_endpoint::prod, rc, request, status, strerror(), usb_complete(), usb_complete_err(), USB_DIR_IN, usb_endpoint_name(), USB_RECIP_INTERFACE, USB_RECIP_MASK, USB_SET_CONFIGURATION, _EFI_USB_IO_PROTOCOL::UsbControlTransfer, usbio_endpoint::usbio, usbio_close(), USBIO_MESSAGE, usbio_open(), and USBIO_RING_COUNT.
Open endpoint.
- Parameters
-
- Return values
-
Definition at line 818 of file usbio.c.
818 {
826
827
828 endpoint =
zalloc (
sizeof ( *endpoint ) );
829 if ( ! endpoint ) {
831 goto err_alloc;
832 }
836
837
846 } else {
848 goto err_operations;
849 }
850
851
855 goto err_interface;
856 }
858
859
861 goto err_open_interface;
864 DBGC ( usbio,
"USBIO %s %s using ",
867
868
869 if ( (
rc = endpoint->
op->
open ( endpoint ) ) != 0 )
870 goto err_open_endpoint;
871
872
874
875 return 0;
876
878 endpoint->
op->
close ( endpoint );
879 err_open_endpoint:
881 err_open_interface:
882 err_interface:
883 err_operations:
885 err_alloc:
887}
#define USB_ENDPOINT_ATTR_BULK
Bulk endpoint transfer type.
static void usb_endpoint_set_hostdata(struct usb_endpoint *ep, void *priv)
Set USB endpoint host controller private data.
#define USB_ENDPOINT_ATTR_INTERRUPT
Interrupt endpoint transfer type.
static void * usb_bus_get_hostdata(struct usb_bus *bus)
Get USB bus host controller private data.
#define USB_ENDPOINT_ATTR_TYPE_MASK
Endpoint attribute transfer type mask.
#define USB_ENDPOINT_ATTR_CONTROL
Control endpoint transfer type.
uint8_t attr
Type and attributes.
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
#define list_del(list)
Delete an entry from a list.
struct usb_port * port
USB port.
unsigned int attributes
Attributes.
struct usb_bus * bus
USB bus.
struct usb_hub * hub
USB hub.
struct list_head endpoints
List of endpoints.
EFI_HANDLE handle
EFI handle.
struct usbio_operations * op
USB I/O endpoint operations.
unsigned int interface
Containing interface number.
struct list_head list
List of endpoints.
void(* close)(struct usbio_endpoint *endpoint)
Close endpoint.
int(* open)(struct usbio_endpoint *endpoint)
Open endpoint.
static struct usbio_operations usbio_control_operations
Control endpoint operations.
static struct usbio_operations usbio_interrupt_operations
Interrupt endpoint operations.
static struct usbio_operations usbio_bulk_in_operations
Bulk endpoint operations.
static struct usbio_operations usbio_bulk_out_operations
Bulk endpoint operations.
References usb_endpoint::address, attr, usb_endpoint::attributes, bus, usb_hub::bus, usbio_operations::close, DBGC, EFI_HANDLE, efi_handle_name(), usbio_device::endpoints, ENOMEM, ENOTSUP, usbio_endpoint::ep, free, handle, usbio_device::handle, usbio_endpoint::handle, usbio_interface::handle, usb_port::hub, usbio_device::interface, usbio_endpoint::interface, usbio_endpoint::io, usbio_interface::io, usbio_endpoint::list, list_add_tail, list_del, usbio_endpoint::op, usbio_operations::open, usb_device::port, rc, usb_endpoint::usb, usb_bus_get_hostdata(), USB_DIR_IN, USB_ENDPOINT_ATTR_BULK, USB_ENDPOINT_ATTR_CONTROL, USB_ENDPOINT_ATTR_INTERRUPT, USB_ENDPOINT_ATTR_TYPE_MASK, usb_endpoint_name(), usb_endpoint_set_hostdata(), usbio_endpoint::usbio, usbio_bulk_in_operations, usbio_bulk_out_operations, usbio_close(), usbio_control_operations, usbio_interrupt_operations, usbio_open(), and zalloc().
Fetch configuration descriptor.
- Parameters
-
- Return values
-
Definition at line 1336 of file usbio.c.
1336 {
1341 union {
1349 unsigned int i;
1352
1353
1356 DBGC ( usbio,
"USB %s could not get device descriptor: "
1358 goto err_get_device_descriptor;
1359 }
1361
1362
1365 DBGC ( usbio,
"USB %s could not get partial configuration "
1368 goto err_get_configuration_descriptor;
1369 }
1371
1372
1376 goto err_alloc;
1377 }
1378
1379
1380
1381
1382
1383
1384
1385
1386 for ( i = 0 ; i <
count ; i++ ) {
1387
1388
1392 msg.setup.index = 0;
1394
1395
1401 DBGC ( usbio,
"USB %s could not get configuration %d "
1404 goto err_control_transfer;
1405 }
1406
1407
1409 continue;
1410
1411
1413 DBGC ( usbio,
"USB %s configuration descriptor length "
1416 goto err_len;
1417 }
1418
1419 return 0;
1420 }
1421
1422
1423 DBGC ( usbio,
"USB %s could not find current configuration "
1426
1427 err_len:
1428 err_control_transfer:
1430 err_alloc:
1431 err_get_configuration_descriptor:
1432 err_get_device_descriptor:
1434}
USB_CONFIG_DESCRIPTOR EFI_USB_CONFIG_DESCRIPTOR
pseudo_bit_t value[0x00020]
static unsigned int count
Number of entries.
#define EINVAL
Invalid argument.
#define cpu_to_le16(value)
#define USB_CONFIGURATION_DESCRIPTOR
A USB configuration descriptor.
#define USB_GET_DESCRIPTOR
Get descriptor.
void * malloc(size_t size)
Allocate memory.
EFI_USB_IO_GET_CONFIG_DESCRIPTOR UsbGetConfigDescriptor
uint16_t len
Total length.
EFI_USB_IO_PROTOCOL * io
USB I/O protocol.
References usb_configuration_descriptor::config, usbio_device::config, USB_CONFIG_DESCRIPTOR::ConfigurationValue, count, cpu_to_le16, DBGC, EEFI, EFI_HANDLE, efi_handle_name(), EfiUsbDataIn, EINVAL, ENOENT, ENOMEM, free, handle, usbio_device::handle, usbio_device::io, le16_to_cpu, len, usb_configuration_descriptor::len, malloc(), msg(), rc, status, strerror(), USB_CONFIG_DESCRIPTOR::TotalLength, USB_CONFIGURATION_DESCRIPTOR, USB_GET_DESCRIPTOR, _EFI_USB_IO_PROTOCOL::UsbControlTransfer, _EFI_USB_IO_PROTOCOL::UsbGetConfigDescriptor, _EFI_USB_IO_PROTOCOL::UsbGetDeviceDescriptor, and value.
Referenced by usbio_start().
Attach driver to device.
- Parameters
-
- Return values
-
Definition at line 1565 of file usbio.c.
1565 {
1570
1571
1572 usbio =
zalloc (
sizeof ( *usbio ) );
1573 if ( ! usbio ) {
1575 goto err_alloc;
1576 }
1580
1581
1583 &usbio->
io ) ) != 0 ) {
1584 DBGC ( usbio,
"USBIO %s cannot open USB I/O protocol: %s\n",
1587 goto err_open_usbio;
1588 }
1589
1590
1595
1596
1598 goto err_config;
1599
1600
1602 goto err_path;
1603
1604
1606 goto err_interfaces;
1607
1608
1611 if ( ! usbio->
bus ) {
1613 goto err_alloc_bus;
1614 }
1617
1618
1621
1622
1624 goto err_register;
1625
1626 return 0;
1627
1629 err_register:
1631 err_alloc_bus:
1633 err_interfaces:
1635 err_path:
1637 err_config:
1640 err_open_usbio:
1642 err_alloc:
1644}
static void efidev_set_drvdata(struct efi_device *efidev, void *priv)
Set EFI driver-private data.
void efi_device_info(EFI_HANDLE device, const char *prefix, struct device *dev)
Get underlying device information.
static struct usb_port * usb_port(struct usb_hub *hub, unsigned int address)
Get USB port.
static void usb_hub_set_drvdata(struct usb_hub *hub, void *priv)
Set USB hub driver private data.
static void usb_bus_set_hostdata(struct usb_bus *bus, void *priv)
Set USB bus host controller private data.
#define INIT_LIST_HEAD(list)
Initialise a list head.
#define list_add(new, head)
Add a new entry to the head of a list.
struct device * parent
Bus device.
struct list_head children
Devices attached to this device.
struct list_head siblings
Devices on the same bus.
EFI_HANDLE device
EFI device handle.
struct device dev
Generic device.
struct usb_hub * hub
Root hub.
struct usb_bus * bus
USB bus.
struct device dev
Generic device.
USB I/O endpoint operations.
void unregister_usb_bus(struct usb_bus *bus)
Unregister USB bus.
int register_usb_bus(struct usb_bus *bus)
Register USB bus.
struct usb_bus * alloc_usb_bus(struct device *dev, unsigned int ports, size_t mtu, struct usb_host_operations *op)
Allocate USB bus.
void free_usb_bus(struct usb_bus *bus)
Free USB bus.
static int usbio_path(struct usbio_device *usbio)
Construct device path for opening other interfaces.
static int usbio_config(struct usbio_device *usbio)
Fetch configuration descriptor.
static int usbio_interfaces(struct usbio_device *usbio)
Construct interface list.
#define USBIO_MTU
USB I/O maximum transfer size.
References alloc_usb_bus(), usbio_device::bus, device::children, usbio_device::config, DBGC, DBGC_EFI_OPENERS, efi_device::dev, usbio_device::dev, efi_device::device, efi_close_by_driver(), efi_device_info(), EFI_HANDLE, efi_handle_name(), efi_open_by_driver, efi_usb_io_protocol_guid, efidev_set_drvdata(), usbio_device::endpoints, ENOMEM, free, free_usb_bus(), handle, usbio_device::handle, usb_bus::hub, INIT_LIST_HEAD, usbio_device::interface, usbio_device::io, list_add, list_del, device::parent, usbio_device::path, port, rc, register_usb_bus(), device::siblings, strerror(), unregister_usb_bus(), usb_bus_set_hostdata(), usb_hub_set_drvdata(), usb_port(), USB_PROTO_2_0, usbio_config(), usbio_interfaces(), USBIO_MTU, usbio_path(), and zalloc().
Referenced by __efi_driver().