mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/5] Add support for USB-EFI devices in EFI Playload
@ 2026-08-12 16:36 Fabian Pflug
  2026-08-12 16:36 ` [PATCH 1/5] efi: usb: add header for usb-efi Fabian Pflug
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

When running as EFI payload, barebox does not have control over the USB
bus, but instead the BIOS will have enumerated and set up devices.

The UEFI will also expose an API to access the devices, with one handle
per USB interface.
This driver will create an USB-Host per device and initialize the device
and pass it onto barebox for driver initialization, allowing all
usb-devices to be used.

This might lead to problems where USB-Storage is handled as an USB
device as well as UEFI Block IO Storage, therefore it is not added to
efi_defconfig by default.

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
Fabian Pflug (5):
      efi: usb: add header for usb-efi
      usb: core: make usb_set_maxpacket_ep public
      drivers: usb: host: efi: add efi io driver
      efi: guid: add guid for usb host controller 2
      test: x86: add test for uefi usb io

 drivers/usb/core/usb.c             |  12 +-
 drivers/usb/core/usb.h             |   2 +
 drivers/usb/host/Kconfig           |  11 ++
 drivers/usb/host/Makefile          |   1 +
 drivers/usb/host/efi-io-protocol.c | 325 +++++++++++++++++++++++++++++++++++++
 efi/guid.c                         |   2 +
 include/efi/guid.h                 |   4 +
 include/efi/protocol/usb.h         |  66 ++++++++
 test/x86/pc@efi_defconfig.yaml     |   9 +-
 9 files changed, 421 insertions(+), 11 deletions(-)
---
base-commit: 87f49b49fdd06c0de492bd2c1cd6b8c93e393029
change-id: 20260812-v2026-06-0-topic-efi_usb-2eb7641b6b60

Best regards,
-- 
Fabian Pflug <f.pflug@pengutronix.de>




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] efi: usb: add header for usb-efi
  2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
@ 2026-08-12 16:36 ` Fabian Pflug
  2026-08-12 16:36 ` [PATCH 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

Convert the spec in [1] to a header, that is useable for barebox.
The async headers are not defined, since it is currently not planned to
support async in addition to sync.

[1] https://uefi.org/specs/UEFI/2.11/17_Protocols_USB_Support.html

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
 include/efi/protocol/usb.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/include/efi/protocol/usb.h b/include/efi/protocol/usb.h
new file mode 100644
index 0000000000..7d30fbbcaa
--- /dev/null
+++ b/include/efi/protocol/usb.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __EFI_PROTOCOL_USB_H_
+#define __EFI_PROTOCOL_USB_H_
+
+#include <efi/types.h>
+#include <linux/usb/usb.h>
+
+enum efi_usb_data_direction {
+	EFI_USB_DATA_IN,
+	EFI_USB_DATA_OUT,
+	EFI_USB_NO_DATA
+};
+
+//
+// Error code for USB Transfer Results
+//
+#define EFI_USB_NOERROR 0x0000
+#define EFI_USB_ERR_NOTEXECUTE 0x0001
+#define EFI_USB_ERR_STALL 0x0002
+#define EFI_USB_ERR_BUFFER 0x0004
+#define EFI_USB_ERR_BABBLE 0x0008
+#define EFI_USB_ERR_NAK 0x0010
+#define EFI_USB_ERR_CRC 0x0020
+#define EFI_USB_ERR_TIMEOUT 0x0040
+#define EFI_USB_ERR_BITSTUFF 0x0080
+#define EFI_USB_ERR_SYSTEM 0x0100
+
+struct efi_usb_io_protocol {
+	efi_status_t(EFIAPI *control_transfer)(
+		struct efi_usb_io_protocol *this, struct devrequest *request,
+		enum efi_usb_data_direction direction, u32 timeout, void *data,
+		efi_uintn_t length, u32 *status);
+	efi_status_t(EFIAPI *bulk_transfer)(struct efi_usb_io_protocol *this,
+					    u8 device_endpoint, void *data,
+					    efi_uintn_t *length,
+					    efi_uintn_t timeout, u32 *status);
+	void *usb_io_async_interrupt_transfer;
+	efi_status_t(EFIAPI *sync_interrupt_transfer)(
+		struct efi_usb_io_protocol *this, u8 device_endpoint,
+		void *data, efi_uintn_t *length, efi_uintn_t timeout,
+		u32 *status);
+	void *efi_usb_io_isochronous_transfer;
+	void *efi_usb_io_async_isochronous_transfer;
+	efi_status_t(EFIAPI *get_device_descriptor)(
+		struct efi_usb_io_protocol *this,
+		struct usb_device_descriptor *desc);
+	efi_status_t(EFIAPI *get_config_descriptor)(
+		struct efi_usb_io_protocol *this,
+		struct usb_config_descriptor *desc);
+	efi_status_t(EFIAPI *get_interface_descriptor)(
+		struct efi_usb_io_protocol *this,
+		struct usb_interface_descriptor *desc);
+	efi_status_t(EFIAPI *get_endpoint_descriptor)(
+		struct efi_usb_io_protocol *this, u8 index,
+		struct usb_endpoint_descriptor *desc);
+	efi_status_t(EFIAPI *get_string_descriptor)(
+		struct efi_usb_io_protocol *this, u16 lang_id, u8 string_id,
+		char **desc);
+	efi_status_t(EFIAPI *get_supported_languages)(
+		struct efi_usb_io_protocol *this, u16 **lang_id_table,
+		u16 *table_size);
+	efi_status_t(EFIAPI *port_reset)(struct efi_usb_io_protocol *this);
+};
+
+#endif

-- 
2.47.3




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/5] usb: core: make usb_set_maxpacket_ep public
  2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
  2026-08-12 16:36 ` [PATCH 1/5] efi: usb: add header for usb-efi Fabian Pflug
