|
| | 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 304 of file usbio.c.
304 {
309 union {
310 struct usb_setup_packet setup;
317 unsigned int recipient;
325
326
327 if ( endpoint->
cons == endpoint->
prod )
328 return;
329
330
334
335
337 DBGC ( usbio,
"USBIO %s %s non-message transfer\n",
340 goto err_not_message;
341 }
342
343
352 } else {
355 }
356
357
360
362 } else {
363
364 interface = 0;
365 }
366
367
369 goto err_open;
371
372
373
374
375
379 DBGC ( usbio,
"USBIO %s cannot change configuration: %s\n",
381 goto err_moronic_specification;
382 }
383
384
388 DBGC ( usbio,
"USBIO %s %s could not submit control transfer ",
390 DBGC ( usbio,
"via %s: %s (status %04x)\n",
393 goto err_transfer;
394 }
395
396
398
399
401
402 return;
403
404 err_transfer:
405 err_moronic_specification:
407 err_open:
408 err_not_message:
410}
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 824 of file usbio.c.
824 {
832
833
834 endpoint =
zalloc (
sizeof ( *endpoint ) );
835 if ( ! endpoint ) {
837 goto err_alloc;
838 }
842
843
852 } else {
854 goto err_operations;
855 }
856
857
861 goto err_interface;
862 }
864
865
867 goto err_open_interface;
870 DBGC ( usbio,
"USBIO %s %s using ",
873
874
875 if ( (
rc = endpoint->
op->
open ( endpoint ) ) != 0 )
876 goto err_open_endpoint;
877
878
880
881 return 0;
882
884 endpoint->
op->
close ( endpoint );
885 err_open_endpoint:
887 err_open_interface:
888 err_interface:
889 err_operations:
891 err_alloc:
893}
#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 1342 of file usbio.c.
1342 {
1347 union {
1355 unsigned int i;
1358
1359
1362 DBGC ( usbio,
"USB %s could not get device descriptor: "
1364 goto err_get_device_descriptor;
1365 }
1367
1368
1371 DBGC ( usbio,
"USB %s could not get partial configuration "
1374 goto err_get_configuration_descriptor;
1375 }
1377
1378
1382 goto err_alloc;
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392 for ( i = 0 ; i <
count ; i++ ) {
1393
1394
1398 msg.setup.index = 0;
1400
1401
1407 DBGC ( usbio,
"USB %s could not get configuration %d "
1410 goto err_control_transfer;
1411 }
1412
1413
1415 continue;
1416
1417
1419 DBGC ( usbio,
"USB %s configuration descriptor length "
1422 goto err_len;
1423 }
1424
1425 return 0;
1426 }
1427
1428
1429 DBGC ( usbio,
"USB %s could not find current configuration "
1432
1433 err_len:
1434 err_control_transfer:
1436 err_alloc:
1437 err_get_configuration_descriptor:
1438 err_get_device_descriptor:
1440}
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 1571 of file usbio.c.
1571 {
1576
1577
1578 usbio =
zalloc (
sizeof ( *usbio ) );
1579 if ( ! usbio ) {
1581 goto err_alloc;
1582 }
1586
1587
1589 &usbio->
io ) ) != 0 ) {
1590 DBGC ( usbio,
"USBIO %s cannot open USB I/O protocol: %s\n",
1593 goto err_open_usbio;
1594 }
1595
1596
1601
1602
1604 goto err_config;
1605
1606
1608 goto err_path;
1609
1610
1612 goto err_interfaces;
1613
1614
1617 if ( ! usbio->
bus ) {
1619 goto err_alloc_bus;
1620 }
1623
1624
1627
1628
1630 goto err_register;
1631
1632 return 0;
1633
1635 err_register:
1637 err_alloc_bus:
1639 err_interfaces:
1641 err_path:
1643 err_config:
1646 err_open_usbio:
1648 err_alloc:
1650}
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().