grub xhci support

see:

https://github.com/9elements/grub/commits/xhci-module-upstreaming-squash_v4/

grub only supports xhci on bios/uefi targets, but not coreboot.
some newer machines don't have ps/2 controllers, and boot in a
way where ehci isn't available at startup; the controller can't
be used by ehci code, there must be xhci support.

the code is from Patrick Rudolph working on behalf of 9elements.
the code was also sent here for review:

https://lists.gnu.org/archive/html/grub-devel/2020-12/msg00111.html

however, upstream never merged these patches. libreboot will have
to maintain these from now on. the patches have been rebased for
use with grub 2.12.

Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
Leah Rowe 2024-04-05 23:44:06 +01:00
parent 5cb17795c6
commit f7283fa10d
9 changed files with 3537 additions and 0 deletions

View File

@ -36,6 +36,7 @@ crypto \
cryptodisk \
diskfilter \
echo \
xhci \
ehci \
eval \
exfat \

View File

@ -0,0 +1,245 @@
From 90c9011f2e0350a97e3df44b0fc6dd022e04c276 Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Sun, 15 Nov 2020 19:00:27 +0100
Subject: [PATCH 1/8] grub-core/bus/usb: Parse SuperSpeed companion descriptors
Parse the SS_ENDPOINT_COMPANION descriptor, which is only present on USB 3.0
capable devices and xHCI controllers. Make the descendp an array of pointers
to the endpoint descriptor as it's no longer an continous array.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/serial/common.c | 2 +-
grub-core/bus/usb/usb.c | 44 +++++++++++++++++++------------
grub-core/bus/usb/usbhub.c | 22 ++++++++++++----
grub-core/commands/usbtest.c | 2 +-
grub-core/disk/usbms.c | 2 +-
grub-core/term/usb_keyboard.c | 2 +-
include/grub/usb.h | 2 +-
include/grub/usbdesc.h | 11 +++++++-
8 files changed, 59 insertions(+), 28 deletions(-)
diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c
index e9c995a0a..fc847d66d 100644
--- a/grub-core/bus/usb/serial/common.c
+++ b/grub-core/bus/usb/serial/common.c
@@ -72,7 +72,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
for (j = 0; j < interf->endpointcnt; j++)
{
struct grub_usb_desc_endp *endp;
- endp = &usbdev->config[0].interf[interfno].descendp[j];
+ endp = usbdev->config[0].interf[interfno].descendp[j];
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2
&& (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
index 7bd49d201..e578af793 100644
--- a/grub-core/bus/usb/usb.c
+++ b/grub-core/bus/usb/usb.c
@@ -118,7 +118,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
struct grub_usb_desc_device *descdev;
struct grub_usb_desc_config config;
grub_usb_err_t err;
- int i;
+ int i, j;
/* First we have to read first 8 bytes only and determine
* max. size of packet */
@@ -152,6 +152,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
int currif;
char *data;
struct grub_usb_desc *desc;
+ struct grub_usb_desc_endp *endp;
/* First just read the first 4 bytes of the configuration
descriptor, after that it is known how many bytes really have
@@ -201,24 +202,27 @@ grub_usb_device_initialize (grub_usb_device_t dev)
= (struct grub_usb_desc_if *) &data[pos];
pos += dev->config[i].interf[currif].descif->length;
+ dev->config[i].interf[currif].descendp = grub_malloc (
+ dev->config[i].interf[currif].descif->endpointcnt *
+ sizeof(struct grub_usb_desc_endp));
+
+ j = 0;
while (pos < config.totallen)
{
desc = (struct grub_usb_desc *)&data[pos];
- if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT)
- break;
- if (!desc->length)
- {
- err = GRUB_USB_ERR_BADDEVICE;
- goto fail;
- }
- pos += desc->length;
- }
-
- /* Point to the first endpoint. */
- dev->config[i].interf[currif].descendp
- = (struct grub_usb_desc_endp *) &data[pos];
- pos += (sizeof (struct grub_usb_desc_endp)
- * dev->config[i].interf[currif].descif->endpointcnt);
+ if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) {
+ endp = (struct grub_usb_desc_endp *) &data[pos];
+ dev->config[i].interf[currif].descendp[j++] = endp;
+ pos += desc->length;
+ } else {
+ if (!desc->length)
+ {
+ err = GRUB_USB_ERR_BADDEVICE;
+ goto fail;
+ }
+ pos += desc->length;
+ }
+ }
}
}
@@ -226,8 +230,14 @@ grub_usb_device_initialize (grub_usb_device_t dev)
fail:
- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
+ int currif;
+
+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
+ grub_free (dev->config[i].interf[currif].descendp);
+
grub_free (dev->config[i].descconf);
+ }
return err;
}
diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
index f5608e330..2ae29cba1 100644
--- a/grub-core/bus/usb/usbhub.c
+++ b/grub-core/bus/usb/usbhub.c
@@ -82,8 +82,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
if (i == GRUB_USBHUB_MAX_DEVICES)
{
grub_error (GRUB_ERR_IO, "can't assign address to USB device");
- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
- grub_free (dev->config[i].descconf);
+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
+ int currif;
+
+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
+ grub_free (dev->config[i].interf[currif].descendp);
+
+ grub_free (dev->config[i].descconf);
+ }
grub_free (dev);
return NULL;
}
@@ -96,8 +102,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
i, 0, 0, NULL);
if (err)
{
- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
- grub_free (dev->config[i].descconf);
+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
+ int currif;
+
+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
+ grub_free (dev->config[i].interf[currif].descendp);
+
+ grub_free (dev->config[i].descconf);
+ }
grub_free (dev);
return NULL;
}
@@ -176,7 +188,7 @@ grub_usb_add_hub (grub_usb_device_t dev)
i++)
{
struct grub_usb_desc_endp *endp = NULL;
- endp = &dev->config[0].interf[0].descendp[i];
+ endp = dev->config[0].interf[0].descendp[i];
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
== GRUB_USB_EP_INTERRUPT)
diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c
index 2c6d93fe6..55a657635 100644
--- a/grub-core/commands/usbtest.c
+++ b/grub-core/commands/usbtest.c
@@ -185,7 +185,7 @@ usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused)))
for (j = 0; j < interf->endpointcnt; j++)
{
struct grub_usb_desc_endp *endp;
- endp = &dev->config[0].interf[i].descendp[j];
+ endp = dev->config[0].interf[i].descendp[j];
grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
endp->endp_addr & 15,
diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c
index b81e3ad9d..b1512dc12 100644
--- a/grub-core/disk/usbms.c
+++ b/grub-core/disk/usbms.c
@@ -184,7 +184,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
for (j = 0; j < interf->endpointcnt; j++)
{
struct grub_usb_desc_endp *endp;
- endp = &usbdev->config[0].interf[interfno].descendp[j];
+ endp = usbdev->config[0].interf[interfno].descendp[j];
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
/* Bulk IN endpoint. */
diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c
index 7322d8dff..d590979f5 100644
--- a/grub-core/term/usb_keyboard.c
+++ b/grub-core/term/usb_keyboard.c
@@ -175,7 +175,7 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
for (j = 0; j < usbdev->config[configno].interf[interfno].descif->endpointcnt;
j++)
{
- endp = &usbdev->config[configno].interf[interfno].descendp[j];
+ endp = usbdev->config[configno].interf[interfno].descendp[j];
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
== GRUB_USB_EP_INTERRUPT)
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 0f346af12..688c11f6d 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -153,7 +153,7 @@ struct grub_usb_interface
{
struct grub_usb_desc_if *descif;
- struct grub_usb_desc_endp *descendp;
+ struct grub_usb_desc_endp **descendp;
/* A driver is handling this interface. Do we need to support multiple drivers
for single interface?
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
index aac5ab05a..bb2ab2e27 100644
--- a/include/grub/usbdesc.h
+++ b/include/grub/usbdesc.h
@@ -29,7 +29,8 @@ typedef enum {
GRUB_USB_DESCRIPTOR_INTERFACE,
GRUB_USB_DESCRIPTOR_ENDPOINT,
GRUB_USB_DESCRIPTOR_DEBUG = 10,
- GRUB_USB_DESCRIPTOR_HUB = 0x29
+ GRUB_USB_DESCRIPTOR_HUB = 0x29,
+ GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30
} grub_usb_descriptor_t;
struct grub_usb_desc
@@ -105,6 +106,14 @@ struct grub_usb_desc_endp
grub_uint8_t interval;
} GRUB_PACKED;
+struct grub_usb_desc_ssep {
+ grub_uint8_t length;
+ grub_uint8_t type;
+ grub_uint8_t maxburst;
+ grub_uint8_t attrib;
+ grub_uint16_t interval;
+} GRUB_PACKED;
+
struct grub_usb_desc_str
{
grub_uint8_t length;
--
2.39.2

View File

@ -0,0 +1,29 @@
From e111983ca5e2a52bfe2bdc5cd639b06bb2f7902d Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Sun, 15 Nov 2020 19:47:06 +0100
Subject: [PATCH 2/8] usb: Add enum for xHCI
Will be used in future patches.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
include/grub/usb.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 688c11f6d..ea6ee8c2c 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -51,7 +51,8 @@ typedef enum
GRUB_USB_SPEED_NONE,
GRUB_USB_SPEED_LOW,
GRUB_USB_SPEED_FULL,
- GRUB_USB_SPEED_HIGH
+ GRUB_USB_SPEED_HIGH,
+ GRUB_USB_SPEED_SUPER
} grub_usb_speed_t;
typedef int (*grub_usb_iterate_hook_t) (grub_usb_device_t dev, void *data);
--
2.39.2

View File

@ -0,0 +1,33 @@
From 3e25c83a1d1c6e149c7e9f0660ddadb2beca2476 Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Sun, 15 Nov 2020 19:48:03 +0100
Subject: [PATCH 3/8] usbtrans: Set default maximum packet size
Set the maximum packet size to 512 for SuperSpeed devices.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/usbtrans.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
index c5680b33a..c1080bb33 100644
--- a/grub-core/bus/usb/usbtrans.c
+++ b/grub-core/bus/usb/usbtrans.c
@@ -128,8 +128,12 @@ grub_usb_control_msg (grub_usb_device_t dev,
setupdata_addr = grub_dma_get_phys (setupdata_chunk);
/* Determine the maximum packet size. */
- if (dev->descdev.maxsize0)
+ if (dev->descdev.maxsize0 && dev->speed != GRUB_USB_SPEED_SUPER)
max = dev->descdev.maxsize0;
+ else if (dev->descdev.maxsize0 && dev->speed == GRUB_USB_SPEED_SUPER)
+ max = 1UL << dev->descdev.maxsize0;
+ else if (dev->speed == GRUB_USB_SPEED_SUPER)
+ max = 512;
else
max = 64;
--
2.39.2

View File

@ -0,0 +1,121 @@
From 89701aba00caa81bb566ab10da0c89264393be30 Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Sun, 15 Nov 2020 19:51:42 +0100
Subject: [PATCH 4/8] grub-core/bus/usb: Add function pointer for attach/detach
events
The xHCI code needs to be called for attaching or detaching a device.
Introduce two functions pointers and call it from the USB hub code.
Will be used in future commits, currently this doesn't change any functionality.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/ehci.c | 2 ++
grub-core/bus/usb/ohci.c | 2 ++
grub-core/bus/usb/uhci.c | 2 ++
grub-core/bus/usb/usbhub.c | 19 +++++++++++++++++++
include/grub/usb.h | 4 ++++
5 files changed, 29 insertions(+)
diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
index 9abebc6bd..953b851c0 100644
--- a/grub-core/bus/usb/ehci.c
+++ b/grub-core/bus/usb/ehci.c
@@ -1812,6 +1812,8 @@ static struct grub_usb_controller_dev usb_controller = {
.hubports = grub_ehci_hubports,
.portstatus = grub_ehci_portstatus,
.detect_dev = grub_ehci_detect_dev,
+ .attach_dev = NULL,
+ .detach_dev = NULL,
/* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
};
diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c
index 5363a61f6..7a3f3e154 100644
--- a/grub-core/bus/usb/ohci.c
+++ b/grub-core/bus/usb/ohci.c
@@ -1440,6 +1440,8 @@ static struct grub_usb_controller_dev usb_controller =
.hubports = grub_ohci_hubports,
.portstatus = grub_ohci_portstatus,
.detect_dev = grub_ohci_detect_dev,
+ .attach_dev = NULL,
+ .detach_dev = NULL,
/* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
};
diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c
index 0fdea4c1e..03c4605b2 100644
--- a/grub-core/bus/usb/uhci.c
+++ b/grub-core/bus/usb/uhci.c
@@ -845,6 +845,8 @@ static struct grub_usb_controller_dev usb_controller =
.hubports = grub_uhci_hubports,
.portstatus = grub_uhci_portstatus,
.detect_dev = grub_uhci_detect_dev,
+ .attach_dev = NULL,
+ .detach_dev = NULL,
/* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = N_TD * 3 / 4
};
diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
index 2ae29cba1..8e963e84b 100644
--- a/grub-core/bus/usb/usbhub.c
+++ b/grub-core/bus/usb/usbhub.c
@@ -66,6 +66,15 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
dev->split_hubport = split_hubport;
dev->split_hubaddr = split_hubaddr;
+ if (controller->dev->attach_dev) {
+ err = controller->dev->attach_dev (controller, dev);
+ if (err)
+ {
+ grub_free (dev);
+ return NULL;
+ }
+ }
+
err = grub_usb_device_initialize (dev);
if (err)
{
@@ -405,6 +414,8 @@ static void
detach_device (grub_usb_device_t dev)
{
unsigned i;
+ grub_usb_err_t err;
+
int k;
if (!dev)
return;
@@ -425,6 +436,14 @@ detach_device (grub_usb_device_t dev)
if (inter && inter->detach_hook)
inter->detach_hook (dev, i, k);
}
+ if (dev->controller.dev->detach_dev) {
+ err = dev->controller.dev->detach_dev (&dev->controller, dev);
+ if (err)
+ {
+ // XXX
+ }
+ }
+
grub_usb_devs[dev->addr] = 0;
}
diff --git a/include/grub/usb.h b/include/grub/usb.h
index ea6ee8c2c..4dd179db2 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -126,6 +126,10 @@ struct grub_usb_controller_dev
grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed);
+ grub_usb_err_t (*attach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev);
+
+ grub_usb_err_t (*detach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev);
+
/* Per controller flag - port reset pending, don't do another reset */
grub_uint64_t pending_reset;
--
2.39.2

View File

@ -0,0 +1,77 @@
From 5e5d74a4531770258e21dedd45c33f1a9d3afa6b Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Sun, 15 Nov 2020 19:54:40 +0100
Subject: [PATCH 5/8] grub-core/bus/usb/usbhub: Add new private fields for xHCI
controller
Store the root port number, the route, consisting out of the port ID
in each nibble, and a pointer to driver private data.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/usbhub.c | 11 ++++++++---
include/grub/usb.h | 5 +++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
index 8e963e84b..b4b3a1a61 100644
--- a/grub-core/bus/usb/usbhub.c
+++ b/grub-core/bus/usb/usbhub.c
@@ -49,7 +49,9 @@ static grub_usb_controller_dev_t grub_usb_list;
static grub_usb_device_t
grub_usb_hub_add_dev (grub_usb_controller_t controller,
grub_usb_speed_t speed,
- int split_hubport, int split_hubaddr)
+ int split_hubport, int split_hubaddr,
+ int root_portno,
+ grub_uint32_t route)
{
grub_usb_device_t dev;
int i;
@@ -65,6 +67,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
dev->speed = speed;
dev->split_hubport = split_hubport;
dev->split_hubaddr = split_hubaddr;
+ dev->root_port = root_portno;
+ dev->route = route;
if (controller->dev->attach_dev) {
err = controller->dev->attach_dev (controller, dev);
@@ -245,7 +249,7 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
and full/low speed device connected to OHCI/UHCI needs not
transaction translation - e.g. hubport and hubaddr should be
always none (zero) for any device connected to any root hub. */
- dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0);
+ dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0, portno, 0);
hub->controller->dev->pending_reset = 0;
npending--;
if (! dev)
@@ -676,7 +680,8 @@ poll_nonroot_hub (grub_usb_device_t dev)
/* Add the device and assign a device address to it. */
next_dev = grub_usb_hub_add_dev (&dev->controller, speed,
- split_hubport, split_hubaddr);
+ split_hubport, split_hubaddr, dev->root_port,
+ dev->route << 4 | (i & 0xf));
if (dev->controller.dev->pending_reset)
{
dev->controller.dev->pending_reset = 0;
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 4dd179db2..609faf7d0 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -237,6 +237,11 @@ struct grub_usb_device
int split_hubport;
int split_hubaddr;
+
+ /* xHCI specific information */
+ int root_port;
+ grub_uint32_t route;
+ void *xhci_priv;
};
--
2.39.2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
From 2a2c64f6ea62337c1263a70f6ca9a9bade66b78b Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Thu, 3 Dec 2020 13:44:55 +0100
Subject: [PATCH 7/8] grub-core/bus/usb/usbhub: Add xHCI non root hub support
Tested on Intel PCH C246, the USB3 hub can be configured by grub.
Issues:
* USB3 devices connected behind that hub are sometimes not detected.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/usbhub.c | 38 +++++++++++++++++++++++++++++++++-----
include/grub/usbdesc.h | 1 +
include/grub/usbtrans.h | 4 ++++
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
index b4b3a1a61..e96505aa9 100644
--- a/grub-core/bus/usb/usbhub.c
+++ b/grub-core/bus/usb/usbhub.c
@@ -148,19 +148,32 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
return dev;
}
-
+static grub_usb_err_t
+grub_usb_set_hub_depth(grub_usb_device_t dev, grub_uint8_t depth)
+{
+ return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+ | GRUB_USB_REQTYPE_CLASS
+ | GRUB_USB_REQTYPE_TARGET_DEV),
+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH, depth,
+ 0, 0, NULL);
+}
+
static grub_usb_err_t
grub_usb_add_hub (grub_usb_device_t dev)
{
struct grub_usb_usb_hubdesc hubdesc;
grub_usb_err_t err;
+ grub_uint16_t req;
int i;
+ req = (dev->speed == GRUB_USB_SPEED_SUPER) ? GRUB_USB_DESCRIPTOR_SS_HUB :
+ GRUB_USB_DESCRIPTOR_HUB;
+
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
| GRUB_USB_REQTYPE_CLASS
| GRUB_USB_REQTYPE_TARGET_DEV),
- GRUB_USB_REQ_GET_DESCRIPTOR,
- (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
+ GRUB_USB_REQ_GET_DESCRIPTOR,
+ (req << 8) | 0,
0, sizeof (hubdesc), (char *) &hubdesc);
if (err)
return err;
@@ -183,6 +196,19 @@ grub_usb_add_hub (grub_usb_device_t dev)
return GRUB_USB_ERR_INTERNAL;
}
+ if (dev->speed == GRUB_USB_SPEED_SUPER)
+ {
+ grub_uint8_t depth;
+ grub_uint32_t route;
+ /* Depth maximum value is 5, but root hubs doesn't count */
+ for (depth = 0, route = dev->route; (route & 0xf) > 0; route >>= 4)
+ depth++;
+
+ err = grub_usb_set_hub_depth(dev, depth);
+ if (err)
+ return err;
+ }
+
/* Power on all Hub ports. */
for (i = 1; i <= hubdesc.portcnt; i++)
{
@@ -637,7 +663,9 @@ poll_nonroot_hub (grub_usb_device_t dev)
int split_hubaddr = 0;
/* Determine the device speed. */
- if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
+ if (dev->speed == GRUB_USB_SPEED_SUPER)
+ speed = GRUB_USB_SPEED_SUPER;
+ else if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
speed = GRUB_USB_SPEED_LOW;
else
{
@@ -651,7 +679,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
grub_millisleep (10);
/* Find correct values for SPLIT hubport and hubaddr */
- if (speed == GRUB_USB_SPEED_HIGH)
+ if (speed == GRUB_USB_SPEED_HIGH || speed == GRUB_USB_SPEED_SUPER)
{
/* HIGH speed device needs not transaction translation */
split_hubport = 0;
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
index bb2ab2e27..1697aa465 100644
--- a/include/grub/usbdesc.h
+++ b/include/grub/usbdesc.h
@@ -30,6 +30,7 @@ typedef enum {
GRUB_USB_DESCRIPTOR_ENDPOINT,
GRUB_USB_DESCRIPTOR_DEBUG = 10,
GRUB_USB_DESCRIPTOR_HUB = 0x29,
+ GRUB_USB_DESCRIPTOR_SS_HUB = 0x2a,
GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30
} grub_usb_descriptor_t;
diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h
index 039ebed65..d6c3f71dc 100644
--- a/include/grub/usbtrans.h
+++ b/include/grub/usbtrans.h
@@ -110,6 +110,10 @@ enum
GRUB_USB_REQ_SET_INTERFACE = 0x0B,
GRUB_USB_REQ_SYNC_FRAME = 0x0C
};
+enum
+ {
+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH = 0x0C,
+ };
#define GRUB_USB_FEATURE_ENDP_HALT 0x00
#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01
--
2.39.2

View File

@ -0,0 +1,90 @@
From 871d768f8c5c960cb0d9761a9028b16882e1a7d3 Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Wed, 24 Feb 2021 08:25:41 +0100
Subject: [PATCH 8/8] Fix compilation on x86_64
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
grub-core/bus/usb/xhci.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c
index f4591ffb5..3495bb919 100644
--- a/grub-core/bus/usb/xhci.c
+++ b/grub-core/bus/usb/xhci.c
@@ -184,7 +184,7 @@ enum
* then we can get it from a trb pointer (provided by evt ring).
*/
#define XHCI_RING(_trb) \
- ((struct grub_xhci_ring*)((grub_uint32_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1)))
+ ((struct grub_xhci_ring*)((grub_addr_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1)))
/* slot context */
struct grub_xhci_slotctx {
@@ -495,6 +495,14 @@ grub_xhci_read8(volatile void *addr) {
return (*((volatile grub_uint32_t *)addr));
}
+static inline void *
+grub_xhci_read_etrb_ptr(volatile struct grub_xhci_trb *trb) {
+ grub_uint64_t tmp;
+ tmp = (grub_uint64_t)grub_xhci_read32(&trb->ptr_low);
+ tmp |= ((grub_uint64_t)grub_xhci_read32(&trb->ptr_high)) << 32;
+ return (void *)(grub_addr_t)tmp;
+}
+
static inline grub_uint32_t
grub_xhci_port_read (struct grub_xhci *x, grub_uint32_t port)
{
@@ -664,7 +672,7 @@ static void xhci_process_events(struct grub_xhci *x)
case ER_TRANSFER:
case ER_COMMAND_COMPLETE:
{
- struct grub_xhci_trb *rtrb = (void*)grub_xhci_read32(&etrb->ptr_low);
+ struct grub_xhci_trb *rtrb = grub_xhci_read_etrb_ptr(etrb);
struct grub_xhci_ring *ring = XHCI_RING(rtrb);
volatile struct grub_xhci_trb *evt = &ring->evt;
grub_uint32_t eidx = rtrb - ring->ring + 1;
@@ -697,9 +705,9 @@ static void xhci_process_events(struct grub_xhci *x)
}
grub_xhci_write32(&evts->nidx, nidx);
volatile struct grub_xhci_ir *ir = x->ir;
- grub_uint32_t erdp = (grub_uint32_t)(evts->ring + nidx);
- grub_xhci_write32(&ir->erdp_low, erdp);
- grub_xhci_write32(&ir->erdp_high, 0);
+ grub_uint64_t erdp = (grub_addr_t)(void *)(&evts->ring[nidx]);
+ grub_xhci_write32(&ir->erdp_low, erdp & 0xffffffff);
+ grub_xhci_write32(&ir->erdp_high, erdp >> 32);
}
}
@@ -800,7 +808,7 @@ static void xhci_trb_queue(volatile struct grub_xhci_ring *ring,
grub_uint32_t xferlen, grub_uint32_t flags)
{
grub_dprintf("xhci", "%s: ring %p data %llx len %d flags 0x%x remain 0x%x\n", __func__,
- ring, data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17);
+ ring, (unsigned long long)data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17);
if (xhci_ring_full(ring))
{
@@ -1907,7 +1915,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev,
if (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL)
{
volatile struct grub_usb_packet_setup *setupdata;
- setupdata = (void *)transfer->transactions[0].data;
+ setupdata = (void *)(grub_addr_t)transfer->transactions[0].data;
grub_dprintf("xhci", "%s: CONTROLL TRANS req %d\n", __func__, setupdata->request);
grub_dprintf("xhci", "%s: CONTROLL TRANS length %d\n", __func__, setupdata->length);
@@ -1974,7 +1982,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev,
/* Assume the ring has enough free space for all TRBs */
if (flags & TRB_TR_IDT && tr->size <= (int)sizeof(inline_data))
{
- grub_memcpy(&inline_data, (void *)tr->data, tr->size);
+ grub_memcpy(&inline_data, (void *)(grub_addr_t)tr->data, tr->size);
xhci_trb_queue(reqs, inline_data, tr->size, flags);
}
else
--
2.39.2