@ 2026-08-12 16:36 ` Fabian Pflug
  2026-08-12 16:36 ` [PATCH 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

The function will be used by the efi usb driver to set the maxpackets
per endpoint.

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
 drivers/usb/core/usb.c | 12 ++----------
 drivers/usb/core/usb.h |  2 ++
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index ae87137447..ce10b71f40 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -127,16 +127,8 @@ static int usb_set_configuration(struct usb_device *dev, int configuration)
 		return res;
 }
 
-/* The routine usb_set_maxpacket_ep() is extracted from the loop of routine
- * usb_set_maxpacket(), because the optimizer of GCC 4.x chokes on this routine
- * when it is inlined in 1 single routine. What happens is that the register r3
- * is used as loop-count 'i', but gets overwritten later on.
- * This is clearly a compiler bug, but it is easier to workaround it here than
- * to update the compiler (Occurs with at least several GCC 4.{1,2},x
- * CodeSourcery compilers like e.g. 2007q3, 2008q1, 2008q3 lite editions on ARM)
- */
-static void  noinline
-usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_descriptor *ep)
+void usb_set_maxpacket_ep(struct usb_device *dev,
+			  struct usb_endpoint_descriptor *ep)
 {
 	int b;
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 0d4f80c21d..b503e5b4a8 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -6,5 +6,7 @@ struct usb_device *usb_alloc_new_device(void);
 void usb_free_device(struct usb_device *dev);
 int usb_new_device(struct usb_device *dev);
 void usb_remove_device(struct usb_device *dev);
+void usb_set_maxpacket_ep(struct usb_device *dev,
+			  struct usb_endpoint_descriptor *ep);
 
 #endif /* __CORE_USB_H */

-- 
2.47.3




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/5] drivers: usb: host: efi: add efi io driver
  2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
  2026-08-12 16:36 ` [PATCH 1/5] efi: usb: add header for usb-efi Fabian Pflug
  2026-08-12 16:36 ` [PATCH 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
@ 2026-08-12 16:36 ` Fabian Pflug
  2026-08-12 16:36 ` [PATCH 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
  2026-08-12 16:36 ` [PATCH 5/5] test: x86: add test for uefi usb io Fabian Pflug
  4 siblings, 0 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

The driver is based on [1] with one "host" controller per device.
The host controller will hopefully not have any sub-devices and only
have the one root device, which functions as the only device needed and
registered for.

[1] https://uefi.org/specs/UEFI/2.11/17_Protocols_USB_Support.html#usb-driver-model

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
 drivers/usb/host/Kconfig           |  11 ++
 drivers/usb/host/Makefile          |   1 +
 drivers/usb/host/efi-io-protocol.c | 316 +++++++++++++++++++++++++++++++++++++
 efi/guid.c                         |   1 +
 include/efi/guid.h                 |   1 +
 5 files changed, 330 insertions(+)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 58f276cdb4..66e320d163 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -22,6 +22,17 @@ config USB_EHCI_ZYNQ
 	help
 	  Enable support for Zynq on-chip EHCI USB controller
 
+config USB_EFI_IO_PROTOCOL
+	bool "EFI USB I/O Protocol"
+	depends on EFI_PAYLOAD
+	depends on USB_HOST
+	help
+	  Enable support for usb devices, initialized by the UEFI BIOS.
+	  Use this with caution, as devices may afterwards have multiple drivers.
+	  For example can a USB-Stick be treated as an IO Blockdevice by UEFI and
+	  have a driver for it, but can also be initiated as a USB-Storage device,
+	  which could lead to errors in handling the USB-Device.
+
 config USB_OHCI
 	bool "OHCI driver"
 	depends on !MMU && HAS_DMA
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cbddfbe923..4f77680fc7 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_USB_EHCI_ZYNQ)	+= ehci-zynq.o
 obj-$(CONFIG_USB_OHCI)		+= ohci-hcd.o
 obj-$(CONFIG_USB_OHCI_AT91)	+= ohci-at91.o
 obj-$(CONFIG_USB_XHCI)		+= xhci.o xhci-mem.o xhci-ring.o
+obj-$(CONFIG_USB_EFI_IO_PROTOCOL)	+= efi-io-protocol.o
diff --git a/drivers/usb/host/efi-io-protocol.c b/drivers/usb/host/efi-io-protocol.c
new file mode 100644
index 0000000000..bd35628f59
--- /dev/null
+++ b/drivers/usb/host/efi-io-protocol.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <efi/payload.h>
+#include <efi/payload/init.h>
+#include <efi/payload/driver.h>
+#include <efi/protocol/usb.h>
+#include <efi/error.h>
+
+#include "../core/usb.h"
+
+struct efi_usb_io_priv {
+	struct efi_usb_io_protocol *protocol;
+	struct device *dev;
+	struct usb_host host;
+};
+
+#define usb_dev_to_efi_priv(ptr) \
+	container_of(ptr->host, struct efi_usb_io_priv, host)
+
+static int efi_usb_error_check(efi_status_t efiret, int status)
+{
+	if (efiret == EFI_DEVICE_ERROR) {
+		if (status & EFI_USB_ERR_TIMEOUT)
+			return -ETIMEDOUT;
+		if (status & EFI_USB_ERR_STALL)
+			return -ETIMEDOUT;
+		if (status & EFI_USB_ERR_NAK)
+			return -EPROTO;
+		if (status & EFI_USB_ERR_BUFFER)
+			return -EINVAL;
+		if (status & EFI_USB_ERR_NOTEXECUTE)
+			return -EIO;
+		if (status & EFI_USB_ERR_BABBLE)
+			return -EIO;
+		if (status & EFI_USB_ERR_CRC)
+			return -EIO;
+		if (status & EFI_USB_ERR_BITSTUFF)
+			return -EIO;
+		if (status & EFI_USB_ERR_SYSTEM)
+			return -EIO;
+	}
+
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	return 0;
+}
+
+static int efi_usb_control_msg(struct usb_device *dev, unsigned long pipe,
+			       void *buffer, int length,
+			       struct devrequest *setup, int timeout)
+{
+	struct efi_usb_io_priv *priv = usb_dev_to_efi_priv(dev);
+	enum efi_usb_data_direction direction;
+	efi_status_t efiret;
+	efi_uintn_t efi_timeout = timeout;
+	u32 status;
+
+	if (usb_pipein(pipe))
+		direction = EFI_USB_DATA_IN;
+	else
+		direction = EFI_USB_DATA_OUT;
+	if (length == 0)
+		direction = EFI_USB_NO_DATA;
+
+	efiret = priv->protocol->control_transfer(priv->protocol, setup,
+						  direction, efi_timeout,
+						  buffer, length, &status);
+
+	dev->status = status; // dev-status is a long, status is u32
+	dev->act_len = length;
+
+	return efi_usb_error_check(efiret, status);
+}
+
+static int efi_usb_bulk_msg(struct usb_device *dev, unsigned long pipe,
+			    void *buffer, int length, int timeout)
+{
+	struct efi_usb_io_priv *priv = usb_dev_to_efi_priv(dev);
+	efi_uintn_t efi_length = length;
+	efi_status_t efiret;
+	u32 status;
+
+	u8 epnum = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
+
+	efiret = priv->protocol->bulk_transfer(priv->protocol, epnum, buffer,
+					       &efi_length, timeout, &status);
+
+	dev->status = status;
+	dev->act_len = efi_length;
+
+	return efi_usb_error_check(efiret, status);
+}
+
+static int efi_usb_int_msg(struct usb_device *dev, unsigned long pipe,
+			   void *buffer, int length,
+			   int __always_unused interval)
+{
+	struct efi_usb_io_priv *priv = usb_dev_to_efi_priv(dev);
+	efi_status_t efiret;
+	u32 status;
+	efi_uintn_t efi_length = length;
+
+	u8 epnum = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
+
+	efiret = priv->protocol->sync_interrupt_transfer(
+		priv->protocol, epnum, buffer, &efi_length, 100, &status);
+
+	dev->status = status;
+	dev->act_len = efi_length;
+
+	return efi_usb_error_check(efiret, status);
+}
+
+static int efi_get_usb_string(struct efi_usb_io_protocol *protocol, u16 lang_id,
+			      int index, char *buf, size_t size)
+{
+	char *efi_name;
+	efi_status_t efiret;
+	unsigned int u, idx;
+
+	memset(buf, 0, size);
+
+	if (!index)
+		return 0;
+
+	efiret = protocol->get_string_descriptor(protocol, lang_id, index,
+						 &efi_name);
+	if (EFI_ERROR(efiret))
+		return -efi_errno(efiret);
+
+	size--; /* leave room for trailing NULL char in output buffer */
+	for (idx = 0, u = 2;; u += 2) {
+		if (idx >= size)
+			break;
+		if (efi_name[u + 1]) /* high byte */
+			buf[idx++] = '?'; /* non-ASCII character */
+		else if (efi_name[u])
+			buf[idx++] = efi_name[u];
+		else
+			break;
+	}
+	buf[idx] = 0;
+
+	return 0;
+}
+
+static int create_usb_device(struct efi_usb_io_priv *priv)
+{
+	struct usb_host *host = &priv->host;
+	struct usb_device *dev;
+	efi_status_t efiret;
+	struct usb_interface *interface;
+	int err;
+	u16 *lang_ids;
+	u16 num_langs;
+
+	dev = usb_alloc_new_device();
+	dev->host = host;
+
+	dev_set_name(&dev->dev, "usb%d", dev->host->busnum);
+	dev->dev.id = DEVICE_ID_SINGLE;
+
+	efiret = priv->protocol->get_device_descriptor(priv->protocol,
+						       dev->descriptor);
+	if (EFI_ERROR(efiret)) {
+		err = -efi_errno(efiret);
+		goto out_err;
+	}
+
+	switch (dev->descriptor->bMaxPacketSize0) {
+	case 8:
+		dev->maxpacketsize = PACKET_SIZE_8;
+		break;
+	case 16:
+		dev->maxpacketsize = PACKET_SIZE_16;
+		break;
+	case 32:
+		dev->maxpacketsize = PACKET_SIZE_32;
+		break;
+	case 64:
+		dev->maxpacketsize = PACKET_SIZE_64;
+		break;
+	}
+
+	// There is only the possibility to access the current active configuration
+	// and not set the configuration.
+	// https://uefi.org/specs/UEFI/2.11/17_Protocols_USB_Support.html#efi-usb-io-protocol-usbgetconfigdescriptor
+	efiret = priv->protocol->get_config_descriptor(priv->protocol,
+						       &dev->config.desc);
+	if (EFI_ERROR(efiret)) {
+		err = -efi_errno(efiret);
+		goto out_err;
+	}
+
+	// UEFI has by definition only one interface per config
+	// https://uefi.org/specs/UEFI/2.11/17_Protocols_USB_Support.html#efi-usb-io-protocol-usbgetinterfacedescriptor
+	dev->config.no_of_if = 1;
+	interface = &dev->config.interface[0];
+
+	efiret = priv->protocol->get_interface_descriptor(priv->protocol,
+							  &interface->desc);
+	if (EFI_ERROR(efiret)) {
+		err = -efi_errno(efiret);
+		goto out_err;
+	}
+
+	interface->no_of_ep = interface->desc.bNumEndpoints;
+
+	if (interface->no_of_ep > USB_MAXENDPOINTS) {
+		err = -EPROTO;
+		goto out_err;
+	}
+
+	for (int i = 0; i < interface->no_of_ep; i++) {
+		efiret = priv->protocol->get_endpoint_descriptor(
+			priv->protocol, i, &interface->ep_desc[i]);
+		if (EFI_ERROR(efiret))
+			return -efi_errno(efiret);
+		usb_set_maxpacket_ep(dev, &interface->ep_desc[i]);
+	}
+
+	efiret = priv->protocol->get_supported_languages(priv->protocol,
+							 &lang_ids, &num_langs);
+	if (EFI_ERROR(efiret)) {
+		err = -efi_errno(efiret);
+		goto out_err;
+	}
+
+	num_langs = num_langs / sizeof(u16);
+	if (num_langs == 0) {
+		err = -EPROTO;
+		goto out_err;
+	}
+
+	dev->string_langid = lang_ids[0];
+	dev->have_langid = num_langs;
+
+	dev_info(&dev->dev, "new device: Mfr=%d, Product=%d, SerialNumber=%d\n",
+		 dev->descriptor->iManufacturer, dev->descriptor->iProduct,
+		 dev->descriptor->iSerialNumber);
+
+	err = efi_get_usb_string(priv->protocol, dev->string_langid,
+				 dev->descriptor->iManufacturer, dev->mf,
+				 sizeof(dev->mf));
+	if (err)
+		goto out_err;
+	err = efi_get_usb_string(priv->protocol, dev->string_langid,
+				 dev->descriptor->iProduct, dev->prod,
+				 sizeof(dev->prod));
+	if (err)
+		goto out_err;
+	err = efi_get_usb_string(priv->protocol, dev->string_langid,
+				 dev->descriptor->iSerialNumber, dev->serial,
+				 sizeof(dev->serial));
+	if (err)
+		goto out_err;
+
+	dev_info(&dev->dev, "Bus %03d Device %03d: ID %04x:%04x %s\n",
+		 dev->host->busnum, dev->devnum, dev->descriptor->idVendor,
+		 dev->descriptor->idProduct, dev->prod);
+
+	err = register_device(&dev->dev);
+	if (err) {
+		dev_err(&dev->dev, "Failed to register device: %pe\n",
+			ERR_PTR(err));
+		goto out_err;
+	}
+
+	// register as root device for host
+	host->root_dev = dev;
+
+	return 0;
+
+out_err:
+	dev_err(&dev->dev, "Failed to create UEFI-USB-IO device: %pe\n",
+		ERR_PTR(err));
+	usb_free_device(dev);
+	return err;
+}
+
+static int efi_usb_io_probe(struct efi_device *efidev)
+{
+	struct device *dev = &efidev->dev;
+	struct efi_usb_io_priv *priv;
+	struct usb_host *host;
+
+	priv = xzalloc(sizeof(*priv));
+
+	BS->handle_protocol(efidev->handle, &efi_usb_io_protocol_guid,
+			    (void **)&priv->protocol);
+	if (!priv->protocol)
+		return -ENODEV;
+
+	dev->priv = priv;
+	priv->dev = dev;
+
+	// EFI has one device per probe, which now needs its own host controller,
+	// since there is no shared host controller resource.
+
+	host = &priv->host;
+	host->submit_int_msg = efi_usb_int_msg;
+	host->submit_control_msg = efi_usb_control_msg;
+	host->submit_bulk_msg = efi_usb_bulk_msg;
+	usb_register_host(host);
+
+	return create_usb_device(priv);
+}
+
+static struct efi_driver efi_usb_io_driver = {
+	.driver = {
+		.name  = "efi-usb-io-protocol",
+	},
+	.probe = efi_usb_io_probe,
+	.guid = EFI_USB_IO_PROTOCOL_GUID,
+};
+device_efi_driver(efi_usb_io_driver);
diff --git a/efi/guid.c b/efi/guid.c
index 8853829d21..f438783fc1 100644
--- a/efi/guid.c
+++ b/efi/guid.c
@@ -15,6 +15,7 @@ efi_guid_t efi_null_guid = EFI_NULL_GUID;
 efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 const efi_guid_t efi_guid_image_security_database = EFI_IMAGE_SECURITY_DATABASE_GUID;
 efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+efi_guid_t efi_usb_io_protocol_guid = EFI_USB_IO_PROTOCOL_GUID;
 efi_guid_t efi_rng_protocol_guid = EFI_RNG_PROTOCOL_GUID;
 efi_guid_t efi_barebox_vendor_guid = EFI_BAREBOX_VENDOR_GUID;
 efi_guid_t efi_file_store_vars_guid = EFI_FILE_STORE_VARS_GUID;
diff --git a/include/efi/guid.h b/include/efi/guid.h
index 202300c74a..7d75842b04 100644
--- a/include/efi/guid.h
+++ b/include/efi/guid.h
@@ -27,6 +27,7 @@ extern efi_guid_t efi_null_guid;
 extern efi_guid_t efi_global_variable_guid;
 extern const efi_guid_t efi_guid_image_security_database;
 extern efi_guid_t efi_block_io_protocol_guid;
+extern efi_guid_t efi_usb_io_protocol_guid;
 extern efi_guid_t efi_rng_protocol_guid;
 extern efi_guid_t efi_barebox_vendor_guid;
 extern efi_guid_t efi_file_store_vars_guid;

-- 
2.47.3




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/5] efi: guid: add guid for usb host controller 2
  2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
                   ` (2 preceding siblings ...)
  2026-08-12 16:36 ` [PATCH 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
@ 2026-08-12 16:36 ` Fabian Pflug
  2026-08-12 16:36 ` [PATCH 5/5] test: x86: add test for uefi usb io Fabian Pflug
  4 siblings, 0 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

Taken from https://uefi.org/specs/UEFI/2.11/17_Protocols_USB_Support.html#usb2-host-controller-protocol

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
 efi/guid.c         | 1 +
 include/efi/guid.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/efi/guid.c b/efi/guid.c
index f438783fc1..568e1daa7d 100644
--- a/efi/guid.c
+++ b/efi/guid.c
@@ -100,6 +100,7 @@ const char *efi_guid_string(const efi_guid_t *g)
 	EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol");
 	EFI_GUID_STRING(EFI_PCI_IO_PROTOCOL_GUID, "PCI IO Protocol", "EFI 1.1 PCI IO Protocol");
 	EFI_GUID_STRING(EFI_USB_IO_PROTOCOL_GUID, "USB IO Protocol", "EFI 1.0 USB IO Protocol");
+	EFI_GUID_STRING(EFI_USB2_HC_PROTOCOL_GUID, "USB HC2 Protocol", "EFI 1.0 USB Host Protocol");
 	EFI_GUID_STRING(EFI_FILE_INFO_GUID, "File Info", "EFI File Info");
 	EFI_GUID_STRING(EFI_FILE_SYSTEM_INFO_GUID, "Filesystem Info", "EFI FileSystem Info");
 	EFI_GUID_STRING(EFI_FILE_SYSTEM_VOLUME_LABEL_ID, "Filesystem Volume Label ID", "EFI FileSystem Volume Label ID");
diff --git a/include/efi/guid.h b/include/efi/guid.h
index 7d75842b04..3e8cff0373 100644
--- a/include/efi/guid.h
+++ b/include/efi/guid.h
@@ -121,6 +121,9 @@ extern const efi_guid_t efi_debug_image_info_table_guid;
 #define EFI_USB_IO_PROTOCOL_GUID \
     EFI_GUID(0x2B2F68D6, 0x0CD2, 0x44cf, 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75)
 
+#define EFI_USB2_HC_PROTOCOL_GUID \
+    EFI_GUID(0x3e745226, 0x9818, 0x45b6, 0xa2, 0xac, 0xd7, 0xcd, 0x0e, 0x8b, 0xa2, 0xbc)
+
 #define EFI_FILE_INFO_GUID \
     EFI_GUID(  0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
 

-- 
2.47.3




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 5/5] test: x86: add test for uefi usb io
  2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
                   ` (3 preceding siblings ...)
  2026-08-12 16:36 ` [PATCH 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
@ 2026-08-12 16:36 ` Fabian Pflug
  4 siblings, 0 replies; 6+ messages in thread
From: Fabian Pflug @ 2026-08-12 16:36 UTC (permalink / raw)
  To: Sascha Hauer, BAREBOX; +Cc: Fabian Pflug

Check, that the EFI-USB-IO controller will create a USB Network device
in barebox. The device has currently no driver, but is available
nevertheless.

Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
---
 drivers/usb/host/efi-io-protocol.c | 15 ++++++++++++---
 test/x86/pc@efi_defconfig.yaml     |  9 ++++++++-
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/efi-io-protocol.c b/drivers/usb/host/efi-io-protocol.c
index bd35628f59..5c6abe5114 100644
--- a/drivers/usb/host/efi-io-protocol.c
+++ b/drivers/usb/host/efi-io-protocol.c
@@ -144,6 +144,16 @@ static int efi_get_usb_string(struct efi_usb_io_protocol *protocol, u16 lang_id,
 	return 0;
 }
 
+static void print_usb_device_info(struct device *dev)
+{
+	struct usb_device *usb_dev = container_of(dev, struct usb_device, dev);
+
+	dev_info(dev, "Bus %03d Device %03d: ID %04x:%04x %s\n",
+		 usb_dev->host->busnum, usb_dev->devnum,
+		 usb_dev->descriptor->idVendor, usb_dev->descriptor->idProduct,
+		 usb_dev->prod);
+}
+
 static int create_usb_device(struct efi_usb_io_priv *priv)
 {
 	struct usb_host *host = &priv->host;
@@ -255,9 +265,8 @@ static int create_usb_device(struct efi_usb_io_priv *priv)
 	if (err)
 		goto out_err;
 
-	dev_info(&dev->dev, "Bus %03d Device %03d: ID %04x:%04x %s\n",
-		 dev->host->busnum, dev->devnum, dev->descriptor->idVendor,
-		 dev->descriptor->idProduct, dev->prod);
+	print_usb_device_info(&dev->dev);
+	devinfo_add(&dev->dev, print_usb_device_info);
 
 	err = register_device(&dev->dev);
 	if (err) {
diff --git a/test/x86/pc@efi_defconfig.yaml b/test/x86/pc@efi_defconfig.yaml
index 2c077d5509..0e77d5a0eb 100644
--- a/test/x86/pc@efi_defconfig.yaml
+++ b/test/x86/pc@efi_defconfig.yaml
@@ -8,7 +8,11 @@ targets:
         memory: 1024M
         kernel: barebox.efi
         display: qemu-default
-        extra_args: '-bios OVMF.fd'
+        extra_args: >
+          -bios OVMF.fd
+          -device qemu-xhci,id=xhci
+          -device usb-net,netdev=usb0,bus=xhci.0
+          -netdev user,id=usb0
       BareboxDriver:
         prompt: 'barebox@[^:]+:[^ ]+ '
         bootstring: 'commandline:'
@@ -16,6 +20,7 @@ targets:
     features:
       - pci
     devices:
+      usb1: 'usb1: Bus 001 Device 000: ID 0525:a4a2 NDIS/QEMU USB Network Device'
       fb0: 'Type: primary'
       fbconsole0: 'Parent: fb0'
       wdog0: 'Parent: efi-wdt'
@@ -25,6 +30,8 @@ targets:
       acpi-APIC0: 'Signature: APIC (Multiple APIC Description Table)'
     runner:
       kconfig_add:
+        - CONFIG_USB_HOST=y
+        - CONFIG_USB_EFI_IO_PROTOCOL=y
         - CONFIG_DRIVER_SERIAL_NS16550=y
         - CONFIG_CONSOLE_ACTIVATE_FIRST=y # avoid duplicate output
 images:

-- 
2.47.3




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-12 16:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-12 16:36 [PATCH 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
2026-08-12 16:36 ` [PATCH 1/5] efi: usb: add header for usb-efi Fabian Pflug
2026-08-12 16:36 ` [PATCH 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
2026-08-12 16:36 ` [PATCH 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
2026-08-12 16:36 ` [PATCH 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
2026-08-12 16:36 ` [PATCH 5/5] test: x86: add test for uefi usb io Fabian Pflug

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox