]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciRootBridgeIo.c
index 932aefd5d621fe8593f2981240b3589a4a8e5b6c..157a0ada80274d0783cacbece7afc1b45a5bbc55 100644 (file)
@@ -2,14 +2,8 @@
 \r
   PCI Root Bridge Io Protocol code.\r
 \r
-Copyright (c) 1999 - 2016, 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
-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) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -19,10 +13,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #define NO_MAPPING  (VOID *) (UINTN) -1\r
 \r
+#define RESOURCE_VALID(Resource)  ((Resource)->Base <= (Resource)->Limit)\r
+\r
 //\r
 // Lookup table for increment values based on transfer widths\r
 //\r
-UINT8 mInStride[] = {\r
+UINT8  mInStride[] = {\r
   1, // EfiPciWidthUint8\r
   2, // EfiPciWidthUint16\r
   4, // EfiPciWidthUint32\r
@@ -40,7 +36,7 @@ UINT8 mInStride[] = {
 //\r
 // Lookup table for increment values based on transfer widths\r
 //\r
-UINT8 mOutStride[] = {\r
+UINT8  mOutStride[] = {\r
   1, // EfiPciWidthUint8\r
   2, // EfiPciWidthUint16\r
   4, // EfiPciWidthUint32\r
@@ -59,108 +55,160 @@ UINT8 mOutStride[] = {
   Construct the Pci Root Bridge instance.\r
 \r
   @param Bridge            The root bridge instance.\r
-  @param HostBridgeHandle  Handle to the HostBridge.\r
 \r
   @return The pointer to PCI_ROOT_BRIDGE_INSTANCE just created\r
           or NULL if creation fails.\r
 **/\r
 PCI_ROOT_BRIDGE_INSTANCE *\r
 CreateRootBridge (\r
-  IN PCI_ROOT_BRIDGE       *Bridge,\r
-  IN EFI_HANDLE            HostBridgeHandle\r
+  IN PCI_ROOT_BRIDGE  *Bridge\r
   )\r
 {\r
-  PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
-  PCI_RESOURCE_TYPE        Index;\r
-  CHAR16                   *DevicePathStr;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  PCI_RESOURCE_TYPE         Index;\r
+  CHAR16                    *DevicePathStr;\r
+  PCI_ROOT_BRIDGE_APERTURE  *Aperture;\r
 \r
   DevicePathStr = NULL;\r
 \r
-  DEBUG ((EFI_D_INFO, "RootBridge: "));\r
-  DEBUG ((EFI_D_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
-  DEBUG ((EFI_D_INFO, "  Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
-  DEBUG ((EFI_D_INFO, "    DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
-  DEBUG ((EFI_D_INFO, "     AllocAttr: %lx (%s%s)\n", Bridge->AllocationAttributes,\r
-          (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
-          (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
-          ));\r
-  DEBUG ((EFI_D_INFO, "           Bus: %lx - %lx\n", Bridge->Bus.Base, Bridge->Bus.Limit));\r
-  DEBUG ((EFI_D_INFO, "            Io: %lx - %lx\n", Bridge->Io.Base, Bridge->Io.Limit));\r
-  DEBUG ((EFI_D_INFO, "           Mem: %lx - %lx\n", Bridge->Mem.Base, Bridge->Mem.Limit));\r
-  DEBUG ((EFI_D_INFO, "    MemAbove4G: %lx - %lx\n", Bridge->MemAbove4G.Base, Bridge->MemAbove4G.Limit));\r
-  DEBUG ((EFI_D_INFO, "          PMem: %lx - %lx\n", Bridge->PMem.Base, Bridge->PMem.Limit));\r
-  DEBUG ((EFI_D_INFO, "   PMemAbove4G: %lx - %lx\n", Bridge->PMemAbove4G.Base, Bridge->PMemAbove4G.Limit));\r
+  DEBUG ((DEBUG_INFO, "RootBridge: "));\r
+  DEBUG ((DEBUG_INFO, "%s\n", DevicePathStr = ConvertDevicePathToText (Bridge->DevicePath, FALSE, FALSE)));\r
+  DEBUG ((DEBUG_INFO, "  Support/Attr: %lx / %lx\n", Bridge->Supports, Bridge->Attributes));\r
+  DEBUG ((DEBUG_INFO, "    DmaAbove4G: %s\n", Bridge->DmaAbove4G ? L"Yes" : L"No"));\r
+  DEBUG ((DEBUG_INFO, "NoExtConfSpace: %s\n", Bridge->NoExtendedConfigSpace ? L"Yes" : L"No"));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "     AllocAttr: %lx (%s%s)\n",\r
+    Bridge->AllocationAttributes,\r
+    (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 ? L"CombineMemPMem " : L"",\r
+    (Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0 ? L"Mem64Decode" : L""\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "           Bus: %lx - %lx Translation=%lx\n",\r
+    Bridge->Bus.Base,\r
+    Bridge->Bus.Limit,\r
+    Bridge->Bus.Translation\r
+    ));\r
+  //\r
+  // Translation for bus is not supported.\r
+  //\r
+  ASSERT (Bridge->Bus.Translation == 0);\r
+  if (Bridge->Bus.Translation != 0) {\r
+    return NULL;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "            Io: %lx - %lx Translation=%lx\n",\r
+    Bridge->Io.Base,\r
+    Bridge->Io.Limit,\r
+    Bridge->Io.Translation\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "           Mem: %lx - %lx Translation=%lx\n",\r
+    Bridge->Mem.Base,\r
+    Bridge->Mem.Limit,\r
+    Bridge->Mem.Translation\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "    MemAbove4G: %lx - %lx Translation=%lx\n",\r
+    Bridge->MemAbove4G.Base,\r
+    Bridge->MemAbove4G.Limit,\r
+    Bridge->MemAbove4G.Translation\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "          PMem: %lx - %lx Translation=%lx\n",\r
+    Bridge->PMem.Base,\r
+    Bridge->PMem.Limit,\r
+    Bridge->PMem.Translation\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "   PMemAbove4G: %lx - %lx Translation=%lx\n",\r
+    Bridge->PMemAbove4G.Base,\r
+    Bridge->PMemAbove4G.Limit,\r
+    Bridge->PMemAbove4G.Translation\r
+    ));\r
 \r
   //\r
   // Make sure Mem and MemAbove4G apertures are valid\r
   //\r
-  if (Bridge->Mem.Base < Bridge->Mem.Limit) {\r
+  if (RESOURCE_VALID (&Bridge->Mem)) {\r
     ASSERT (Bridge->Mem.Limit < SIZE_4GB);\r
     if (Bridge->Mem.Limit >= SIZE_4GB) {\r
       return NULL;\r
     }\r
   }\r
-  if (Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) {\r
+\r
+  if (RESOURCE_VALID (&Bridge->MemAbove4G)) {\r
     ASSERT (Bridge->MemAbove4G.Base >= SIZE_4GB);\r
     if (Bridge->MemAbove4G.Base < SIZE_4GB) {\r
       return NULL;\r
     }\r
   }\r
-  if (Bridge->PMem.Base < Bridge->PMem.Limit) {\r
+\r
+  if (RESOURCE_VALID (&Bridge->PMem)) {\r
     ASSERT (Bridge->PMem.Limit < SIZE_4GB);\r
     if (Bridge->PMem.Limit >= SIZE_4GB) {\r
       return NULL;\r
     }\r
   }\r
-  if (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit) {\r
+\r
+  if (RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
     ASSERT (Bridge->PMemAbove4G.Base >= SIZE_4GB);\r
     if (Bridge->PMemAbove4G.Base < SIZE_4GB) {\r
       return NULL;\r
     }\r
   }\r
 \r
-  if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
-    //\r
-    // If this bit is set, then the PCI Root Bridge does not\r
-    // support separate windows for Non-prefetchable and Prefetchable\r
-    // memory.\r
-    //\r
-    ASSERT (Bridge->PMem.Base >= Bridge->PMem.Limit);\r
-    ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
-    if ((Bridge->PMem.Base < Bridge->PMem.Limit) ||\r
-        (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
-        ) {\r
-      return NULL;\r
+  //\r
+  // Ignore AllocationAttributes when resources were already assigned.\r
+  //\r
+  if (!Bridge->ResourceAssigned) {\r
+    if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+      //\r
+      // If this bit is set, then the PCI Root Bridge does not\r
+      // support separate windows for Non-prefetchable and Prefetchable\r
+      // memory.\r
+      //\r
+      ASSERT (!RESOURCE_VALID (&Bridge->PMem));\r
+      ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));\r
+      if (RESOURCE_VALID (&Bridge->PMem) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
+        return NULL;\r
+      }\r
     }\r
-  }\r
 \r
-  if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
-    //\r
-    // If this bit is not set, then the PCI Root Bridge does not support\r
-    // 64 bit memory windows.\r
-    //\r
-    ASSERT (Bridge->MemAbove4G.Base >= Bridge->MemAbove4G.Limit);\r
-    ASSERT (Bridge->PMemAbove4G.Base >= Bridge->PMemAbove4G.Limit);\r
-    if ((Bridge->MemAbove4G.Base < Bridge->MemAbove4G.Limit) ||\r
-        (Bridge->PMemAbove4G.Base < Bridge->PMemAbove4G.Limit)\r
-        ) {\r
-      return NULL;\r
+    if ((Bridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) == 0) {\r
+      //\r
+      // If this bit is not set, then the PCI Root Bridge does not support\r
+      // 64 bit memory windows.\r
+      //\r
+      ASSERT (!RESOURCE_VALID (&Bridge->MemAbove4G));\r
+      ASSERT (!RESOURCE_VALID (&Bridge->PMemAbove4G));\r
+      if (RESOURCE_VALID (&Bridge->MemAbove4G) || RESOURCE_VALID (&Bridge->PMemAbove4G)) {\r
+        return NULL;\r
+      }\r
     }\r
   }\r
 \r
   RootBridge = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));\r
   ASSERT (RootBridge != NULL);\r
 \r
-  RootBridge->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
-  RootBridge->Supports = Bridge->Supports;\r
-  RootBridge->Attributes = Bridge->Attributes;\r
-  RootBridge->DmaAbove4G = Bridge->DmaAbove4G;\r
-  RootBridge->AllocationAttributes = Bridge->AllocationAttributes;\r
-  RootBridge->DevicePath = DuplicateDevicePath (Bridge->DevicePath);\r
-  RootBridge->DevicePathStr = DevicePathStr;\r
-  RootBridge->ConfigBuffer = AllocatePool (\r
-    TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
-    );\r
+  RootBridge->Signature             = PCI_ROOT_BRIDGE_SIGNATURE;\r
+  RootBridge->Supports              = Bridge->Supports;\r
+  RootBridge->Attributes            = Bridge->Attributes;\r
+  RootBridge->DmaAbove4G            = Bridge->DmaAbove4G;\r
+  RootBridge->NoExtendedConfigSpace = Bridge->NoExtendedConfigSpace;\r
+  RootBridge->AllocationAttributes  = Bridge->AllocationAttributes;\r
+  RootBridge->DevicePath            = DuplicateDevicePath (Bridge->DevicePath);\r
+  RootBridge->DevicePathStr         = DevicePathStr;\r
+  RootBridge->ConfigBuffer          = AllocatePool (\r
+                                        TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+                                        );\r
   ASSERT (RootBridge->ConfigBuffer != NULL);\r
   InitializeListHead (&RootBridge->Maps);\r
 \r
@@ -168,17 +216,55 @@ CreateRootBridge (
   CopyMem (&RootBridge->Io, &Bridge->Io, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
   CopyMem (&RootBridge->Mem, &Bridge->Mem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
   CopyMem (&RootBridge->MemAbove4G, &Bridge->MemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
-\r
+  CopyMem (&RootBridge->PMem, &Bridge->PMem, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
+  CopyMem (&RootBridge->PMemAbove4G, &Bridge->PMemAbove4G, sizeof (PCI_ROOT_BRIDGE_APERTURE));\r
 \r
   for (Index = TypeIo; Index < TypeMax; Index++) {\r
-    RootBridge->ResAllocNode[Index].Type   = Index;\r
-    RootBridge->ResAllocNode[Index].Base   = 0;\r
-    RootBridge->ResAllocNode[Index].Length = 0;\r
-    RootBridge->ResAllocNode[Index].Status = ResNone;\r
+    switch (Index) {\r
+      case TypeBus:\r
+        Aperture = &RootBridge->Bus;\r
+        break;\r
+      case TypeIo:\r
+        Aperture = &RootBridge->Io;\r
+        break;\r
+      case TypeMem32:\r
+        Aperture = &RootBridge->Mem;\r
+        break;\r
+      case TypeMem64:\r
+        Aperture = &RootBridge->MemAbove4G;\r
+        break;\r
+      case TypePMem32:\r
+        Aperture = &RootBridge->PMem;\r
+        break;\r
+      case TypePMem64:\r
+        Aperture = &RootBridge->PMemAbove4G;\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+        Aperture = NULL;\r
+        break;\r
+    }\r
+\r
+    RootBridge->ResAllocNode[Index].Type = Index;\r
+    if (Bridge->ResourceAssigned && (Aperture->Limit >= Aperture->Base)) {\r
+      //\r
+      // Base in ResAllocNode is a host address, while Base in Aperture is a\r
+      // device address.\r
+      //\r
+      RootBridge->ResAllocNode[Index].Base = TO_HOST_ADDRESS (\r
+                                               Aperture->Base,\r
+                                               Aperture->Translation\r
+                                               );\r
+      RootBridge->ResAllocNode[Index].Length = Aperture->Limit - Aperture->Base + 1;\r
+      RootBridge->ResAllocNode[Index].Status = ResAllocated;\r
+    } else {\r
+      RootBridge->ResAllocNode[Index].Base   = 0;\r
+      RootBridge->ResAllocNode[Index].Length = 0;\r
+      RootBridge->ResAllocNode[Index].Status = ResNone;\r
+    }\r
   }\r
 \r
   RootBridge->RootBridgeIo.SegmentNumber  = Bridge->Segment;\r
-  RootBridge->RootBridgeIo.ParentHandle   = HostBridgeHandle;\r
   RootBridge->RootBridgeIo.PollMem        = RootBridgeIoPollMem;\r
   RootBridge->RootBridgeIo.PollIo         = RootBridgeIoPollIo;\r
   RootBridge->RootBridgeIo.Mem.Read       = RootBridgeIoMemRead;\r
@@ -232,6 +318,8 @@ CreateRootBridge (
 \r
   @retval EFI_INVALID_PARAMETER  Buffer is NULL.\r
 \r
+  @retval EFI_INVALID_PARAMETER  Address or Count is invalid.\r
+\r
   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.\r
 \r
   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,\r
@@ -252,6 +340,7 @@ RootBridgeIoCheckParameter (
   UINT64                                       Base;\r
   UINT64                                       Limit;\r
   UINT32                                       Size;\r
+  UINT64                                       Length;\r
 \r
   //\r
   // Check to see if Buffer is NULL\r
@@ -263,21 +352,28 @@ RootBridgeIoCheckParameter (
   //\r
   // Check to see if Width is in the valid range\r
   //\r
-  if ((UINT32) Width >= EfiPciWidthMaximum) {\r
+  if ((UINT32)Width >= EfiPciWidthMaximum) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
-  // For FIFO type, the target address won't increase during the access,\r
+  // For FIFO type, the device address won't increase during the access,\r
   // so treat Count as 1\r
   //\r
-  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+  if ((Width >= EfiPciWidthFifoUint8) && (Width <= EfiPciWidthFifoUint64)) {\r
     Count = 1;\r
   }\r
 \r
-  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
   Size  = 1 << Width;\r
 \r
+  //\r
+  // Make sure (Count * Size) doesn't exceed MAX_UINT64\r
+  //\r
+  if (Count > DivU64x32 (MAX_UINT64, Size)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // Check to see if Address is aligned\r
   //\r
@@ -285,6 +381,14 @@ RootBridgeIoCheckParameter (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
+  //\r
+  // Make sure (Address + Count * Size) doesn't exceed MAX_UINT64\r
+  //\r
+  Length = MultU64x32 (Count, Size);\r
+  if (Address > MAX_UINT64 - Length) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
   //\r
@@ -303,45 +407,56 @@ RootBridgeIoCheckParameter (
     //\r
     // Allow Legacy IO access\r
     //\r
-    if (Address + MultU64x32 (Count, Size) <= 0x1000) {\r
+    if (Address + Length <= 0x1000) {\r
       if ((RootBridge->Attributes & (\r
-           EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
-           EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
-           EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+                                     EFI_PCI_ATTRIBUTE_ISA_IO | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_ATTRIBUTE_VGA_IO |\r
+                                     EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
+                                     EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_IO_16)) != 0)\r
+      {\r
         return EFI_SUCCESS;\r
       }\r
     }\r
-    Base = RootBridge->Io.Base;\r
+\r
+    Base  = RootBridge->Io.Base;\r
     Limit = RootBridge->Io.Limit;\r
   } else if (OperationType == MemOperation) {\r
     //\r
     // Allow Legacy MMIO access\r
     //\r
-    if ((Address >= 0xA0000) && (Address + MultU64x32 (Count, Size)) <= 0xC0000) {\r
+    if ((Address >= 0xA0000) && ((Address + Length) <= 0xC0000)) {\r
       if ((RootBridge->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) != 0) {\r
         return EFI_SUCCESS;\r
       }\r
     }\r
+\r
     //\r
     // By comparing the Address against Limit we know which range to be used\r
     // for checking\r
     //\r
-    if (Address + MultU64x32 (Count, Size) <= RootBridge->Mem.Limit + 1) {\r
-      Base = RootBridge->Mem.Base;\r
+    if ((Address >= RootBridge->Mem.Base) && (Address + Length <= RootBridge->Mem.Limit + 1)) {\r
+      Base  = RootBridge->Mem.Base;\r
       Limit = RootBridge->Mem.Limit;\r
-    } else {\r
-      Base = RootBridge->MemAbove4G.Base;\r
+    } else if ((Address >= RootBridge->PMem.Base) && (Address + Length <= RootBridge->PMem.Limit + 1)) {\r
+      Base  = RootBridge->PMem.Base;\r
+      Limit = RootBridge->PMem.Limit;\r
+    } else if ((Address >= RootBridge->MemAbove4G.Base) && (Address + Length <= RootBridge->MemAbove4G.Limit + 1)) {\r
+      Base  = RootBridge->MemAbove4G.Base;\r
       Limit = RootBridge->MemAbove4G.Limit;\r
+    } else {\r
+      Base  = RootBridge->PMemAbove4G.Base;\r
+      Limit = RootBridge->PMemAbove4G.Limit;\r
     }\r
   } else {\r
-    PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;\r
-    if (PciRbAddr->Bus < RootBridge->Bus.Base ||\r
-        PciRbAddr->Bus > RootBridge->Bus.Limit) {\r
+    PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&Address;\r
+    if ((PciRbAddr->Bus < RootBridge->Bus.Base) ||\r
+        (PciRbAddr->Bus > RootBridge->Bus.Limit))\r
+    {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    if (PciRbAddr->Device > PCI_MAX_DEVICE ||\r
-        PciRbAddr->Function > PCI_MAX_FUNC) {\r
+    if ((PciRbAddr->Device > PCI_MAX_DEVICE) ||\r
+        (PciRbAddr->Function > PCI_MAX_FUNC))\r
+    {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
@@ -350,21 +465,138 @@ RootBridgeIoCheckParameter (
     } else {\r
       Address = PciRbAddr->Register;\r
     }\r
-    Base = 0;\r
-    Limit = 0xFFF;\r
+\r
+    Base  = 0;\r
+    Limit = RootBridge->NoExtendedConfigSpace ? 0xFF : 0xFFF;\r
   }\r
 \r
   if (Address < Base) {\r
-      return EFI_INVALID_PARAMETER;\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (Address + MultU64x32 (Count, Size) > Limit + 1) {\r
+  if (Address + Length > Limit + 1) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Use address to match apertures of memory type and then get the corresponding\r
+  translation.\r
+\r
+  @param RootBridge              The root bridge instance.\r
+  @param Address                 The address used to match aperture.\r
+  @param Translation             Pointer containing the output translation.\r
+\r
+  @return EFI_SUCCESS            Get translation successfully.\r
+  @return EFI_INVALID_PARAMETER  No matched memory aperture; the input Address\r
+                                 must be invalid.\r
+**/\r
+EFI_STATUS\r
+RootBridgeIoGetMemTranslationByAddress (\r
+  IN PCI_ROOT_BRIDGE_INSTANCE  *RootBridge,\r
+  IN UINT64                    Address,\r
+  IN OUT UINT64                *Translation\r
+  )\r
+{\r
+  if ((Address >= RootBridge->Mem.Base) && (Address <= RootBridge->Mem.Limit)) {\r
+    *Translation = RootBridge->Mem.Translation;\r
+  } else if ((Address >= RootBridge->PMem.Base) && (Address <= RootBridge->PMem.Limit)) {\r
+    *Translation = RootBridge->PMem.Translation;\r
+  } else if ((Address >= RootBridge->MemAbove4G.Base) && (Address <= RootBridge->MemAbove4G.Limit)) {\r
+    *Translation = RootBridge->MemAbove4G.Translation;\r
+  } else if ((Address >= RootBridge->PMemAbove4G.Base) && (Address <= RootBridge->PMemAbove4G.Limit)) {\r
+    *Translation = RootBridge->PMemAbove4G.Translation;\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Return the result of (Multiplicand * Multiplier / Divisor).\r
+\r
+  @param Multiplicand A 64-bit unsigned value.\r
+  @param Multiplier   A 64-bit unsigned value.\r
+  @param Divisor      A 32-bit unsigned value.\r
+  @param Remainder    A pointer to a 32-bit unsigned value. This parameter is\r
+                      optional and may be NULL.\r
+\r
+  @return Multiplicand * Multiplier / Divisor.\r
+**/\r
+UINT64\r
+MultThenDivU64x64x32 (\r
+  IN      UINT64  Multiplicand,\r
+  IN      UINT64  Multiplier,\r
+  IN      UINT32  Divisor,\r
+  OUT     UINT32  *Remainder  OPTIONAL\r
+  )\r
+{\r
+  UINT64  Uint64;\r
+  UINT32  LocalRemainder;\r
+  UINT32  Uint32;\r
+\r
+  if (Multiplicand > DivU64x64Remainder (MAX_UINT64, Multiplier, NULL)) {\r
+    //\r
+    // Make sure Multiplicand is the bigger one.\r
+    //\r
+    if (Multiplicand < Multiplier) {\r
+      Uint64       = Multiplicand;\r
+      Multiplicand = Multiplier;\r
+      Multiplier   = Uint64;\r
+    }\r
+\r
+    //\r
+    // Because Multiplicand * Multiplier overflows,\r
+    //   Multiplicand * Multiplier / Divisor\r
+    // = (2 * Multiplicand' + 1) * Multiplier / Divisor\r
+    // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor\r
+    //\r
+    Uint64 = MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multiplier, Divisor, &LocalRemainder);\r
+    Uint64 = LShiftU64 (Uint64, 1);\r
+    Uint32 = 0;\r
+    if ((Multiplicand & 0x1) == 1) {\r
+      Uint64 += DivU64x32Remainder (Multiplier, Divisor, &Uint32);\r
+    }\r
+\r
+    return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder, 1), Divisor, Remainder);\r
+  } else {\r
+    return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divisor, Remainder);\r
+  }\r
+}\r
+\r
+/**\r
+  Return the elapsed tick count from CurrentTick.\r
+\r
+  @param  CurrentTick  On input, the previous tick count.\r
+                       On output, the current tick count.\r
+  @param  StartTick    The value the performance counter starts with when it\r
+                       rolls over.\r
+  @param  EndTick      The value that the performance counter ends with before\r
+                       it rolls over.\r
+\r
+  @return  The elapsed tick count from CurrentTick.\r
+**/\r
+UINT64\r
+GetElapsedTick (\r
+  UINT64  *CurrentTick,\r
+  UINT64  StartTick,\r
+  UINT64  EndTick\r
+  )\r
+{\r
+  UINT64  PreviousTick;\r
+\r
+  PreviousTick = *CurrentTick;\r
+  *CurrentTick = GetPerformanceCounter ();\r
+  if (StartTick < EndTick) {\r
+    return *CurrentTick - PreviousTick;\r
+  } else {\r
+    return PreviousTick - *CurrentTick;\r
+  }\r
+}\r
+\r
 /**\r
   Polls an address in memory mapped I/O space until an exit condition is met,\r
   or a timeout occurs.\r
@@ -414,6 +646,11 @@ RootBridgeIoPollMem (
   EFI_STATUS  Status;\r
   UINT64      NumberOfTicks;\r
   UINT32      Remainder;\r
+  UINT64      StartTick;\r
+  UINT64      EndTick;\r
+  UINT64      CurrentTick;\r
+  UINT64      ElapsedTick;\r
+  UINT64      Frequency;\r
 \r
   if (Result == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -437,30 +674,21 @@ RootBridgeIoPollMem (
 \r
   if (Delay == 0) {\r
     return EFI_SUCCESS;\r
-\r
   } else {\r
-\r
-    //\r
-    // Determine the proper # of metronome ticks to wait for polling the\r
-    // location.  The nuber of ticks is Roundup (Delay /\r
-    // mMetronome->TickPeriod)+1\r
-    // The "+1" to account for the possibility of the first tick being short\r
-    // because we started in the middle of a tick.\r
     //\r
-    // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome\r
-    // protocol definition is updated.\r
+    // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)\r
     //\r
-    NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod,\r
-                      &Remainder);\r
-    if (Remainder != 0) {\r
-      NumberOfTicks += 1;\r
+    Frequency     = GetPerformanceCounterProperties (&StartTick, &EndTick);\r
+    NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS (1), &Remainder);\r
+    if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS (1) / 2) {\r
+      NumberOfTicks++;\r
     }\r
-    NumberOfTicks += 1;\r
-\r
-    while (NumberOfTicks != 0) {\r
-\r
-      mMetronome->WaitForTick (mMetronome, 1);\r
 \r
+    for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter ()\r
+          ; ElapsedTick <= NumberOfTicks\r
+          ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)\r
+          )\r
+    {\r
       Status = This->Mem.Read (This, Width, Address, 1, Result);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
@@ -469,10 +697,9 @@ RootBridgeIoPollMem (
       if ((*Result & Mask) == Value) {\r
         return EFI_SUCCESS;\r
       }\r
-\r
-      NumberOfTicks -= 1;\r
     }\r
   }\r
+\r
   return EFI_TIMEOUT;\r
 }\r
 \r
@@ -523,6 +750,11 @@ RootBridgeIoPollIo (
   EFI_STATUS  Status;\r
   UINT64      NumberOfTicks;\r
   UINT32      Remainder;\r
+  UINT64      StartTick;\r
+  UINT64      EndTick;\r
+  UINT64      CurrentTick;\r
+  UINT64      ElapsedTick;\r
+  UINT64      Frequency;\r
 \r
   //\r
   // No matter what, always do a single poll.\r
@@ -540,33 +772,28 @@ RootBridgeIoPollIo (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   if ((*Result & Mask) == Value) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   if (Delay == 0) {\r
     return EFI_SUCCESS;\r
-\r
   } else {\r
-\r
     //\r
-    // Determine the proper # of metronome ticks to wait for polling the\r
-    // location.  The number of ticks is Roundup (Delay /\r
-    // mMetronome->TickPeriod)+1\r
-    // The "+1" to account for the possibility of the first tick being short\r
-    // because we started in the middle of a tick.\r
+    // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)\r
     //\r
-    NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod,\r
-                      &Remainder);\r
-    if (Remainder != 0) {\r
-      NumberOfTicks += 1;\r
+    Frequency     = GetPerformanceCounterProperties (&StartTick, &EndTick);\r
+    NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS (1), &Remainder);\r
+    if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS (1) / 2) {\r
+      NumberOfTicks++;\r
     }\r
-    NumberOfTicks += 1;\r
-\r
-    while (NumberOfTicks != 0) {\r
-\r
-      mMetronome->WaitForTick (mMetronome, 1);\r
 \r
+    for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter ()\r
+          ; ElapsedTick <= NumberOfTicks\r
+          ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)\r
+          )\r
+    {\r
       Status = This->Io.Read (This, Width, Address, 1, Result);\r
       if (EFI_ERROR (Status)) {\r
         return Status;\r
@@ -575,10 +802,9 @@ RootBridgeIoPollIo (
       if ((*Result & Mask) == Value) {\r
         return EFI_SUCCESS;\r
       }\r
-\r
-      NumberOfTicks -= 1;\r
     }\r
   }\r
+\r
   return EFI_TIMEOUT;\r
 }\r
 \r
@@ -619,14 +845,37 @@ RootBridgeIoMemRead (
   OUT    VOID                                   *Buffer\r
   )\r
 {\r
-  EFI_STATUS                             Status;\r
+  EFI_STATUS                Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  UINT64                    Translation;\r
 \r
-  Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
-                                       Count, Buffer);\r
+  Status = RootBridgeIoCheckParameter (\r
+             This,\r
+             MemOperation,\r
+             Width,\r
+             Address,\r
+             Count,\r
+             Buffer\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+  Status     = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+  // Address passed to CpuIo->Mem.Read needs to be a host address instead of\r
+  // device address.\r
+  return mCpuIo->Mem.Read (\r
+                       mCpuIo,\r
+                       (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+                       TO_HOST_ADDRESS (Address, Translation),\r
+                       Count,\r
+                       Buffer\r
+                       );\r
 }\r
 \r
 /**\r
@@ -666,14 +915,37 @@ RootBridgeIoMemWrite (
   IN     VOID                                   *Buffer\r
   )\r
 {\r
-  EFI_STATUS                             Status;\r
+  EFI_STATUS                Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  UINT64                    Translation;\r
 \r
-  Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address,\r
-                                       Count, Buffer);\r
+  Status = RootBridgeIoCheckParameter (\r
+             This,\r
+             MemOperation,\r
+             Width,\r
+             Address,\r
+             Count,\r
+             Buffer\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  return mCpuIo->Mem.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+  Status     = RootBridgeIoGetMemTranslationByAddress (RootBridge, Address, &Translation);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  // Address passed to CpuIo->Mem.Write needs to be a host address instead of\r
+  // device address.\r
+  return mCpuIo->Mem.Write (\r
+                       mCpuIo,\r
+                       (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+                       TO_HOST_ADDRESS (Address, Translation),\r
+                       Count,\r
+                       Buffer\r
+                       );\r
 }\r
 \r
 /**\r
@@ -707,15 +979,32 @@ RootBridgeIoIoRead (
   OUT    VOID                                   *Buffer\r
   )\r
 {\r
-  EFI_STATUS                                    Status;\r
+  EFI_STATUS                Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+\r
   Status = RootBridgeIoCheckParameter (\r
-             This, IoOperation, Width,\r
-             Address, Count, Buffer\r
+             This,\r
+             IoOperation,\r
+             Width,\r
+             Address,\r
+             Count,\r
+             Buffer\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  return mCpuIo->Io.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+  // Address passed to CpuIo->Io.Read needs to be a host address instead of\r
+  // device address.\r
+  return mCpuIo->Io.Read (\r
+                      mCpuIo,\r
+                      (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+                      TO_HOST_ADDRESS (Address, RootBridge->Io.Translation),\r
+                      Count,\r
+                      Buffer\r
+                      );\r
 }\r
 \r
 /**\r
@@ -742,22 +1031,39 @@ RootBridgeIoIoRead (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoIoWrite (\r
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,\r
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,\r
-  IN       UINT64                                  Address,\r
-  IN       UINTN                                   Count,\r
-  IN       VOID                                    *Buffer\r
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,\r
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,\r
+  IN       UINT64                                 Address,\r
+  IN       UINTN                                  Count,\r
+  IN       VOID                                   *Buffer\r
   )\r
 {\r
-  EFI_STATUS                                    Status;\r
+  EFI_STATUS                Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+\r
   Status = RootBridgeIoCheckParameter (\r
-             This, IoOperation, Width,\r
-             Address, Count, Buffer\r
+             This,\r
+             IoOperation,\r
+             Width,\r
+             Address,\r
+             Count,\r
+             Buffer\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer);\r
+\r
+  RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
+  // Address passed to CpuIo->Io.Write needs to be a host address instead of\r
+  // device address.\r
+  return mCpuIo->Io.Write (\r
+                      mCpuIo,\r
+                      (EFI_CPU_IO_PROTOCOL_WIDTH)Width,\r
+                      TO_HOST_ADDRESS (Address, RootBridge->Io.Translation),\r
+                      Count,\r
+                      Buffer\r
+                      );\r
 }\r
 \r
 /**\r
@@ -794,11 +1100,11 @@ RootBridgeIoIoWrite (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoCopyMem (\r
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,\r
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        Width,\r
-  IN UINT64                                       DestAddress,\r
-  IN UINT64                                       SrcAddress,\r
-  IN UINTN                                        Count\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINT64                                 DestAddress,\r
+  IN UINT64                                 SrcAddress,\r
+  IN UINTN                                  Count\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -807,7 +1113,7 @@ RootBridgeIoCopyMem (
   UINTN       Index;\r
   UINT64      Result;\r
 \r
-  if ((UINT32) Width > EfiPciWidthUint64) {\r
+  if ((UINT32)Width > EfiPciWidthUint64) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -815,13 +1121,14 @@ RootBridgeIoCopyMem (
     return EFI_SUCCESS;\r
   }\r
 \r
-  Stride = (UINTN) (1 << Width);\r
+  Stride = (UINTN)(1 << Width);\r
 \r
   Forward = TRUE;\r
   if ((DestAddress > SrcAddress) &&\r
-      (DestAddress < (SrcAddress + Count * Stride))) {\r
-    Forward = FALSE;\r
-    SrcAddress = SrcAddress + (Count - 1) * Stride;\r
+      (DestAddress < (SrcAddress + Count * Stride)))\r
+  {\r
+    Forward     = FALSE;\r
+    SrcAddress  = SrcAddress + (Count - 1) * Stride;\r
     DestAddress = DestAddress + (Count - 1) * Stride;\r
   }\r
 \r
@@ -836,6 +1143,7 @@ RootBridgeIoCopyMem (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+\r
     Status = RootBridgeIoMemWrite (\r
                This,\r
                Width,\r
@@ -846,18 +1154,19 @@ RootBridgeIoCopyMem (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+\r
     if (Forward) {\r
-      SrcAddress += Stride;\r
+      SrcAddress  += Stride;\r
       DestAddress += Stride;\r
     } else {\r
-      SrcAddress -= Stride;\r
+      SrcAddress  -= Stride;\r
       DestAddress -= Stride;\r
     }\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   PCI configuration space access.\r
 \r
@@ -876,12 +1185,12 @@ RootBridgeIoCopyMem (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoPciAccess (\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This,\r
-  IN     BOOLEAN                               Read,\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
-  IN     UINT64                                Address,\r
-  IN     UINTN                                 Count,\r
-  IN OUT VOID                                  *Buffer\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,\r
+  IN     BOOLEAN                                Read,\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT64                                 Address,\r
+  IN     UINTN                                  Count,\r
+  IN OUT VOID                                   *Buffer\r
   )\r
 {\r
   EFI_STATUS                                   Status;\r
@@ -920,7 +1229,7 @@ RootBridgeIoPciAccess (
   //\r
   InStride  = mInStride[Width];\r
   OutStride = mOutStride[Width];\r
-  Size      = (UINTN) (1 << (Width & 0x03));\r
+  Size      = (UINTN)(1 << (Width & 0x03));\r
   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
     if (Read) {\r
       PciSegmentReadBuffer (Address, Size, Uint8Buffer);\r
@@ -928,6 +1237,7 @@ RootBridgeIoPciAccess (
       PciSegmentWriteBuffer (Address, Size, Uint8Buffer);\r
     }\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -948,11 +1258,11 @@ RootBridgeIoPciAccess (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoPciRead (\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This,\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
-  IN     UINT64                                Address,\r
-  IN     UINTN                                 Count,\r
-  IN OUT VOID                                  *Buffer\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT64                                 Address,\r
+  IN     UINTN                                  Count,\r
+  IN OUT VOID                                   *Buffer\r
   )\r
 {\r
   return RootBridgeIoPciAccess (This, TRUE, Width, Address, Count, Buffer);\r
@@ -975,11 +1285,11 @@ RootBridgeIoPciRead (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoPciWrite (\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL       *This,\r
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
-  IN     UINT64                                Address,\r
-  IN     UINTN                                 Count,\r
-  IN OUT VOID                                  *Buffer\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT64                                 Address,\r
+  IN     UINTN                                  Count,\r
+  IN OUT VOID                                   *Buffer\r
   )\r
 {\r
   return RootBridgeIoPciAccess (This, FALSE, Width, Address, Count, Buffer);\r
@@ -1017,35 +1327,63 @@ RootBridgeIoMap (
   OUT    VOID                                       **Mapping\r
   )\r
 {\r
-  EFI_STATUS                                        Status;\r
-  PCI_ROOT_BRIDGE_INSTANCE                          *RootBridge;\r
-  EFI_PHYSICAL_ADDRESS                              PhysicalAddress;\r
-  MAP_INFO                                          *MapInfo;\r
+  EFI_STATUS                Status;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  EFI_PHYSICAL_ADDRESS      PhysicalAddress;\r
+  MAP_INFO                  *MapInfo;\r
 \r
-  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||\r
-      Mapping == NULL) {\r
+  if ((HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) ||\r
+      (Mapping == NULL))\r
+  {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
   // Make sure that Operation is valid\r
   //\r
-  if ((UINT32) Operation >= EfiPciOperationMaximum) {\r
+  if ((UINT32)Operation >= EfiPciOperationMaximum) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
-  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
-  if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+  if (mIoMmu != NULL) {\r
+    if (!RootBridge->DmaAbove4G) {\r
+      //\r
+      // Clear 64bit support\r
+      //\r
+      if (Operation > EfiPciOperationBusMasterCommonBuffer) {\r
+        Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation - EfiPciOperationBusMasterRead64);\r
+      }\r
+    }\r
+\r
+    Status = mIoMmu->Map (\r
+                       mIoMmu,\r
+                       (EDKII_IOMMU_OPERATION)Operation,\r
+                       HostAddress,\r
+                       NumberOfBytes,\r
+                       DeviceAddress,\r
+                       Mapping\r
+                       );\r
+    return Status;\r
+  }\r
+\r
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
+  if ((!RootBridge->DmaAbove4G ||\r
+       ((Operation != EfiPciOperationBusMasterRead64) &&\r
+        (Operation != EfiPciOperationBusMasterWrite64) &&\r
+        (Operation != EfiPciOperationBusMasterCommonBuffer64))) &&\r
+      ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB))\r
+  {\r
     //\r
-    // If the root bridge can not handle performing DMA above 4GB but\r
-    // any part of the DMA transfer being mapped is above 4GB, then\r
+    // If the root bridge or the device cannot handle performing DMA above\r
+    // 4GB but any part of the DMA transfer being mapped is above 4GB, then\r
     // map the DMA transfer to a buffer below 4GB.\r
     //\r
 \r
-    if (Operation == EfiPciOperationBusMasterCommonBuffer ||\r
-        Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
+    if ((Operation == EfiPciOperationBusMasterCommonBuffer) ||\r
+        (Operation == EfiPciOperationBusMasterCommonBuffer64))\r
+    {\r
       //\r
       // Common Buffer operations can not be remapped.  If the common buffer\r
       // if above 4GB, then it is not possible to generate a mapping, so return\r
@@ -1094,11 +1432,12 @@ RootBridgeIoMap (
     // then copy the contents of the real buffer into the mapped buffer\r
     // so the Bus Master can read the contents of the real buffer.\r
     //\r
-    if (Operation == EfiPciOperationBusMasterRead ||\r
-        Operation == EfiPciOperationBusMasterRead64) {\r
+    if ((Operation == EfiPciOperationBusMasterRead) ||\r
+        (Operation == EfiPciOperationBusMasterRead64))\r
+    {\r
       CopyMem (\r
-        (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
-        (VOID *) (UINTN) MapInfo->HostAddress,\r
+        (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
+        (VOID *)(UINTN)MapInfo->HostAddress,\r
         MapInfo->NumberOfBytes\r
         );\r
     }\r
@@ -1112,7 +1451,7 @@ RootBridgeIoMap (
     //\r
     // Return a pointer to the MAP_INFO structure in Mapping\r
     //\r
-    *Mapping       = MapInfo;\r
+    *Mapping = MapInfo;\r
   } else {\r
     //\r
     // If the root bridge CAN handle performing DMA above 4GB or\r
@@ -1150,11 +1489,21 @@ RootBridgeIoUnmap (
   IN VOID                             *Mapping\r
   )\r
 {\r
-  MAP_INFO                 *MapInfo;\r
-  LIST_ENTRY               *Link;\r
-  PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+  MAP_INFO                  *MapInfo;\r
+  LIST_ENTRY                *Link;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
+  EFI_STATUS                Status;\r
+\r
+  if (mIoMmu != NULL) {\r
+    Status = mIoMmu->Unmap (\r
+                       mIoMmu,\r
+                       Mapping\r
+                       );\r
+    return Status;\r
+  }\r
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
+\r
   //\r
   // See if the Map() operation associated with this Unmap() required a mapping\r
   // buffer. If a mapping buffer was not required, then this function simply\r
@@ -1168,18 +1517,21 @@ RootBridgeIoUnmap (
   for (Link = GetFirstNode (&RootBridge->Maps)\r
        ; !IsNull (&RootBridge->Maps, Link)\r
        ; Link = GetNextNode (&RootBridge->Maps, Link)\r
-       ) {\r
+       )\r
+  {\r
     MapInfo = MAP_INFO_FROM_LINK (Link);\r
     if (MapInfo == Mapping) {\r
       break;\r
     }\r
   }\r
+\r
   //\r
   // Mapping is not a valid value returned by Map()\r
   //\r
   if (MapInfo != Mapping) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   RemoveEntryList (&MapInfo->Link);\r
 \r
   //\r
@@ -1187,11 +1539,12 @@ RootBridgeIoUnmap (
   // then copy the contents of the mapped buffer into the real buffer\r
   // so the processor can read the contents of the real buffer.\r
   //\r
-  if (MapInfo->Operation == EfiPciOperationBusMasterWrite ||\r
-      MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
+  if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||\r
+      (MapInfo->Operation == EfiPciOperationBusMasterWrite64))\r
+  {\r
     CopyMem (\r
-      (VOID *) (UINTN) MapInfo->HostAddress,\r
-      (VOID *) (UINTN) MapInfo->MappedHostAddress,\r
+      (VOID *)(UINTN)MapInfo->HostAddress,\r
+      (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
       MapInfo->NumberOfBytes\r
       );\r
   }\r
@@ -1264,21 +1617,44 @@ RootBridgeIoAllocateBuffer (
   // The only valid memory types are EfiBootServicesData and\r
   // EfiRuntimeServicesData\r
   //\r
-  if (MemoryType != EfiBootServicesData &&\r
-      MemoryType != EfiRuntimeServicesData) {\r
+  if ((MemoryType != EfiBootServicesData) &&\r
+      (MemoryType != EfiRuntimeServicesData))\r
+  {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
+  if (mIoMmu != NULL) {\r
+    if (!RootBridge->DmaAbove4G) {\r
+      //\r
+      // Clear DUAL_ADDRESS_CYCLE\r
+      //\r
+      Attributes &= ~((UINT64)EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
+    }\r
+\r
+    Status = mIoMmu->AllocateBuffer (\r
+                       mIoMmu,\r
+                       Type,\r
+                       MemoryType,\r
+                       Pages,\r
+                       HostAddress,\r
+                       Attributes\r
+                       );\r
+    return Status;\r
+  }\r
+\r
   AllocateType = AllocateAnyPages;\r
-  if (!RootBridge->DmaAbove4G) {\r
+  if (!RootBridge->DmaAbove4G ||\r
+      ((Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0))\r
+  {\r
     //\r
     // Limit allocations to memory below 4GB\r
     //\r
     AllocateType    = AllocateMaxAddress;\r
-    PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
+    PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(SIZE_4GB - 1);\r
   }\r
+\r
   Status = gBS->AllocatePages (\r
                   AllocateType,\r
                   MemoryType,\r
@@ -1286,7 +1662,7 @@ RootBridgeIoAllocateBuffer (
                   &PhysicalAddress\r
                   );\r
   if (!EFI_ERROR (Status)) {\r
-    *HostAddress = (VOID *) (UINTN) PhysicalAddress;\r
+    *HostAddress = (VOID *)(UINTN)PhysicalAddress;\r
   }\r
 \r
   return Status;\r
@@ -1314,7 +1690,18 @@ RootBridgeIoFreeBuffer (
   OUT VOID                             *HostAddress\r
   )\r
 {\r
-  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
+  EFI_STATUS  Status;\r
+\r
+  if (mIoMmu != NULL) {\r
+    Status = mIoMmu->FreeBuffer (\r
+                       mIoMmu,\r
+                       Pages,\r
+                       HostAddress\r
+                       );\r
+    return Status;\r
+  }\r
+\r
+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);\r
 }\r
 \r
 /**\r
@@ -1341,7 +1728,7 @@ RootBridgeIoFreeBuffer (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoFlush (\r
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This\r
   )\r
 {\r
   return EFI_SUCCESS;\r
@@ -1377,9 +1764,9 @@ RootBridgeIoGetAttributes (
   OUT UINT64                           *Attributes\r
   )\r
 {\r
-  PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
 \r
-  if (Attributes == NULL && Supported == NULL) {\r
+  if ((Attributes == NULL) && (Supported == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -1388,7 +1775,7 @@ RootBridgeIoGetAttributes (
   // Set the return value for Supported and Attributes\r
   //\r
   if (Supported != NULL) {\r
-    *Supported  = RootBridge->Supports;\r
+    *Supported = RootBridge->Supports;\r
   }\r
 \r
   if (Attributes != NULL) {\r
@@ -1443,7 +1830,7 @@ RootBridgeIoSetAttributes (
   IN OUT UINT64                           *ResourceLength\r
   )\r
 {\r
-  PCI_ROOT_BRIDGE_INSTANCE            *RootBridge;\r
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridge;\r
 \r
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
@@ -1457,20 +1844,19 @@ RootBridgeIoSetAttributes (
 \r
 /**\r
   Retrieves the current resource settings of this PCI root bridge in the form\r
-  of a set of ACPI 2.0 resource descriptors.\r
+  of a set of ACPI resource descriptors.\r
 \r
   There are only two resource descriptor types from the ACPI Specification that\r
   may be used to describe the current resources allocated to a PCI root bridge.\r
-  These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),\r
-  and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space\r
-  Descriptor can describe memory, I/O, and bus number ranges for dynamic or\r
-  fixed resources. The configuration of a PCI root bridge is described with one\r
-  or more QWORD Address Space Descriptors followed by an End Tag.\r
+  These are the QWORD Address Space Descriptor, and the End Tag. The QWORD\r
+  Address Space Descriptor can describe memory, I/O, and bus number ranges for\r
+  dynamic or fixed resources. The configuration of a PCI root bridge is described\r
+  with one or more QWORD Address Space Descriptors followed by an End Tag.\r
 \r
   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
-  @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that\r
+  @param[out]  Resources   A pointer to the resource descriptors that\r
                            describe the current configuration of this PCI root\r
-                           bridge. The storage for the ACPI 2.0 resource\r
+                           bridge. The storage for the resource\r
                            descriptors is allocated by this function. The\r
                            caller must treat the return buffer as read-only\r
                            data, and the buffer must not be freed by the\r
@@ -1484,15 +1870,15 @@ RootBridgeIoSetAttributes (
 EFI_STATUS\r
 EFIAPI\r
 RootBridgeIoConfiguration (\r
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,\r
-  OUT VOID                                **Resources\r
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,\r
+  OUT VOID                             **Resources\r
   )\r
 {\r
-  PCI_RESOURCE_TYPE                 Index;\r
-  PCI_ROOT_BRIDGE_INSTANCE          *RootBridge;\r
-  PCI_RES_NODE                      *ResAllocNode;\r
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
-  EFI_ACPI_END_TAG_DESCRIPTOR       *End;\r
+  PCI_RESOURCE_TYPE                  Index;\r
+  PCI_ROOT_BRIDGE_INSTANCE           *RootBridge;\r
+  PCI_RES_NODE                       *ResAllocNode;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptor;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR        *End;\r
 \r
   //\r
   // Get this instance of the Root Bridge.\r
@@ -1504,7 +1890,6 @@ RootBridgeIoConfiguration (
     );\r
   Descriptor = RootBridge->ConfigBuffer;\r
   for (Index = TypeIo; Index < TypeMax; Index++) {\r
-\r
     ResAllocNode = &RootBridge->ResAllocNode[Index];\r
 \r
     if (ResAllocNode->Status != ResAllocated) {\r
@@ -1513,43 +1898,51 @@ RootBridgeIoConfiguration (
 \r
     Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
     Descriptor->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
-    Descriptor->AddrRangeMin  = ResAllocNode->Base;\r
-    Descriptor->AddrRangeMax  = ResAllocNode->Base + ResAllocNode->Length - 1;\r
-    Descriptor->AddrLen       = ResAllocNode->Length;\r
-    switch (ResAllocNode->Type) {\r
-\r
-    case TypeIo:\r
-      Descriptor->ResType       = ACPI_ADDRESS_SPACE_TYPE_IO;\r
-      break;\r
+    // According to UEFI 2.7, RootBridgeIo->Configuration should return address\r
+    // range in CPU view (host address), and ResAllocNode->Base is already a CPU\r
+    // view address (host address).\r
+    Descriptor->AddrRangeMin          = ResAllocNode->Base;\r
+    Descriptor->AddrRangeMax          = ResAllocNode->Base + ResAllocNode->Length - 1;\r
+    Descriptor->AddrLen               = ResAllocNode->Length;\r
+    Descriptor->AddrTranslationOffset = GetTranslationByResourceType (\r
+                                          RootBridge,\r
+                                          ResAllocNode->Type\r
+                                          );\r
 \r
-    case TypePMem32:\r
-      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
-    case TypeMem32:\r
-      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
-      Descriptor->AddrSpaceGranularity  = 32;\r
-      break;\r
-\r
-    case TypePMem64:\r
-      Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
-    case TypeMem64:\r
-      Descriptor->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
-      Descriptor->AddrSpaceGranularity  = 64;\r
-      break;\r
-\r
-    case TypeBus:\r
-      Descriptor->ResType       = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
-      break;\r
-\r
-    default:\r
-      break;\r
+    switch (ResAllocNode->Type) {\r
+      case TypeIo:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+        break;\r
+\r
+      case TypePMem32:\r
+        Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+      case TypeMem32:\r
+        Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        Descriptor->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case TypePMem64:\r
+        Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;\r
+      case TypeMem64:\r
+        Descriptor->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        Descriptor->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      case TypeBus:\r
+        Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+        break;\r
+\r
+      default:\r
+        break;\r
     }\r
 \r
     Descriptor++;\r
   }\r
+\r
   //\r
   // Terminate the entries.\r
   //\r
-  End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;\r
+  End           = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;\r
   End->Desc     = ACPI_END_TAG_DESCRIPTOR;\r
   End->Checksum = 0x0;\r
 \r