]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
MdeModulePkg UsbBusDxe: Fix wrong buffer length used to read hub desc
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
index 2dfc5751d55d032b3d45959ee8834f00bde4bb25..a962f76638e8bd5512e35d118e00a1cd4a051135 100644 (file)
@@ -2,7 +2,7 @@
 \r
     Unified interface for RootHub and Hub.\r
 \r
-Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR> \r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -201,43 +201,7 @@ UsbHubCtrlClearTTBuffer (
 }\r
 \r
 /**\r
-  Usb hub control transfer to get the super speed hub descriptor.\r
-\r
-  @param  HubDev                The hub device.\r
-  @param  Buf                   The buffer to hold the descriptor.\r
-  @param  Len                   The length to retrieve.\r
-\r
-  @retval EFI_SUCCESS           The hub descriptor is retrieved.\r
-  @retval Others                Failed to retrieve the hub descriptor.\r
-\r
-**/\r
-EFI_STATUS\r
-UsbHubCtrlGetSuperSpeedHubDesc (\r
-  IN  USB_DEVICE          *HubDev,\r
-  OUT VOID                *Buf\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  \r
-  Status = EFI_INVALID_PARAMETER;\r
-  \r
-  Status = UsbCtrlRequest (\r
-             HubDev,\r
-             EfiUsbDataIn,\r
-             USB_REQ_TYPE_CLASS,\r
-             USB_HUB_TARGET_HUB,\r
-             USB_HUB_REQ_GET_DESC,\r
-             (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),\r
-             0,\r
-             Buf,\r
-             32\r
-             );\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Usb hub control transfer to get the hub descriptor.\r
+  Usb hub control transfer to get the (super speed) hub descriptor.\r
 \r
   @param  HubDev                The hub device.\r
   @param  Buf                   The buffer to hold the descriptor.\r
@@ -255,6 +219,11 @@ UsbHubCtrlGetHubDesc (
   )\r
 {\r
   EFI_STATUS              Status;\r
+  UINT8                   DescType;\r
+\r
+  DescType = (HubDev->Speed == EFI_USB_SPEED_SUPER) ?\r
+             USB_DESC_TYPE_HUB_SUPER_SPEED :\r
+             USB_DESC_TYPE_HUB;\r
 \r
   Status = UsbCtrlRequest (\r
              HubDev,\r
@@ -262,7 +231,7 @@ UsbHubCtrlGetHubDesc (
              USB_REQ_TYPE_CLASS,\r
              USB_HUB_TARGET_HUB,\r
              USB_HUB_REQ_GET_DESC,\r
-             (UINT16) (USB_DESC_TYPE_HUB << 8),\r
+             (UINT16) (DescType << 8),\r
              0,\r
              Buf,\r
              Len\r
@@ -476,29 +445,19 @@ UsbHubReadDesc (
 {\r
   EFI_STATUS              Status;\r
 \r
-  if (HubDev->Speed == EFI_USB_SPEED_SUPER) {\r
-    //\r
-    // Get the super speed hub descriptor\r
-    //\r
-    Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);\r
-  } else {\r
-\r
-    //\r
-    // First get the hub descriptor length\r
-    //\r
-    Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+  //\r
+  // First get the hub descriptor length\r
+  //\r
+  Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
 \r
-    //\r
-    // Get the whole hub descriptor\r
-    //\r
-    Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
 \r
-  return Status;\r
+  //\r
+  // Get the whole hub descriptor\r
+  //\r
+  return UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
 }\r
 \r
 \r
@@ -691,7 +650,8 @@ UsbHubInit (
   IN USB_INTERFACE        *HubIf\r
   )\r
 {\r
-  EFI_USB_HUB_DESCRIPTOR  HubDesc;\r
+  UINT8                   HubDescBuffer[256];\r
+  EFI_USB_HUB_DESCRIPTOR  *HubDesc;\r
   USB_ENDPOINT_DESC       *EpDesc;\r
   USB_INTERFACE_SETTING   *Setting;\r
   EFI_USB_IO_PROTOCOL     *UsbIo;\r
@@ -726,14 +686,19 @@ UsbHubInit (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  Status = UsbHubReadDesc (HubDev, &HubDesc);\r
+  //\r
+  // The length field of descriptor is UINT8 type, so the buffer\r
+  // with 256 bytes is enough to hold the descriptor data.\r
+  //\r
+  HubDesc = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;\r
+  Status = UsbHubReadDesc (HubDev, HubDesc);\r
 \r
   if (EFI_ERROR (Status)) {\r
     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));\r
     return Status;\r
   }\r
 \r
-  HubIf->NumOfPort = HubDesc.NumPorts;\r
+  HubIf->NumOfPort = HubDesc->NumPorts;\r
 \r
   DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));\r
 \r
@@ -752,7 +717,7 @@ UsbHubInit (
     DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));\r
     UsbHubCtrlSetHubDepth (HubIf->Device, Depth);\r
     \r
-    for (Index = 0; Index < HubDesc.NumPorts; Index++) {\r
+    for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
       UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);\r
     }    \r
   } else {\r
@@ -760,11 +725,16 @@ UsbHubInit (
     // Feed power to all the hub ports. It should be ok\r
     // for both gang/individual powered hubs.\r
     //\r
-    for (Index = 0; Index < HubDesc.NumPorts; Index++) {\r
+    for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
       UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);\r
     }\r
 \r
-    gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
+    //\r
+    // Update for the usb hub has no power on delay requirement\r
+    //\r
+    if (HubDesc->PwrOn2PwrGood > 0) {\r
+      gBS->Stall (HubDesc->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
+    }\r
     UsbHubAckHubStatus (HubIf->Device);\r
   }\r
 \r
@@ -845,12 +815,6 @@ UsbHubGetPortStatus (
 \r
   Status  = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);\r
 \r
-  //\r
-  // Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed\r
-  //\r
-  if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {\r
-    PortState->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
-  } \r
   return Status;\r
 }\r
 \r
