* [PATCH v2 1/5] efi: usb: add header for usb-efi
2026-08-17 8:47 [PATCH v2 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
@ 2026-08-17 8:47 ` Fabian Pflug
2026-08-19 10:01 ` Ahmad Fatoum
2026-08-17 8:47 ` [PATCH v2 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-17 8:47 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>
---
v2:
- Fixed wrong type in header for get_string_descriptor
---
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..78953a4fa7
--- /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,
+ wchar_t **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] 14+ messages in thread* Re: [PATCH v2 1/5] efi: usb: add header for usb-efi
2026-08-17 8:47 ` [PATCH v2 1/5] efi: usb: add header for usb-efi Fabian Pflug
@ 2026-08-19 10:01 ` Ahmad Fatoum
2026-08-19 13:32 ` Fabian Pflug
0 siblings, 1 reply; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 10:01 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
Hello,
On 8/17/26 10:47 AM, Fabian Pflug wrote:
> 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
Some nitpicks below. You don't need to resend for just those, but if you
are sending a v2, it would be good to address these as well.
>
> Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>
> ---
> v2:
> - Fixed wrong type in header for get_string_descriptor
> ---
> 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..78953a4fa7
> --- /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>
Nitpick: I would drop this and just predeclare struct devrequest.
> +
> +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
Nitpick: Add some tabs between the macros and the values for indentation?
> +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,
> + wchar_t **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
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v2 1/5] efi: usb: add header for usb-efi
2026-08-19 10:01 ` Ahmad Fatoum
@ 2026-08-19 13:32 ` Fabian Pflug
2026-08-19 14:03 ` Ahmad Fatoum
0 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-19 13:32 UTC (permalink / raw)
To: Ahmad Fatoum, Sascha Hauer, BAREBOX
Hey,
On Wed, 2026-08-19 at 12:01 +0200, Ahmad Fatoum wrote:
> Hello,
>
> On 8/17/26 10:47 AM, Fabian Pflug wrote:
> > 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
>
> Some nitpicks below. You don't need to resend for just those, but if you
> are sending a v2, it would be good to address these as well.
>
> >
> > Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
>
> Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>
> >
> > ---
> > v2:
> > - Fixed wrong type in header for get_string_descriptor
> > ---
> > 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..78953a4fa7
> > --- /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>
>
> Nitpick: I would drop this and just predeclare struct devrequest.
It is also
struct usb_config_descriptor
struct usb_device_descriptor
struct usb_interface_descriptor
struct usb_endpoint_descriptor
>
> > +
> > +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
>
> Nitpick: Add some tabs between the macros and the values for indentation?
I could, but clang-format will remove the tabs. And I like to just call it to format the rest and not have the hassle to
revert formatting here.
/Fabian
>
> > +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,
> > + wchar_t **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
> >
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v2 1/5] efi: usb: add header for usb-efi
2026-08-19 13:32 ` Fabian Pflug
@ 2026-08-19 14:03 ` Ahmad Fatoum
2026-08-19 14:11 ` Fabian Pflug
0 siblings, 1 reply; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 14:03 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
Hi Fabian,
On 8/19/26 3:32 PM, Fabian Pflug wrote:
> Hey,
>
> On Wed, 2026-08-19 at 12:01 +0200, Ahmad Fatoum wrote:
>> Hello,
>>
>> On 8/17/26 10:47 AM, Fabian Pflug wrote:
>>> 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
>>
>> Some nitpicks below. You don't need to resend for just those, but if you
>> are sending a v2, it would be good to address these as well.
>>
>>>
>>> Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
>>
>> Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>>
>>>
>>> ---
>>> v2:
>>> - Fixed wrong type in header for get_string_descriptor
>>> ---
>>> 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..78953a4fa7
>>> --- /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>
>>
>> Nitpick: I would drop this and just predeclare struct devrequest.
>
> It is also
>
> struct usb_config_descriptor
> struct usb_device_descriptor
> struct usb_interface_descriptor
> struct usb_endpoint_descriptor
as all of these are used behind a pointer, just predeclare them as well
(don't define them).
>
>>
>>> +
>>> +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
>>
>> Nitpick: Add some tabs between the macros and the values for indentation?
>
> I could, but clang-format will remove the tabs. And I like to just call it to format the rest and not have the hassle to
> revert formatting here.
Does it also do that, when you sync against an up-to-date .clang-format
from the kernel?
Cheers,
Ahmad
>
> /Fabian
>
>>
>>> +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,
>>> + wchar_t **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
>>>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH v2 1/5] efi: usb: add header for usb-efi
2026-08-19 14:03 ` Ahmad Fatoum
@ 2026-08-19 14:11 ` Fabian Pflug
0 siblings, 0 replies; 14+ messages in thread
From: Fabian Pflug @ 2026-08-19 14:11 UTC (permalink / raw)
To: Ahmad Fatoum, Sascha Hauer, BAREBOX
On Wed, 2026-08-19 at 16:03 +0200, Ahmad Fatoum wrote:
> Hi Fabian,
>
> On 8/19/26 3:32 PM, Fabian Pflug wrote:
> > Hey,
> >
> > On Wed, 2026-08-19 at 12:01 +0200, Ahmad Fatoum wrote:
> > > Hello,
> > >
> > > On 8/17/26 10:47 AM, Fabian Pflug wrote:
> > > > 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
> > >
> > > Some nitpicks below. You don't need to resend for just those, but if you
> > > are sending a v2, it would be good to address these as well.
> > >
> > > >
> > > > Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
> > >
> > > Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> > >
> > > >
> > > > ---
> > > > v2:
> > > > - Fixed wrong type in header for get_string_descriptor
> > > > ---
> > > > 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..78953a4fa7
> > > > --- /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>
> > >
> > > Nitpick: I would drop this and just predeclare struct devrequest.
> >
> > It is also
> >
> > struct usb_config_descriptor
> > struct usb_device_descriptor
> > struct usb_interface_descriptor
> > struct usb_endpoint_descriptor
>
> as all of these are used behind a pointer, just predeclare them as well
> (don't define them).
>
Okay.
> >
> > >
> > > > +
> > > > +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
> > >
> > > Nitpick: Add some tabs between the macros and the values for indentation?
> >
> > I could, but clang-format will remove the tabs. And I like to just call it to format the rest and not have the
> > hassle to
> > revert formatting here.
>
> Does it also do that, when you sync against an up-to-date .clang-format
> from the kernel?
>
Since the only difference are the ForEachMacros. Yes. (Tested it nonetheless)
/Fabian
> Cheers,
> Ahmad
>
> >
> > /Fabian
> >
> > >
> > > > +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,
> > > > + wchar_t **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
> > > >
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 2/5] usb: core: make usb_set_maxpacket_ep public
2026-08-17 8:47 [PATCH v2 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
2026-08-17 8:47 ` [PATCH v2 1/5] efi: usb: add header for usb-efi Fabian Pflug
@ 2026-08-17 8:47 ` Fabian Pflug
2026-08-19 9:15 ` Ahmad Fatoum
2026-08-17 8:47 ` [PATCH v2 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-17 8:47 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] 14+ messages in thread* Re: [PATCH v2 2/5] usb: core: make usb_set_maxpacket_ep public
2026-08-17 8:47 ` [PATCH v2 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
@ 2026-08-19 9:15 ` Ahmad Fatoum
0 siblings, 0 replies; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 9:15 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
On 8/17/26 10:47 AM, Fabian Pflug wrote:
> 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>
Reviewed-by: Ahmad Fatoum <a.fatoum@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 */
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/5] drivers: usb: host: efi: add efi io driver
2026-08-17 8:47 [PATCH v2 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
2026-08-17 8:47 ` [PATCH v2 1/5] efi: usb: add header for usb-efi Fabian Pflug
2026-08-17 8:47 ` [PATCH v2 2/5] usb: core: make usb_set_maxpacket_ep public Fabian Pflug
@ 2026-08-17 8:47 ` Fabian Pflug
2026-08-19 11:04 ` Ahmad Fatoum
2026-08-17 8:47 ` [PATCH v2 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
2026-08-17 8:47 ` [PATCH v2 5/5] test: x86: add test for uefi usb io Fabian Pflug
4 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-17 8:47 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>
---
v2:
- add missing free to string buffer
- use 16bit data type for string buffer
- include the first byte of string buffer
- renamed num_langs to table_size and made usage clearer
---
drivers/usb/host/Kconfig | 11 ++
drivers/usb/host/Makefile | 1 +
drivers/usb/host/efi-io-protocol.c | 317 +++++++++++++++++++++++++++++++++++++
efi/guid.c | 1 +
include/efi/guid.h | 1 +
5 files changed, 331 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..8207d33dcf
--- /dev/null
+++ b/drivers/usb/host/efi-io-protocol.c
@@ -0,0 +1,317 @@
+// 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)
+{
+ wchar_t *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 = 0;; u++) {
+ if (idx >= size)
+ break;
+ if (efi_name[u] & 0xff00) /* high byte */
+ buf[idx++] = '?'; /* non-ASCII character */
+ else if (efi_name[u])
+ buf[idx++] = efi_name[u] & 0xff;
+ else
+ break;
+ }
+ buf[idx] = 0;
+ BS->free_pool(efi_name);
+
+ 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 table_size;
+
+ 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, &table_size);
+ if (EFI_ERROR(efiret)) {
+ err = -efi_errno(efiret);
+ goto out_err;
+ }
+
+ /* table size is given in bytes, not entries */
+ if (table_size < sizeof(*lang_ids)) {
+ err = -EPROTO;
+ goto out_err;
+ }
+
+ dev->string_langid = lang_ids[0];
+ dev->have_langid = true;
+
+ 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] 14+ messages in thread* Re: [PATCH v2 3/5] drivers: usb: host: efi: add efi io driver
2026-08-17 8:47 ` [PATCH v2 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
@ 2026-08-19 11:04 ` Ahmad Fatoum
0 siblings, 0 replies; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 11:04 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
Hi,
On 8/17/26 10:47 AM, Fabian Pflug wrote:
> +config USB_EFI_IO_PROTOCOL
> + bool "EFI USB I/O Protocol"
> + depends on EFI_PAYLOAD
> + depends on USB_HOST
This depends is redundant, because the whole file is only included when
USB_HOST is selected.
> +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;
return -EPIPE
> +
> + 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);
Should be goto.
> + usb_set_maxpacket_ep(dev, &interface->ep_desc[i]);
> + }
> +
> + efiret = priv->protocol->get_supported_languages(priv->protocol,
> + &lang_ids, &table_size);
> + if (EFI_ERROR(efiret)) {
> + err = -efi_errno(efiret);
> + goto out_err;
> + }
> +
> + /* table size is given in bytes, not entries */
> + if (table_size < sizeof(*lang_ids)) {
> + err = -EPROTO;
> + goto out_err;
> + }
> +
> + dev->string_langid = lang_ids[0];
> + dev->have_langid = true;
Set this to false when table_size == 0 instead of an error?
> +
> + 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;
host->hw_dev must be set.
Cheers,
Ahmad
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 4/5] efi: guid: add guid for usb host controller 2
2026-08-17 8:47 [PATCH v2 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
` (2 preceding siblings ...)
2026-08-17 8:47 ` [PATCH v2 3/5] drivers: usb: host: efi: add efi io driver Fabian Pflug
@ 2026-08-17 8:47 ` Fabian Pflug
2026-08-19 9:18 ` Ahmad Fatoum
2026-08-17 8:47 ` [PATCH v2 5/5] test: x86: add test for uefi usb io Fabian Pflug
4 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-17 8:47 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] 14+ messages in thread* Re: [PATCH v2 4/5] efi: guid: add guid for usb host controller 2
2026-08-17 8:47 ` [PATCH v2 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
@ 2026-08-19 9:18 ` Ahmad Fatoum
0 siblings, 0 replies; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 9:18 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
On 8/17/26 10:47 AM, Fabian Pflug wrote:
> 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>
Acked-by: Ahmad Fatoum <a.fatoum@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 )
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 5/5] test: x86: add test for uefi usb io
2026-08-17 8:47 [PATCH v2 0/5] Add support for USB-EFI devices in EFI Playload Fabian Pflug
` (3 preceding siblings ...)
2026-08-17 8:47 ` [PATCH v2 4/5] efi: guid: add guid for usb host controller 2 Fabian Pflug
@ 2026-08-17 8:47 ` Fabian Pflug
2026-08-19 9:18 ` Ahmad Fatoum
4 siblings, 1 reply; 14+ messages in thread
From: Fabian Pflug @ 2026-08-17 8:47 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 8207d33dcf..fdd21f24a0 100644
--- a/drivers/usb/host/efi-io-protocol.c
+++ b/drivers/usb/host/efi-io-protocol.c
@@ -145,6 +145,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;
@@ -256,9 +266,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..4feabb232d 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 RNDIS/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] 14+ messages in thread* Re: [PATCH v2 5/5] test: x86: add test for uefi usb io
2026-08-17 8:47 ` [PATCH v2 5/5] test: x86: add test for uefi usb io Fabian Pflug
@ 2026-08-19 9:18 ` Ahmad Fatoum
0 siblings, 0 replies; 14+ messages in thread
From: Ahmad Fatoum @ 2026-08-19 9:18 UTC (permalink / raw)
To: Fabian Pflug, Sascha Hauer, BAREBOX
Hi,
On 8/17/26 10:47 AM, Fabian Pflug wrote:
> 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.
Thanks for adding a test!
>
> Signed-off-by: Fabian Pflug <f.pflug@pengutronix.de>
Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Cheers,
Ahmad
> ---
> 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 8207d33dcf..fdd21f24a0 100644
> --- a/drivers/usb/host/efi-io-protocol.c
> +++ b/drivers/usb/host/efi-io-protocol.c
> @@ -145,6 +145,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;
> @@ -256,9 +266,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..4feabb232d 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 RNDIS/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:
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 14+ messages in thread