]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbDesc.c
index 0e9ea1e4d329a1f0c8010c7cb4f80e755a8a467f..a64f33fde67a5aa066faf3c5bea5d38215155600 100644 (file)
@@ -2,14 +2,8 @@
 \r
     Manage Usb Descriptor List\r
 \r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -21,8 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
   @param  Setting               The descriptor to free.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbFreeInterfaceDesc (\r
@@ -40,14 +32,19 @@ UsbFreeInterfaceDesc (
       Ep = Setting->Endpoints[Index];\r
 \r
       if (Ep != NULL) {\r
-        gBS->FreePool (Ep);\r
+        FreePool (Ep);\r
       }\r
     }\r
 \r
-    gBS->FreePool (Setting->Endpoints);\r
+    //\r
+    // Only call FreePool() if NumEndpoints > 0.\r
+    //\r
+    if (Setting->Desc.NumEndpoints > 0) {\r
+      FreePool (Setting->Endpoints);\r
+    }\r
   }\r
 \r
-  gBS->FreePool (Setting);\r
+  FreePool (Setting);\r
 }\r
 \r
 \r
@@ -57,8 +54,6 @@ UsbFreeInterfaceDesc (
 \r
   @param  Config                The configuration descriptor to free.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbFreeConfigDesc (\r
@@ -89,13 +84,13 @@ UsbFreeConfigDesc (
         }\r
       }\r
 \r
-      gBS->FreePool (Interface);\r
+      FreePool (Interface);\r
     }\r
 \r
-    gBS->FreePool (Config->Interfaces);\r
+    FreePool (Config->Interfaces);\r
   }\r
 \r
-  gBS->FreePool (Config);\r
+  FreePool (Config);\r
 \r
 }\r
 \r
@@ -105,8 +100,6 @@ UsbFreeConfigDesc (
 \r
   @param  DevDesc               The device descriptor.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbFreeDevDesc (\r
@@ -122,10 +115,10 @@ UsbFreeDevDesc (
       }\r
     }\r
 \r
-    gBS->FreePool (DevDesc->Configs);\r
+    FreePool (DevDesc->Configs);\r
   }\r
 \r
-  gBS->FreePool (DevDesc);\r
+  FreePool (DevDesc);\r
 }\r
 \r
 \r