@@ -886,7 +850,7 @@ UsbHubClearPortChange (
   // It may lead to extra port state report. USB bus should\r
   // be able to handle this.\r
   //\r
-  for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {\r
+  for (Index = 0; Index < ARRAY_SIZE (mHubFeatureMap); Index++) {\r
     Map = &mHubFeatureMap[Index];\r
 \r
     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
@@ -977,22 +941,26 @@ UsbHubResetPort (
   }\r
 \r
   //\r
-  // Drive the reset signal for at least 10ms. Check USB 2.0 Spec\r
+  // Drive the reset signal for worst 20ms. Check USB 2.0 Spec\r
   // section 7.1.7.5 for timing requirements.\r
   //\r
   gBS->Stall (USB_SET_PORT_RESET_STALL);\r
 \r
   //\r
-  // USB hub will clear RESET bit if reset is actually finished.\r
+  // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.\r
   //\r
   ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
 \r
   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
     Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
 \r
-    if (!EFI_ERROR (Status) &&\r
-        !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
+    if (!EFI_ERROR (Status) &&\r
+        USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {\r
+      gBS->Stall (USB_SET_PORT_RECOVERY_STALL);\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -1178,7 +1146,7 @@ UsbRootHubClearPortChange (
   // It may lead to extra port state report. USB bus should\r
   // be able to handle this.\r
   //\r
-  for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {\r
+  for (Index = 0; Index < ARRAY_SIZE (mRootHubFeatureMap); Index++) {\r
     Map = &mRootHubFeatureMap[Index];\r
 \r
     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
@@ -1270,6 +1238,7 @@ UsbRootHubResetPort (
   // should be handled in the EHCI driver.\r
   //\r
   Bus     = RootIf->Device->Bus;\r
+\r
   Status  = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
 \r
   if (EFI_ERROR (Status)) {\r