]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c
Add DevicePathUtilities DevicePathToText DevciePathFromText USB2HostController protocols
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Ehci / Dxe / EhciMem.c
diff --git a/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c b/EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciMem.c
new file mode 100644 (file)
index 0000000..2f35f77
--- /dev/null
@@ -0,0 +1,761 @@
+/*++\r
+\r
+Copyright (c) 2006, 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
+\r
+Module Name:\r
+\r
+    EhciMem.c\r
+    \r
+Abstract: \r
+    \r
+\r
+Revision History\r
+--*/\r
+\r
+#include "Ehci.h"\r
+\r
+\r
+EFI_STATUS\r
+CreateMemoryBlock (\r
+  IN  USB2_HC_DEV               *HcDev,\r
+  OUT MEMORY_MANAGE_HEADER      **MemoryHeader,\r
+  IN  UINTN                     MemoryBlockSizeInPages\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Use PciIo->AllocateBuffer to allocate common buffer for the memory block,\r
+  and use PciIo->Map to map the common buffer for Bus Master Read/Write.\r
+\r
+Arguments:\r
+\r
+  HcDev                  - USB2_HC_DEV\r
+  MemoryHeader           - MEMORY_MANAGE_HEADER to output\r
+  MemoryBlockSizeInPages - MemoryBlockSizeInPages\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS           Success\r
+  EFI_OUT_OF_RESOURCES  Fail for no resources\r
+  EFI_UNSUPPORTED       Unsupported currently\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  VOID                  *CommonBuffer;\r
+  EFI_PHYSICAL_ADDRESS  MappedAddress;\r
+  UINTN                 MemoryBlockSizeInBytes;\r
+  VOID                  *Mapping;\r
+\r
+  //\r
+  // Allocate memory for MemoryHeader\r
+  //\r
+  *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));\r
+  if (*MemoryHeader == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  (*MemoryHeader)->Next = NULL;\r
+\r
+  //\r
+  // set Memory block size\r
+  //\r
+  (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
+\r
+  //\r
+  // each bit in Bit Array will manage 32 bytes memory in memory block\r
+  //\r
+  (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8;\r
+\r
+  //\r
+  // Allocate memory for BitArray\r
+  //\r
+  (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);\r
+  if ((*MemoryHeader)->BitArrayPtr == NULL) {\r
+    gBS->FreePool (*MemoryHeader);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  //\r
+  // Memory Block uses MemoryBlockSizeInPages pages,\r
+  // and it is allocated as common buffer use.\r
+  //\r
+  Status = HcDev->PciIo->AllocateBuffer (\r
+                           HcDev->PciIo,\r
+                           AllocateAnyPages,\r
+                           EfiBootServicesData,\r
+                           MemoryBlockSizeInPages,\r
+                           &CommonBuffer,\r
+                           0\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
+    gBS->FreePool (*MemoryHeader);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
+  Status = HcDev->PciIo->Map (\r
+                           HcDev->PciIo,\r
+                           EfiPciIoOperationBusMasterCommonBuffer,\r
+                           CommonBuffer,\r
+                           &MemoryBlockSizeInBytes,\r
+                           &MappedAddress,\r
+                           &Mapping\r
+                           );\r
+  //\r
+  // If returned Mapped size is less than the size \r
+  // we request,do not support.\r
+  //\r
+  if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {\r
+    HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
+    gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
+    gBS->FreePool (*MemoryHeader);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  //\r
+  // Data structure involved by host controller \r
+  // should be restricted into the same 4G\r
+  //\r
+  if (HcDev->Is64BitCapable != 0) {\r
+       if (HcDev->High32BitAddr != GET_32B_TO_63B (MappedAddress)) {\r
+         HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);\r
+      HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
+      gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
+      gBS->FreePool (*MemoryHeader);\r
+      return EFI_UNSUPPORTED;\r
+       }\r
+  }\r
+  \r
+  //\r
+  // Set Memory block initial address\r
+  //\r
+  (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);\r
+  (*MemoryHeader)->Mapping        = Mapping;\r
+\r
+  ZeroMem (\r
+    (*MemoryHeader)->MemoryBlockPtr,\r
+    EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeMemoryHeader (\r
+  IN USB2_HC_DEV               *HcDev,\r
+  IN MEMORY_MANAGE_HEADER      *MemoryHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Free Memory Header\r
+\r
+Arguments:\r
+\r
+  HcDev         - USB2_HC_DEV\r
+  MemoryHeader  - MemoryHeader to be freed\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            Success\r
+  EFI_INVALID_PARAMETER  Parameter is error\r
+\r
+--*/\r
+{\r
+  if ((MemoryHeader == NULL) || (HcDev == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // unmap the common buffer used by the memory block\r
+  //\r
+  HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);\r
+\r
+  //\r
+  // free common buffer\r
+  //\r
+  HcDev->PciIo->FreeBuffer (\r
+                  HcDev->PciIo,\r
+                  EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),\r
+                  MemoryHeader->MemoryBlockPtr\r
+                  );\r
+  //\r
+  // free bit array\r
+  //\r
+  gBS->FreePool (MemoryHeader->BitArrayPtr);\r
+  //\r
+  // free memory header\r
+  //\r
+  gBS->FreePool (MemoryHeader);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EhciAllocatePool (\r
+  IN  USB2_HC_DEV     *HcDev,\r
+  OUT UINT8           **Pool,\r
+  IN  UINTN           AllocSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Ehci Allocate Pool\r
+\r
+Arguments:\r
+\r
+  HcDev     - USB2_HC_DEV\r
+  Pool      - Place to store pointer to the memory buffer\r
+  AllocSize - Alloc Size\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+\r
+--*/\r
+{\r
+  MEMORY_MANAGE_HEADER  *MemoryHeader;\r
+  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+  MEMORY_MANAGE_HEADER  *NewMemoryHeader;\r
+  UINTN                 RealAllocSize;\r
+  UINTN                 MemoryBlockSizeInPages;\r
+  EFI_STATUS            Status;\r
+  EFI_TPL               OldTpl;\r
+\r
+  *Pool         = NULL;\r
+\r
+  MemoryHeader  = HcDev->MemoryHeader;\r
+  ASSERT (MemoryHeader != NULL);\r
+\r
+  OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
+  \r
+  //\r
+  // allocate unit is 32 bytes (align on 32 byte)\r
+  //\r
+  if (AllocSize & 0x1F) {\r
+    RealAllocSize = (AllocSize / 32 + 1) * 32;\r
+  } else {\r
+    RealAllocSize = AllocSize;\r
+  }\r
+  \r
+  //\r
+  // There may be linked MemoryHeaders.\r
+  // To allocate a free pool in Memory blocks,\r
+  // must search in the MemoryHeader link list\r
+  // until enough free pool is found.\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+  for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
+\r
+    Status = AllocMemInMemoryBlock (\r
+              TempHeaderPtr,\r
+              Pool,\r
+              RealAllocSize / 32\r
+              );\r
+    if (!EFI_ERROR (Status)) {\r
+      ZeroMem (*Pool, AllocSize);\r
+      gBS->RestoreTPL (OldTpl);\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  \r
+  //\r
+  // There is no enough memory,\r
+  // Create a new Memory Block\r
+  //\r
+  \r
+  //\r
+  // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,\r
+  // just allocate a large enough memory block.\r
+  //\r
+  if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {\r
+    MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;\r
+  } else {\r
+    MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
+  }\r
+\r
+  Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r\r
+       \r
+  //\r
+  // Link the new Memory Block to the Memory Header list\r
+  //\r
+  InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);\r
+\r
+  Status = AllocMemInMemoryBlock (\r
+             NewMemoryHeader,\r
+             Pool,\r
+             RealAllocSize / 32\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    ZeroMem (*Pool, AllocSize);\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+VOID\r
+EhciFreePool (\r
+  IN USB2_HC_DEV     *HcDev,\r
+  IN UINT8           *Pool,\r
+  IN UINTN           AllocSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Uhci Free Pool\r
+\r
+Arguments:\r
+\r
+  HcDev     - USB_HC_DEV\r
+  Pool      - Pool to free\r
+  AllocSize - Pool size\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  MEMORY_MANAGE_HEADER  *MemoryHeader;\r
+  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+  UINTN                 StartBytePos;\r
+  UINTN                 Index;\r
+  UINT8                 StartBitPos;\r
+  UINT8                 Index2;\r
+  UINTN                 Count;\r
+  UINTN                 RealAllocSize;\r
+  EFI_TPL               OldTpl;\r
+\r
+  OldTpl        = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
+\r
+  MemoryHeader  = HcDev->MemoryHeader;\r
+\r
+  //\r
+  // allocate unit is 32 byte (align on 32 byte)\r
+  //\r
+  if (AllocSize & 0x1F) {\r
+    RealAllocSize = (AllocSize / 32 + 1) * 32;\r
+  } else {\r
+    RealAllocSize = AllocSize;\r
+  }\r
+  \r
+  //\r
+  // scan the memory header linked list for\r
+  // the asigned memory to free.\r
+  //\r
+  for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
+\r
+    if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&\r
+        ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))\r
+        ) {\r
+      //\r
+      // Pool is in the Memory Block area,\r
+      // find the start byte and bit in the bit array\r
+      //\r
+      StartBytePos  = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;\r
+      StartBitPos   = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);\r
+\r
+      //\r
+      // reset associated bits in bit arry\r
+      //\r
+      for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {\r
+        TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));\r
+        Index2++;\r
+        if (Index2 == 8) {\r
+          Index += 1;\r
+          Index2 = 0;\r
+        }\r
+      }\r
+      //\r
+      // break the loop\r
+      //\r
+      break;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Release emptied memory blocks (only if the memory block is not\r
+  // the first one in the memory header list\r
+  //\r
+  for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
+\r
+    ASSERT (MemoryHeader->Next != NULL);\r
+\r
+    if (IsMemoryBlockEmptied (TempHeaderPtr)) {\r
+\r
+      DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);\r
+      //\r
+      // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
+      // the TempHeaderPtr is pointing to nonsense content.\r
+      //\r
+      gBS->RestoreTPL (OldTpl);\r
+      FreeMemoryHeader (HcDev, TempHeaderPtr);\r
+      OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);\r
+      //\r
+      // reset the TempHeaderPtr, continue search for\r
+      // another empty memory block.\r
+      //\r
+      TempHeaderPtr = MemoryHeader->Next;\r
+      continue;\r
+    }\r
+\r
+    TempHeaderPtr = TempHeaderPtr->Next;\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+}\r
+\r
+VOID\r
+InsertMemoryHeaderToList (\r
+  IN MEMORY_MANAGE_HEADER     *MemoryHeader,\r
+  IN MEMORY_MANAGE_HEADER     *NewMemoryHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Insert Memory Header To List\r
+\r
+Arguments:\r
+\r
+  MemoryHeader    - MEMORY_MANAGE_HEADER\r
+  NewMemoryHeader - MEMORY_MANAGE_HEADER\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+\r
+  for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
+    if (TempHeaderPtr->Next == NULL) {\r
+      TempHeaderPtr->Next = NewMemoryHeader;\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+AllocMemInMemoryBlock (\r
+  IN  MEMORY_MANAGE_HEADER     *MemoryHeader,\r
+  OUT VOID                     **Pool,\r
+  IN  UINTN                    NumberOfMemoryUnit\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Alloc Memory In MemoryBlock\r
+\r
+Arguments:\r
+\r
+  MemoryHeader        - MEMORY_MANAGE_HEADER\r
+  Pool                - Place to store pointer to memory\r
+  NumberOfMemoryUnit  - Number Of Memory Unit\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS    Success\r
+  EFI_NOT_FOUND  Can't find the free memory \r
+\r
+--*/\r
+{\r
+  UINTN TempBytePos;\r
+  UINTN FoundBytePos;\r
+  UINT8 Index;\r
+  UINT8 FoundBitPos;\r
+  UINT8 ByteValue;\r
+  UINT8 BitValue;\r
+  UINTN NumberOfZeros;\r
+  UINTN Count;\r
+\r
+  FoundBytePos  = 0;\r
+  FoundBitPos   = 0;\r
+  ByteValue     = MemoryHeader->BitArrayPtr[0];\r
+  NumberOfZeros = 0;\r
+  Index         = 0;\r
+\r
+  for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {\r
+       \r
+    //\r
+    // Pop out BitValue from a byte in TempBytePos.\r
+    //\r
+    BitValue = (UINT8) (ByteValue & 0x1);\r
+       \r
+    //\r
+    // right shift the byte\r
+    //\r
+    ByteValue /= 2;\r
+\r
+    if (BitValue == 0) {\r
+      //\r
+      // Found a free bit, the NumberOfZeros only record the number\r
+      // of those consecutive zeros\r
+      //\r
+      NumberOfZeros++;\r
+      //\r
+      // Found enough consecutive free space, break the loop\r
+      //\r
+      if (NumberOfZeros >= NumberOfMemoryUnit) {\r
+        break;\r
+      }\r
+    } else {\r
+      //\r
+      // Encountering a '1', meant the bit is ocupied.\r
+      //\r
+      if (NumberOfZeros >= NumberOfMemoryUnit) {\r
+        //\r
+        // Found enough consecutive free space,break the loop\r
+        //\r
+        break;\r
+      } else {\r
+        //\r
+        // the NumberOfZeros only record the number of those consecutive zeros,\r
+        // so reset the NumberOfZeros to 0 when encountering '1' before finding\r
+        // enough consecutive '0's\r
+        //\r
+        NumberOfZeros = 0;\r
+        //\r
+        // reset the (FoundBytePos,FoundBitPos) to the position of '1'\r
+        //\r
+        FoundBytePos  = TempBytePos;\r
+        FoundBitPos   = Index;\r
+      }\r
+    }\r
+       \r
+    //\r
+    // step forward a bit\r
+    //\r
+    Index++;\r
+    if (Index == 8) {\r
+      //\r
+      // step forward a byte, getting the byte value,\r
+      // and reset the bit pos.\r
+      //\r
+      TempBytePos += 1;\r
+      ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];\r
+      Index     = 0;\r
+    }\r
+  }\r
+\r
+  if (NumberOfZeros < NumberOfMemoryUnit) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  //\r
+  // Found enough free space.\r
+  //\r
+  \r
+  //\r
+  // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:\r
+  //  1)(FoundBytePos,FoundBitPos) record the position\r
+  //    of the last '1' before the consecutive '0's, it must\r
+  //    be adjusted to the start position of the consecutive '0's.\r
+  //  2)the start address of the consecutive '0's is just the start of\r
+  //    the bitarray. so no need to adjust the values of\r
+  //    (FoundBytePos,FoundBitPos).\r
+  //\r
+  if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) {\r
+    FoundBitPos += 1;\r
+  }\r
+  \r
+  //\r
+  // Have the (FoundBytePos,FoundBitPos) make sense.\r
+  //\r
+  if (FoundBitPos > 7) {\r
+    FoundBytePos += 1;\r
+    FoundBitPos -= 8;\r
+  }\r
+  \r
+  //\r
+  // Set the memory as allocated\r
+  //\r
+  for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) {\r
+\r
+    MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);\r
+    Index++;\r
+    if (Index == 8) {\r
+      TempBytePos += 1;\r
+      Index = 0;\r
+    }\r
+  }\r
+\r
+  *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsMemoryBlockEmptied (\r
+  IN MEMORY_MANAGE_HEADER     *MemoryHeaderPtr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Is Memory Block Emptied\r
+\r
+Arguments:\r
+\r
+  MemoryHeaderPtr - MEMORY_MANAGE_HEADER\r
+\r
+Returns:\r
+\r
+  TRUE    Empty\r
+  FALSE   Not Empty \r
+\r
+--*/\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r
+    if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+VOID\r
+DelinkMemoryBlock (\r
+  IN MEMORY_MANAGE_HEADER     *FirstMemoryHeader,\r
+  IN MEMORY_MANAGE_HEADER     *NeedFreeMemoryHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Delink Memory Block\r
+\r
+Arguments:\r
+\r
+  FirstMemoryHeader     - MEMORY_MANAGE_HEADER\r
+  NeedFreeMemoryHeader  - MEMORY_MANAGE_HEADER\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+\r
+  if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {\r
+    return ;\r
+  }\r
+\r
+  for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {\r
+\r
+    if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {\r
+      //\r
+      // Link the before and after\r
+      //\r
+      TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+InitialMemoryManagement (\r
+  IN USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize Memory Management\r
+\r
+Arguments:\r
+\r
+  HcDev  - USB2_HC_DEV\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  MEMORY_MANAGE_HEADER  *MemoryHeader;\r
+  UINTN                 MemPages;\r
+\r
+  MemPages  = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
+  Status    = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto exit;\r
+  }\r
+\r
+  HcDev->MemoryHeader = MemoryHeader;\r
+\r
+exit:\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+DeinitialMemoryManagement (\r
+  IN USB2_HC_DEV     *HcDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Deinitialize Memory Management\r
+\r
+Arguments:\r
+\r
+  HcDev   - USB2_HC_DEV\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS        Success\r
+  EFI_DEVICE_ERROR   Fail\r
+  \r
+--*/\r
+{\r
+  MEMORY_MANAGE_HEADER  *TempHeaderPtr;\r
+\r
+  for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
+\r
+    DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);\r
+    //\r
+    // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
+    // the TempHeaderPtr is pointing to nonsense content.\r
+    //\r
+    FreeMemoryHeader (HcDev, TempHeaderPtr);\r
+    //\r
+    // reset the TempHeaderPtr,continue free another memory block.\r
+    //\r
+    TempHeaderPtr = HcDev->MemoryHeader->Next;\r
+  }\r
+\r
+  FreeMemoryHeader (HcDev, HcDev->MemoryHeader);\r
+\r
+  return EFI_SUCCESS;\r
+}\r