@@ -133,7 +126,7 @@ UsbFreeDevDesc (
   Create a descriptor.\r
 \r
   @param  DescBuf               The buffer of raw descriptor.\r
-  @param  Len                   The lenght of the raw descriptor buffer.\r
+  @param  Len                   The length of the raw descriptor buffer.\r
   @param  Type                  The type of descriptor to create.\r
   @param  Consumed              Number of bytes consumed.\r
 \r
@@ -143,15 +136,15 @@ UsbFreeDevDesc (
 VOID *\r
 UsbCreateDesc (\r
   IN  UINT8               *DescBuf,\r
-  IN  INTN                Len,\r
+  IN  UINTN               Len,\r
   IN  UINT8               Type,\r
-  OUT INTN                *Consumed\r
+  OUT UINTN               *Consumed\r
   )\r
 {\r
   USB_DESC_HEAD           *Head;\r
-  INTN                    DescLen;\r
-  INTN                    CtrlLen;\r
-  INTN                    Offset;\r
+  UINTN                   DescLen;\r
+  UINTN                   CtrlLen;\r
+  UINTN                   Offset;\r
   VOID                    *Desc;\r
 \r
   DescLen   = 0;\r
@@ -178,6 +171,18 @@ UsbCreateDesc (
     DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
     CtrlLen = sizeof (USB_ENDPOINT_DESC);\r
     break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Total length is too small that cannot hold the single descriptor header plus data.\r
+  //\r
+  if (Len <= sizeof (USB_DESC_HEAD)) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, total length = %d!\n", Len));\r
+    return NULL;\r
   }\r
 \r
   //\r
@@ -185,37 +190,65 @@ UsbCreateDesc (
   // format. Skip the descriptor that isn't of this Type\r
   //\r
   Offset = 0;\r
-  Head   = (USB_DESC_HEAD*)DescBuf;\r
+  Head   = (USB_DESC_HEAD *)DescBuf;\r
+  while (Offset < Len - sizeof (USB_DESC_HEAD)) {\r
+    //\r
+    // Above condition make sure Head->Len and Head->Type are safe to access\r
+    //\r
+    Head = (USB_DESC_HEAD *)&DescBuf[Offset];\r
+\r
+    if (Head->Len == 0) {\r
+      DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Head->Len = 0!\n"));\r
+      return NULL;\r
+    }\r
+\r
+    //\r
+    // Make sure no overflow when adding Head->Len to Offset.\r
+    //\r
+    if (Head->Len > MAX_UINTN - Offset) {\r
+      DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
+      return NULL;\r
+    }\r
 \r
-  while ((Offset < Len) && (Head->Type != Type)) {\r
     Offset += Head->Len;\r
-    Head    = (USB_DESC_HEAD*)(DescBuf + Offset);\r
+\r
+    if (Head->Type == Type) {\r
+      break;\r
+    }\r
   }\r
 \r
-  if ((Len <= Offset)      || (Len < Offset + DescLen) ||\r
-      (Head->Type != Type) || (Head->Len != DescLen)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));\r
+  //\r
+  // Head->Len is invalid resulting data beyond boundary, or\r
+  // Descriptor cannot be found: No such type.\r
+  //\r
+  if (Len < Offset) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Len));\r
     return NULL;\r
   }\r
 \r
-  Desc = AllocateZeroPool (CtrlLen);\r
+  if ((Head->Type != Type) || (Head->Len < DescLen)) {\r
+    DEBUG ((DEBUG_ERROR, "UsbCreateDesc: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
+    return NULL;\r
+  }\r
 \r
+  Desc = AllocateZeroPool ((UINTN) CtrlLen);\r
   if (Desc == NULL) {\r
     return NULL;\r
   }\r
 \r
-  CopyMem (Desc, Head, DescLen);\r
-  *Consumed = Offset + Head->Len;\r
+  CopyMem (Desc, Head, (UINTN) DescLen);\r
+\r
+  *Consumed = Offset;\r
 \r
   return Desc;\r
 }\r
 \r
 \r
 /**\r
-  Parse an interface desciptor and its endpoints.\r
+  Parse an interface descriptor and its endpoints.\r
 \r
   @param  DescBuf               The buffer of raw descriptor.\r
-  @param  Len                   The lenght of the raw descriptor buffer.\r
+  @param  Len                   The length of the raw descriptor buffer.\r
   @param  Consumed              The number of raw descriptor consumed.\r
 \r
   @return The create interface setting or NULL if failed.\r
@@ -224,16 +257,16 @@ UsbCreateDesc (
 USB_INTERFACE_SETTING *\r
 UsbParseInterfaceDesc (\r
   IN  UINT8               *DescBuf,\r
-  IN  INTN                Len,\r
-  OUT INTN                *Consumed\r
+  IN  UINTN               Len,\r
+  OUT UINTN               *Consumed\r
   )\r
 {\r
   USB_INTERFACE_SETTING   *Setting;\r
   USB_ENDPOINT_DESC       *Ep;\r
   UINTN                   Index;\r
   UINTN                   NumEp;\r
-  INTN                    Used;\r
-  INTN                    Offset;\r
+  UINTN                   Used;\r
+  UINTN                   Offset;\r
 \r
   *Consumed = 0;\r
   Setting   = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);\r
@@ -246,7 +279,7 @@ UsbParseInterfaceDesc (
   Offset = Used;\r
 \r
   //\r
-  // Create an arry to hold the interface's endpoints\r
+  // Create an array to hold the interface's endpoints\r
   //\r
   NumEp  = Setting->Desc.NumEndpoints;\r
 \r
@@ -266,7 +299,7 @@ UsbParseInterfaceDesc (
   //\r
   // Create the endpoints for this interface\r
   //\r
-  for (Index = 0; Index < NumEp; Index++) {\r
+  for (Index = 0; (Index < NumEp) && (Offset < Len); Index++) {\r
     Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);\r
 \r
     if (Ep == NULL) {\r
@@ -293,7 +326,7 @@ ON_ERROR:
   Parse the configuration descriptor and its interfaces.\r
 \r
   @param  DescBuf               The buffer of raw descriptor.\r
-  @param  Len                   The lenght of the raw descriptor buffer.\r
+  @param  Len                   The length of the raw descriptor buffer.\r
 \r
   @return The created configuration descriptor.\r
 \r
@@ -301,7 +334,7 @@ ON_ERROR:
 USB_CONFIG_DESC *\r
 UsbParseConfigDesc (\r
   IN UINT8                *DescBuf,\r
-  IN INTN                 Len\r
+  IN UINTN                Len\r
   )\r
 {\r
   USB_CONFIG_DESC         *Config;\r
@@ -309,7 +342,7 @@ UsbParseConfigDesc (
   USB_INTERFACE_DESC      *Interface;\r
   UINTN                   Index;\r
   UINTN                   NumIf;\r
-  INTN                    Consumed;\r
+  UINTN                   Consumed;\r
 \r
   ASSERT (DescBuf != NULL);\r
 \r
@@ -353,12 +386,16 @@ UsbParseConfigDesc (
   DescBuf += Consumed;\r
   Len     -= Consumed;\r
 \r
-  while (Len > 0) {\r
+  //\r
+  // Make allowances for devices that return extra data at the\r
+  // end of their config descriptors\r
+  //\r
+  while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {\r
     Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);\r
 \r
-    if ((Setting == NULL)) {\r
-      DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));\r
-      goto ON_ERROR;\r
+    if (Setting == NULL) {\r
+      DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));\r
+      break;\r
 \r
     } else if (Setting->Desc.InterfaceNumber >= NumIf) {\r
       DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));\r
@@ -524,12 +561,14 @@ UsbGetMaxPacketSize0 (
   // Get the first 8 bytes of the device descriptor which contains\r
   // max packet size for endpoint 0, which is at least 8.\r
   //\r
-  UsbDev->MaxPacket0 = 8;\r
-\r
   for (Index = 0; Index < 3; Index++) {\r
     Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);\r
 \r
     if (!EFI_ERROR (Status)) {\r
+      if ((DevDesc.BcdUSB >= 0x0300) && (DevDesc.MaxPacketSize0 == 9)) {\r
+        UsbDev->MaxPacket0 = 1 << 9;\r
+        return EFI_SUCCESS;\r
+      }\r
       UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;\r
       return EFI_SUCCESS;\r
     }\r
@@ -611,7 +650,13 @@ UsbGetOneString (
   //\r
   Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);\r
 \r
-  if (EFI_ERROR (Status)) {\r
+  //\r
+  // Reject if Length even cannot cover itself, or odd because Unicode string byte length should be even.\r
+  //\r
+  if (EFI_ERROR (Status) ||\r
+      (Desc.Length < OFFSET_OF (EFI_USB_STRING_DESCRIPTOR, Length) + sizeof (Desc.Length)) ||\r
+      (Desc.Length % 2 != 0)\r
+    ) {\r
     return NULL;\r
   }\r
 \r
@@ -631,7 +676,7 @@ UsbGetOneString (
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (Buf);\r
+    FreePool (Buf);\r
     return NULL;\r
   }\r
 \r
@@ -675,7 +720,7 @@ UsbBuildLangTable (
   Status = EFI_SUCCESS;\r
 \r
   Max   = (Desc->Length - 2) / 2;\r
-  Max   = (Max < USB_MAX_LANG_ID ? Max : USB_MAX_LANG_ID);\r
+  Max   = MIN(Max, USB_MAX_LANG_ID);\r
 \r
   Point = Desc->String;\r
   for (Index = 0; Index < Max; Index++) {\r
@@ -693,7 +738,7 @@ ON_EXIT:
 \r
 /**\r
   Retrieve the indexed configure for the device. USB device\r
-  returns the configuration togetther with the interfaces for\r
+  returns the configuration together with the interfaces for\r
   this configuration. Configuration descriptor is also of\r
   variable length.\r
 \r
@@ -728,6 +773,13 @@ UsbGetOneConfig (
 \r
   DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));\r
 \r
+  //\r
+  // Reject if TotalLength even cannot cover itself.\r
+  //\r
+  if (Desc.TotalLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (Desc.TotalLength)) {\r
+    return NULL;\r
+  }\r
+\r
   Buf = AllocateZeroPool (Desc.TotalLength);\r
 \r
   if (Buf == NULL) {\r
@@ -739,7 +791,7 @@ UsbGetOneConfig (
   if (EFI_ERROR (Status)) {\r
     DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status));\r
 \r
-    gBS->FreePool (Buf);\r
+    FreePool (Buf);\r
     return NULL;\r
   }\r
 \r
@@ -781,10 +833,13 @@ UsbBuildDescTable (
     return Status;\r
   }\r
 \r
-  DevDesc          = UsbDev->DevDesc;\r
-  NumConfig        = DevDesc->Desc.NumConfigurations;\r
-  DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));\r
+  DevDesc   = UsbDev->DevDesc;\r
+  NumConfig = DevDesc->Desc.NumConfigurations;\r
+  if (NumConfig == 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 \r
+  DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));\r
   if (DevDesc->Configs == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -813,7 +868,7 @@ UsbBuildDescTable (
 \r
     ConfigDesc = UsbParseConfigDesc ((UINT8 *) Config, Config->TotalLength);\r
 \r
-    gBS->FreePool (Config);\r
+    FreePool (Config);\r
 \r
     if (ConfigDesc == NULL) {\r
       DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index));\r
@@ -839,7 +894,7 @@ UsbBuildDescTable (
   Status = UsbBuildLangTable (UsbDev);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: get language ID table %r\n", Status));\r
+    DEBUG (( EFI_D_INFO, "UsbBuildDescTable: get language ID table %r\n", Status));\r
   }\r
 \r
   return EFI_SUCCESS;\r