Nico Huber (nico.h@gmx.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3467
-gerrit
commit 7ae94034ef8e81b41151d8817d2a4cfc4119f995 Author: Anton Kochkov anton.kochkov@gmail.com Date: Fri Jun 14 19:41:48 2013 +0400
libpayload: usb: Deep search for endpoint descriptors
This improves searching for endpoint descriptors and skipping non-endpoint interface descriptors.
Change-Id: I063c096ab886f9753a9ee59f570fd81ce6f618cb Signed-off-by: Anton Kochkov anton.kochkov@gmail.com Signed-off-by: Nico Huber nico.huber@secunet.com --- payloads/libpayload/drivers/usb/usb.c | 54 ++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-)
diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c index 2d9cbe9..6a1d5bb 100644 --- a/payloads/libpayload/drivers/usb/usb.c +++ b/payloads/libpayload/drivers/usb/usb.c @@ -320,6 +320,30 @@ usb_decode_interval(const int speed, const endpoint_type type, const unsigned ch #undef LOG2 }
+static const endpoint_descriptor_t * +next_endpoint(const u8 *start, const u8 *const end) +{ + for (start += start[0]; + start < end && start[1] != 0x04 && start[1] != 0x05; + start += start[0]); + if (start < end && start[1] == 0x05) + return (const endpoint_descriptor_t *)start; + else + return NULL; +} + +static const interface_descriptor_t * +next_interface(const u8 *start, const u8 *const end) +{ + for (start += start[0]; + start < end && start[1] != 0x04; + start += start[0]); + if (start < end && start[1] == 0x04) + return (const interface_descriptor_t *)start; + else + return NULL; +} + static int set_address (hci_t *controller, int speed, int hubport, int hubaddr) { @@ -329,6 +353,7 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) return -1; } configuration_descriptor_t *cd; + const u8 *cd_end; device_descriptor_t *dd;
usbdev_t *dev = controller->devices[adr]; @@ -356,12 +381,12 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) dev->configuration = get_descriptor (dev, gen_bmRequestType (device_to_host, standard_type, dev_recp), 2, 0, 0); cd = (configuration_descriptor_t *) dev->configuration; + cd_end = dev->configuration + cd->wTotalLength; interface_descriptor_t *interface = (interface_descriptor_t *) (((char *) cd) + cd->bLength); { int i; int num = cd->bNumInterfaces; - interface_descriptor_t *current = interface; usb_debug ("device has %x interfaces\n", num); if (num > 1) { int interfaces = usb_interface_check(dd->idVendor, dd->idProduct); @@ -382,17 +407,18 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) num = (num > 1) ? 1 : num; } } + const interface_descriptor_t *current = + (const interface_descriptor_t *)cd; for (i = 0; i < num; i++) { + current = next_interface((const u8 *)current, cd_end); + if (!current) { + usb_detach_device(controller, adr); + return -1; + } + int j; usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n", current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); - endpoint_descriptor_t *endp = - (endpoint_descriptor_t *) (((char *) current) - + current->bLength); - /* Skip any non-endpoint descriptor */ - if (endp->bDescriptorType != 0x05) - endp = (endpoint_descriptor_t *)(((char *)endp) + ((char *)endp)[0]); - memset (dev->endpoints, 0, sizeof (dev->endpoints)); dev->num_endp = 1; // 0 always exists dev->endpoints[0].dev = dev; @@ -400,7 +426,15 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) dev->endpoints[0].direction = SETUP; dev->endpoints[0].type = CONTROL; dev->endpoints[0].interval = 0; + + const endpoint_descriptor_t *endp = + (const endpoint_descriptor_t *)current; for (j = 1; j <= current->bNumEndpoints; j++) { + endp = next_endpoint((const u8 *)endp, cd_end); + if (!endp) { + usb_detach_device(controller, adr); + return -1; + } #ifdef USB_DEBUG static const char *transfertypes[4] = { "control", "isochronous", "bulk", "interrupt" @@ -418,10 +452,8 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) 0) ? OUT : IN; ep->type = endp->bmAttributes; ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval); - endp = (endpoint_descriptor_t - *) (((char *) endp) + endp->bLength); } - current = (interface_descriptor_t *) endp; + current = (const interface_descriptor_t *)endp; } }