]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
MdeModulePkg/XhciDxe: Add boundary check for TRB ring allocation
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / UsbHcMem.c
index 99fb3521d56be80bd0ae827061042ee8560c734c..d0ad1582e4ea81a482bd90ed8c75d50e6b381ff7 100644 (file)
@@ -132,8 +132,9 @@ UsbHcFreeMemBlock (
 /**\r
   Alloc some memory from the block.\r
 \r
-  @param  Block          The memory block to allocate memory from.\r
-  @param  Units          Number of memory units to allocate.\r
+  @param  Block                The memory block to allocate memory from.\r
+  @param  Units                Number of memory units to allocate.\r
+  @param  AllocationForRing    The allocated memory is for Ring or not.\r
 \r
   @return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
           the return value is NULL.\r
@@ -142,7 +143,8 @@ UsbHcFreeMemBlock (
 VOID *\r
 UsbHcAllocMemFromBlock (\r
   IN  USBHC_MEM_BLOCK  *Block,\r
-  IN  UINTN            Units\r
+  IN  UINTN            Units,\r
+  IN  BOOLEAN          AllocationForRing\r
   )\r
 {\r
   UINTN  Byte;\r
@@ -151,12 +153,15 @@ UsbHcAllocMemFromBlock (
   UINT8  StartBit;\r
   UINTN  Available;\r
   UINTN  Count;\r
+  UINTN  MemUnitAddr;\r
+  UINTN  AlignmentMask;\r
 \r
   ASSERT ((Block != 0) && (Units != 0));\r
 \r
-  StartByte = 0;\r
-  StartBit  = 0;\r
-  Available = 0;\r
+  StartByte     = 0;\r
+  StartBit      = 0;\r
+  Available     = 0;\r
+  AlignmentMask = ~((UINTN)USBHC_MEM_TRB_RINGS_BOUNDARY - 1);\r
 \r
   for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
     //\r
@@ -165,6 +170,20 @@ UsbHcAllocMemFromBlock (
     // Available counts the consective number of zero bit.\r
     //\r
     if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
+      if (AllocationForRing && (Available != 0)) {\r
+        MemUnitAddr = (UINTN)Block->BufHost + (Byte * 8 + Bit) * USBHC_MEM_UNIT;\r
+        if ((MemUnitAddr & AlignmentMask) != ((MemUnitAddr - USBHC_MEM_UNIT) & AlignmentMask)) {\r
+          //\r
+          // If the TRB Ring memory cross 64K-byte boundary, then restart the\r
+          // search starting at current memory unit.\r
+          // Doing so is to meet the TRB Ring boundary requirement in XHCI spec.\r
+          //\r
+          Available = 0;\r
+          StartByte = Byte;\r
+          StartBit  = Bit;\r
+        }\r
+      }\r
+\r
       Available++;\r
 \r
       if (Available >= Units) {\r
@@ -438,8 +457,9 @@ UsbHcFreeMemPool (
   Allocate some memory from the host controller's memory pool\r
   which can be used to communicate with host controller.\r
 \r
-  @param  Pool           The host controller's memory pool.\r
-  @param  Size           Size of the memory to allocate.\r
+  @param  Pool                 The host controller's memory pool.\r
+  @param  Size                 Size of the memory to allocate.\r
+  @param  AllocationForRing    The allocated memory is for Ring or not.\r
 \r
   @return The allocated memory or NULL.\r
 \r
@@ -447,7 +467,8 @@ UsbHcFreeMemPool (
 VOID *\r
 UsbHcAllocateMem (\r
   IN  USBHC_MEM_POOL  *Pool,\r
-  IN  UINTN           Size\r
+  IN  UINTN           Size,\r
+  IN  BOOLEAN         AllocationForRing\r
   )\r
 {\r
   USBHC_MEM_BLOCK  *Head;\r
@@ -466,7 +487,7 @@ UsbHcAllocateMem (
   // First check whether current memory blocks can satisfy the allocation.\r
   //\r
   for (Block = Head; Block != NULL; Block = Block->Next) {\r
-    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
+    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
 \r
     if (Mem != NULL) {\r
       ZeroMem (Mem, Size);\r
@@ -501,7 +522,7 @@ UsbHcAllocateMem (
   // Add the new memory block to the pool, then allocate memory from it\r
   //\r
   UsbHcInsertMemBlockToPool (Head, NewBlock);\r
-  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
+  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
 \r
   if (Mem != NULL) {\r
     ZeroMem (Mem, Size);\r