Nico Huber (nico.huber@secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1126
-gerrit
commit ac87dc97d32ca8c8cfa5aa163fbe7358b4dd3608 Author: Nico Huber nico.huber@secunet.com Date: Wed Jun 20 11:37:17 2012 +0200
libpayload: Fix initialization of OHCI driver
This fixes some memory corruption, leaking and padding issues within the initialization of the OHCI driver.
Change-Id: If6891f2a53e339d32c4324f4c9e0b1ed07596a60 Signed-off-by: Nico Huber nico.huber@secunet.com --- payloads/libpayload/drivers/usb/ohci.c | 14 +++++++++----- payloads/libpayload/drivers/usb/ohci_private.h | 22 ++++++++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c index be6d5e3..6d98cc1 100644 --- a/payloads/libpayload/drivers/usb/ohci.c +++ b/payloads/libpayload/drivers/usb/ohci.c @@ -129,17 +129,20 @@ ohci_init (pcidev_t addr) } int interval = OHCI_INST (controller)->opreg->HcFmInterval;
- td_t *periodic_td = memalign(sizeof(*periodic_td), sizeof(*periodic_td)); - memset((void*)periodic_td, 0, sizeof(*periodic_td)); - for (i=0; i<32; i++) OHCI_INST (controller)->hcca->HccaInterruptTable[i] = virt_to_phys(periodic_td); - /* TODO: build HCCA data structures */ - OHCI_INST (controller)->opreg->HcCommandStatus = HostControllerReset; udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */ OHCI_INST (controller)->opreg->HcFmInterval = interval; OHCI_INST (controller)->hcca = memalign(256, 256); memset((void*)OHCI_INST (controller)->hcca, 0, 256);
+ /* Initialize interrupt table. */ + u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable; + ed_t *const periodic_ed = memalign(sizeof(ed_t), sizeof(ed_t)); + memset((void *)periodic_ed, 0, sizeof(*periodic_ed)); + for (i = 0; i < 32; ++i) + intr_table[i] = virt_to_phys(periodic_ed); + OHCI_INST (controller)->periodic_ed = periodic_ed; + OHCI_INST (controller)->opreg->HcHCCA = virt_to_phys(OHCI_INST (controller)->hcca); OHCI_INST (controller)->opreg->HcControl &= ~IsochronousEnable; // unused by this driver // disable everything, contrary to what OHCI spec says in 5.1.1.4, as we don't need IRQs @@ -167,6 +170,7 @@ ohci_shutdown (hci_t *controller) ohci_stop(controller); OHCI_INST (controller)->roothub->destroy (OHCI_INST (controller)-> roothub); + free ((void *)OHCI_INST (controller)->periodic_ed); free (OHCI_INST (controller)); free (controller); } diff --git a/payloads/libpayload/drivers/usb/ohci_private.h b/payloads/libpayload/drivers/usb/ohci_private.h index 0bcae03..3826db0 100644 --- a/payloads/libpayload/drivers/usb/ohci_private.h +++ b/payloads/libpayload/drivers/usb/ohci_private.h @@ -189,22 +189,15 @@ volatile u32 HcRhPortStatus[]; } __attribute__ ((packed)) opreg_t;
- typedef struct { + typedef struct { /* should be 256 bytes according to spec */ u32 HccaInterruptTable[32]; volatile u16 HccaFrameNumber; volatile u16 HccaPad1; volatile u32 HccaDoneHead; - u8 reserved[116]; // pad to 256 byte + u8 reserved[116]; /* pad according to spec */ + u8 what[4]; /* really pad to 256 as spec only covers 252 */ } __attribute__ ((packed)) hcca_t;
- typedef struct ohci { - opreg_t *opreg; - hcca_t *hcca; - usbdev_t *roothub; - } ohci_t; - - typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; - typedef volatile struct { u32 config; u32 tail_pointer; @@ -259,4 +252,13 @@
#define OHCI_INST(controller) ((ohci_t*)((controller)->instance))
+ typedef struct ohci { + opreg_t *opreg; + hcca_t *hcca; + usbdev_t *roothub; + ed_t *periodic_ed; + } ohci_t; + + typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; + #endif