public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe
@ 2016-08-22  6:35 Ard Biesheuvel
  2016-08-22  6:35 ` [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property Ard Biesheuvel
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

Now that Laszlo's virtio-gpu-pci have removed the last remaining obstacle,
we can get rid of the special PciHostBridgeDxe implementation in ArmVirtPkg,
and move to the generic one. This will allow us to perform DMA above 4GB
without bounce buffering, and use 64-bit MMIO BARs.

Patch #1 removes the linux,pci-probe-only override which does more harm than
good now that we switched to virtio-gp-pci, which does not expose a raw
framebuffer.

Patch #2 implements PciHostBridgeLib for platforms exposing a PCI host bridge
using a pci-host-ecam-generic DT node.

Patch #3 switches to the generic PciHostBridgeDxe, with no change in
functionality other than support for DMA above 4 GB without bounce buffering.

Patch #4 adds support for 64-bit MMIO BARs

Patch #5 removes the now obsolete PciHostBridgeDxe from ArmVirPkg.

Ard Biesheuvel (5):
  ArmVirtPkg/PciHostBridgeDxe: don't set linux,pci-probe-only DT
    property
  ArmVirtPkg: implement FdtPciHostBridgeLib
  ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe
  ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support
  ArmVirtPkg: remove now unused PciHostBridgeDxe

 ArmVirtPkg/ArmVirtQemu.dsc                                     |    7 +-
 ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc                           |    3 +-
 ArmVirtPkg/ArmVirtQemuKernel.dsc                               |    7 +-
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c   |  417 ++++
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf |   56 +
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c                    | 1496 --------------
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h                    |  499 -----
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf               |   64 -
 ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c                  | 2144 --------------------
 9 files changed, 487 insertions(+), 4206 deletions(-)
 create mode 100644 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
 create mode 100644 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
 delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
 delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
 delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
 delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c

-- 
2.7.4



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
@ 2016-08-22  6:35 ` Ard Biesheuvel
  2016-08-23 21:23   ` Laszlo Ersek
  2016-08-22  6:35 ` [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib Ard Biesheuvel
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

Setting the linux,pci-probe-only was intended to align OSes booting via
DT with OSes booting via ACPI in the way they honor the PCI configuration
performed by the firmware. However, ACPI on arm64 does not currently honor
the firmware's PCI configuration, and the linux,pci-probe-only completely
prevents any PCI reconfiguration from occurring under the OS, including
what is needed to support PCI hotplug.

Since the primary use case was OS access to the GOP framebuffer (which
breaks when the framebuffer BAR is moved when the OS reconfigures the
PCI), we can undo this change now that ArmVirtQemu has moved to a GOP
implementation that does not expose a raw framebuffer in the first place.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c | 38 --------------------
 1 file changed, 38 deletions(-)

diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
index 5063782bb392..669c90355889 100644
--- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
+++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
@@ -79,42 +79,6 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
 // Implementation
 //
 
-STATIC
-VOID
-SetLinuxPciProbeOnlyProperty (
-  IN FDT_CLIENT_PROTOCOL         *FdtClient
-  )
-{
-  INT32         Node;
-  UINT32        Tmp;
-  EFI_STATUS    Status;
-
-  if (!FeaturePcdGet (PcdPureAcpiBoot)) {
-    //
-    // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI
-    // setup we will perform in the firmware is honored by the Linux OS,
-    // rather than torn down and done from scratch. This is generally a more
-    // sensible approach, and aligns with what ACPI based OSes do typically.
-    //
-    // In case we are exposing an emulated VGA PCI device to the guest, which
-    // may subsequently get exposed via the Graphics Output protocol and
-    // driven as an efifb by Linux, we need this setting to prevent the
-    // framebuffer from becoming unresponsive.
-    //
-    Status = FdtClient->GetOrInsertChosenNode (FdtClient, &Node);
-
-    if (!EFI_ERROR (Status)) {
-      Tmp = SwapBytes32 (1);
-      Status = FdtClient->SetNodeProperty (FdtClient, Node,
-                            "linux,pci-probe-only", &Tmp, sizeof (Tmp));
-    }
-    if (EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_WARN,
-        "Failed to set /chosen/linux,pci-probe-only property\n"));
-    }
-  }
-}
-
 //
 // We expect the "ranges" property of "pci-host-ecam-generic" to consist of
 // records like this.
@@ -293,8 +257,6 @@ ProcessPciHost (
   //
   ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
 
-  SetLinuxPciProbeOnlyProperty (FdtClient);
-
   DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
     "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
     ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
  2016-08-22  6:35 ` [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property Ard Biesheuvel
@ 2016-08-22  6:35 ` Ard Biesheuvel
  2016-08-24 15:01   ` Laszlo Ersek
  2016-08-22  6:35 ` [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe Ard Biesheuvel
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

Implement PciHostBridgeLib for DT platforms that expose a PCI root bridge
via a pci-host-ecam-generic DT node. The DT parsing logic is copied from
the PciHostBridgeDxe implementation in ArmVirtPkg, with the one notable
difference that we don't set the various legacy PCI attributes for IDE
and VGA I/O ranges.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c   | 400 ++++++++++++++++++++
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf |  56 +++
 2 files changed, 456 insertions(+)

diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
new file mode 100644
index 000000000000..887ddb01f586
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
@@ -0,0 +1,400 @@
+/** @file
+  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
+
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which accompanies this
+  distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <PiDxe.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#pragma pack(1)
+typedef struct {
+  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+  {
+    {
+      ACPI_DEVICE_PATH,
+      ACPI_DP,
+      {
+        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+      }
+    },
+    EISA_PNP_ID(0x0A08), // PCI Express
+    0
+  },
+
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      END_DEVICE_PATH_LENGTH,
+      0
+    }
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+  L"Mem", L"I/O", L"Bus"
+};
+
+//
+// We expect the "ranges" property of "pci-host-ecam-generic" to consist of
+// records like this.
+//
+#pragma pack (1)
+typedef struct {
+  UINT32 Type;
+  UINT64 ChildBase;
+  UINT64 CpuBase;
+  UINT64 Size;
+} DTB_PCI_HOST_RANGE_RECORD;
+#pragma pack ()
+
+#define DTB_PCI_HOST_RANGE_RELOCATABLE  BIT31
+#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
+#define DTB_PCI_HOST_RANGE_ALIASED      BIT29
+#define DTB_PCI_HOST_RANGE_MMIO32       BIT25
+#define DTB_PCI_HOST_RANGE_MMIO64       (BIT25 | BIT24)
+#define DTB_PCI_HOST_RANGE_IO           BIT24
+#define DTB_PCI_HOST_RANGE_TYPEMASK     (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
+
+STATIC
+EFI_STATUS
+ProcessPciHost (
+  OUT  UINT64    *IoBase,
+  OUT  UINT64    *IoSize,
+  OUT  UINT64    *IoTranslation,
+  OUT  UINT64    *MmioBase,
+  OUT  UINT64    *MmioSize,
+  OUT  UINT64    *MmioTranslation,
+  OUT  UINT32    *BusMin,
+  OUT  UINT32    *BusMax
+  )
+{
+  FDT_CLIENT_PROTOCOL         *FdtClient;
+  INT32                       Node;
+  UINT64                      ConfigBase, ConfigSize;
+  CONST VOID                  *Prop;
+  UINT32                      Len;
+  UINT32                      RecordIdx;
+  EFI_STATUS                  Status;
+
+  //
+  // The following output arguments are initialized only in
+  // order to suppress '-Werror=maybe-uninitialized' warnings
+  // *incorrectly* emitted by some gcc versions.
+  //
+  *IoBase = 0;
+  *IoTranslation = 0;
+  *MmioBase = 0;
+  *MmioTranslation = 0;
+  *BusMin = 0;
+  *BusMax = 0;
+
+  //
+  // *IoSize and *MmioSize are initialized to zero because the logic below
+  // requires it. However, since they are also affected by the issue reported
+  // above, they are initialized early.
+  //
+  *IoSize = 0;
+  *MmioSize = 0;
+
+  Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
+                  (VOID **)&FdtClient);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",
+                        &Node);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO,
+      "%a: No 'pci-host-ecam-generic' compatible DT node found\n",
+      __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG_CODE (
+    INT32 Tmp;
+
+    //
+    // A DT can legally describe multiple PCI host bridges, but we are not
+    // equipped to deal with that. So assert that there is only one.
+    //
+    Status = FdtClient->FindNextCompatibleNode (FdtClient,
+                          "pci-host-ecam-generic", Node, &Tmp);
+    ASSERT (Status == EFI_NOT_FOUND);
+  );
+
+  Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);
+  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {
+    DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",
+      __FUNCTION__));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  //
+  // Fetch the ECAM window.
+  //
+  ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);
+  ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);
+
+  //
+  // Fetch the bus range (note: inclusive).
+  //
+  Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,
+                        &Len);
+  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {
+    DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",
+      __FUNCTION__));
+    return EFI_PROTOCOL_ERROR;
+  }
+  *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);
+  *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);
+
+  //
+  // Sanity check: the config space must accommodate all 4K register bytes of
+  // all 8 functions of all 32 devices of all buses.
+  //
+  if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||
+      DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {
+    DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",
+      __FUNCTION__));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  //
+  // Iterate over "ranges".
+  //
+  Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);
+  if (EFI_ERROR (Status) || Len == 0 ||
+      Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {
+    DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);
+       ++RecordIdx) {
+    CONST DTB_PCI_HOST_RANGE_RECORD *Record;
+
+    Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;
+    switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {
+    case DTB_PCI_HOST_RANGE_IO:
+      *IoBase = SwapBytes64 (Record->ChildBase);
+      *IoSize = SwapBytes64 (Record->Size);
+      *IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;
+      break;
+
+    case DTB_PCI_HOST_RANGE_MMIO32:
+      *MmioBase = SwapBytes64 (Record->ChildBase);
+      *MmioSize = SwapBytes64 (Record->Size);
+      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
+
+      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
+          *MmioBase + *MmioSize > SIZE_4GB) {
+        DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
+        return EFI_PROTOCOL_ERROR;
+      }
+
+      if (*MmioTranslation != 0) {
+        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
+          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
+        return EFI_UNSUPPORTED;
+      }
+
+      break;
+    }
+  }
+  if (*IoSize == 0 || *MmioSize == 0) {
+    DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
+      (*IoSize == 0) ? "IO" : "MMIO32"));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  //
+  // The dynamic PCD PcdPciExpressBaseAddress should have already been set,
+  // and should match the value we found in the DT node.
+  //
+  ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
+
+  DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
+    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
+    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
+    *MmioSize, *MmioTranslation));
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Return all the root bridge instances in an array.
+
+  @param Count  Return the count of root bridge instances.
+
+  @return All the root bridge instances in an array.
+          The array should be passed into PciHostBridgeFreeRootBridges()
+          when it's not used.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+  UINTN *Count
+  )
+{
+  PCI_ROOT_BRIDGE     *RootBridge;
+  UINT64              IoBase, IoSize, IoTranslation;
+  UINT64              Mmio32Base, Mmio32Size, Mmio32Translation;
+  UINT32              BusMin, BusMax;
+  EFI_STATUS          Status;
+
+  if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {
+    DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));
+
+    *Count = 0;
+    return NULL;
+  }
+
+  Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &Mmio32Base,
+             &Mmio32Size, &Mmio32Translation, &BusMin, &BusMax);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO,
+      "%a: failed to discover PCI host bridge: %s not present\n",
+      __FUNCTION__, Status));
+    *Count = 0;
+    return NULL;
+  }
+
+  PcdSet64 (PcdPciIoTranslation, IoTranslation);
+
+  *Count = 1;
+  RootBridge = AllocateZeroPool (*Count * sizeof *RootBridge);
+
+  RootBridge->Segment     = 0;
+  RootBridge->Supports    = 0;
+  RootBridge->Attributes  = RootBridge->Supports;
+
+  RootBridge->DmaAbove4G  = TRUE;
+
+  RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
+                                      EFI_PCI_HOST_BRIDGE_MEM64_DECODE ;
+
+  RootBridge->Bus.Base              = BusMin;
+  RootBridge->Bus.Limit             = BusMax;
+  RootBridge->Io.Base               = IoBase;
+  RootBridge->Io.Limit              = IoBase + IoSize - 1;
+  RootBridge->Mem.Base              = Mmio32Base;
+  RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
+  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
+  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;
+
+  //
+  // No separate ranges for prefetchable and non-prefetchable BARs
+  //
+  RootBridge->PMem.Base             = MAX_UINT64;
+  RootBridge->PMem.Limit            = 0;
+  RootBridge->PMemAbove4G.Base      = MAX_UINT64;
+  RootBridge->PMemAbove4G.Limit     = 0;
+
+  ASSERT (FixedPcdGet64 (PcdPciMmio32Translation) == 0);
+  ASSERT (FixedPcdGet64 (PcdPciMmio64Translation) == 0);
+
+  RootBridge->NoExtendedConfigSpace = FALSE;
+
+  RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
+
+  return RootBridge;
+}
+
+/**
+  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
+
+  @param Bridges The root bridge instances array.
+  @param Count   The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeFreeRootBridges (
+  PCI_ROOT_BRIDGE *Bridges,
+  UINTN           Count
+  )
+{
+  FreePool (Bridges);
+}
+
+/**
+  Inform the platform that the resource conflict happens.
+
+  @param HostBridgeHandle Handle of the Host Bridge.
+  @param Configuration    Pointer to PCI I/O and PCI memory resource
+                          descriptors. The Configuration contains the resources
+                          for all the root bridges. The resource for each root
+                          bridge is terminated with END descriptor and an
+                          additional END is appended indicating the end of the
+                          entire resources. The resource descriptor field
+                          values follow the description in
+                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                          .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeResourceConflict (
+  EFI_HANDLE                        HostBridgeHandle,
+  VOID                              *Configuration
+  )
+{
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+  UINTN                             RootBridgeIndex;
+  DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+  RootBridgeIndex = 0;
+  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+    DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+      ASSERT (Descriptor->ResType <
+              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
+               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
+               )
+              );
+      DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+              Descriptor->AddrLen, Descriptor->AddrRangeMax
+              ));
+      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+        DEBUG ((EFI_D_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
+                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+                ((Descriptor->SpecificFlag &
+                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+                  ) != 0) ? L" (Prefetchable)" : L""
+                ));
+      }
+    }
+    //
+    // Skip the END descriptor for root bridge
+    //
+    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+                   );
+  }
+}
diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
new file mode 100644
index 000000000000..16beef0c2425
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
@@ -0,0 +1,56 @@
+## @file
+#  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
+#
+#  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
+#
+#  This program and the accompanying materials are licensed and made available
+#  under the terms and conditions of the BSD License which accompanies this
+#  distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+#  IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AmdStyxPciHostBridgeLib
+  FILE_GUID                      = 05E7AB83-EF8D-482D-80F8-905B73377A15
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PciHostBridgeLib
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+#  VALID_ARCHITECTURES           = AARCH64
+#
+
+[Sources]
+  FdtPciHostBridgeLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  PciPcdProducerLib
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdPciMmio32Translation
+  gArmTokenSpaceGuid.PcdPciMmio64Translation
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gArmTokenSpaceGuid.PcdPciIoTranslation
+
+[Depex]
+  gFdtClientProtocolGuid
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
  2016-08-22  6:35 ` [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property Ard Biesheuvel
  2016-08-22  6:35 ` [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib Ard Biesheuvel
@ 2016-08-22  6:35 ` Ard Biesheuvel
  2016-08-23 18:04   ` Ard Biesheuvel
  2016-08-22  6:35 ` [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support Ard Biesheuvel
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

Wire up the FdtPciHostBridgeLib introduced in the previous patch
to the generic PciHostBridgeDxe implementation, and drop the special
ArmVirtPkg version. The former's dependency on gEfiCpuIo2ProtocolGuid
is satisfied by adding ArmPciCpuIo2Dxe.inf as well, and adding the PCD
gArmTokenSpaceGuid.PcdPciIoTranslation as a dynamic PCD.

In terms of functionality, the only effect this change should have is
that we will no longer use bounce buffers for DMA above 4 GB. Other
than that, no functional changes are intended.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmVirtPkg/ArmVirtQemu.dsc                                   | 7 ++++++-
 ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc                         | 3 ++-
 ArmVirtPkg/ArmVirtQemuKernel.dsc                             | 7 ++++++-
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 4 ++--
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 1d459756f61b..ddc72e7044f7 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -69,6 +69,8 @@ [LibraryClasses.common]
   QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
   PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
+  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
@@ -210,6 +212,8 @@ [PcdsDynamicDefault.common]
   # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
 
+  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
+
   #
   # Set video resolution for boot options and for text setup.
   # PlatformDxe can set the former at runtime.
@@ -363,7 +367,8 @@ [Components.common]
   #
   # PCI support
   #
-  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
     <LibraryClasses>
       NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
index 01e650d9e333..c56188f347ec 100644
--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
@@ -151,7 +151,8 @@ [FV.FvMain]
   #
   # PCI support
   #
-  INF ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
+  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
   INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
   INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
   INF OvmfPkg/Virtio10Dxe/Virtio10.inf
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
index 99d2feba202b..305aa5bacb32 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -71,6 +71,8 @@ [LibraryClasses.common]
   QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
   PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
+  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
@@ -203,6 +205,8 @@ [PcdsDynamicDefault.common]
   # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
   gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
 
+  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
+
   #
   # Set video resolution for boot options and for text setup.
   # PlatformDxe can set the former at runtime.
@@ -349,7 +353,8 @@ [Components.common]
   #
   # PCI support
   #
-  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
     <LibraryClasses>
       NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
index 887ddb01f586..0aff149e8029 100644
--- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
+++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
@@ -304,8 +304,8 @@ PciHostBridgeGetRootBridges (
   RootBridge->Io.Limit              = IoBase + IoSize - 1;
   RootBridge->Mem.Base              = Mmio32Base;
   RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
-  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
-  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;
+  RootBridge->MemAbove4G.Base       = MAX_UINT64;
+  RootBridge->MemAbove4G.Limit      = 0;
 
   //
   // No separate ranges for prefetchable and non-prefetchable BARs
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2016-08-22  6:35 ` [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe Ard Biesheuvel
@ 2016-08-22  6:35 ` Ard Biesheuvel
  2016-08-31 14:06   ` Laszlo Ersek
  2016-08-22  6:35 ` [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe Ard Biesheuvel
  2016-08-22 11:58 ` [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Laszlo Ersek
  5 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

If the pci-host-ecam-generic DT node describes a 64-bit MMIO region,
account for it in the PCI_ROOT_BRIDGE description that we return to
the generic PciHostBridgeDxe implementation, which will be able to
allocate BARs from it without any further changes.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 59 +++++++++++++-------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
index 0aff149e8029..74fda4d23fa3 100644
--- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
+++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
@@ -87,9 +87,10 @@ ProcessPciHost (
   OUT  UINT64    *IoBase,
   OUT  UINT64    *IoSize,
   OUT  UINT64    *IoTranslation,
-  OUT  UINT64    *MmioBase,
-  OUT  UINT64    *MmioSize,
-  OUT  UINT64    *MmioTranslation,
+  OUT  UINT64    *Mmio32Base,
+  OUT  UINT64    *Mmio32Size,
+  OUT  UINT64    *Mmio64Base,
+  OUT  UINT64    *Mmio64Size,
   OUT  UINT32    *BusMin,
   OUT  UINT32    *BusMax
   )
@@ -101,6 +102,7 @@ ProcessPciHost (
   UINT32                      Len;
   UINT32                      RecordIdx;
   EFI_STATUS                  Status;
+  UINT64                      MmioTranslation;
 
   //
   // The following output arguments are initialized only in
@@ -109,8 +111,8 @@ ProcessPciHost (
   //
   *IoBase = 0;
   *IoTranslation = 0;
-  *MmioBase = 0;
-  *MmioTranslation = 0;
+  *Mmio32Base = 0;
+  *Mmio64Base = MAX_UINT64;
   *BusMin = 0;
   *BusMax = 0;
 
@@ -120,7 +122,8 @@ ProcessPciHost (
   // above, they are initialized early.
   //
   *IoSize = 0;
-  *MmioSize = 0;
+  *Mmio32Size = 0;
+  *Mmio64Size = 0;
 
   Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
                   (VOID **)&FdtClient);
@@ -207,26 +210,39 @@ ProcessPciHost (
       break;
 
     case DTB_PCI_HOST_RANGE_MMIO32:
-      *MmioBase = SwapBytes64 (Record->ChildBase);
-      *MmioSize = SwapBytes64 (Record->Size);
-      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
+      *Mmio32Base = SwapBytes64 (Record->ChildBase);
+      *Mmio32Size = SwapBytes64 (Record->Size);
+      MmioTranslation = SwapBytes64 (Record->CpuBase) - *Mmio32Base;
 
-      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
-          *MmioBase + *MmioSize > SIZE_4GB) {
+      if (*Mmio32Base > MAX_UINT32 || *Mmio32Size > MAX_UINT32 ||
+          *Mmio32Base + *Mmio32Size > SIZE_4GB) {
         DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
         return EFI_PROTOCOL_ERROR;
       }
 
-      if (*MmioTranslation != 0) {
+      if (MmioTranslation != 0) {
         DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
-          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
+          "0x%Lx\n", __FUNCTION__, MmioTranslation));
+        return EFI_UNSUPPORTED;
+      }
+
+      break;
+
+    case DTB_PCI_HOST_RANGE_MMIO64:
+      *Mmio64Base = SwapBytes64 (Record->ChildBase);
+      *Mmio64Size = SwapBytes64 (Record->Size);
+      MmioTranslation = SwapBytes64 (Record->CpuBase) - *Mmio64Base;
+
+      if (MmioTranslation != 0) {
+        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO64 translation "
+          "0x%Lx\n", __FUNCTION__, MmioTranslation));
         return EFI_UNSUPPORTED;
       }
 
       break;
     }
   }
-  if (*IoSize == 0 || *MmioSize == 0) {
+  if (*IoSize == 0 || *Mmio32Size == 0) {
     DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
       (*IoSize == 0) ? "IO" : "MMIO32"));
     return EFI_PROTOCOL_ERROR;
@@ -239,9 +255,9 @@ ProcessPciHost (
   ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
 
   DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
-    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
-    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
-    *MmioSize, *MmioTranslation));
+    "Io[0x%Lx+0x%Lx)@0x%Lx Mem32[0x%Lx+0x%Lx) Mem64[0x%Lx+0x%Lx)\n",
+    __FUNCTION__, ConfigBase, ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize,
+    *IoTranslation, *Mmio32Base, *Mmio32Size, *Mmio64Base, *Mmio64Size));
   return EFI_SUCCESS;
 }
 
@@ -263,7 +279,8 @@ PciHostBridgeGetRootBridges (
 {
   PCI_ROOT_BRIDGE     *RootBridge;
   UINT64              IoBase, IoSize, IoTranslation;
-  UINT64              Mmio32Base, Mmio32Size, Mmio32Translation;
+  UINT64              Mmio32Base, Mmio32Size;
+  UINT64              Mmio64Base, Mmio64Size;
   UINT32              BusMin, BusMax;
   EFI_STATUS          Status;
 
@@ -275,7 +292,7 @@ PciHostBridgeGetRootBridges (
   }
 
   Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &Mmio32Base,
-             &Mmio32Size, &Mmio32Translation, &BusMin, &BusMax);
+             &Mmio32Size, &Mmio64Base, &Mmio64Size, &BusMin, &BusMax);
   if (EFI_ERROR (Status)) {
     DEBUG ((EFI_D_INFO,
       "%a: failed to discover PCI host bridge: %s not present\n",
@@ -304,8 +321,8 @@ PciHostBridgeGetRootBridges (
   RootBridge->Io.Limit              = IoBase + IoSize - 1;
   RootBridge->Mem.Base              = Mmio32Base;
   RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
-  RootBridge->MemAbove4G.Base       = MAX_UINT64;
-  RootBridge->MemAbove4G.Limit      = 0;
+  RootBridge->MemAbove4G.Base       = Mmio64Base;
+  RootBridge->MemAbove4G.Limit      = Mmio64Base + Mmio64Size - 1;
 
   //
   // No separate ranges for prefetchable and non-prefetchable BARs
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2016-08-22  6:35 ` [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support Ard Biesheuvel
@ 2016-08-22  6:35 ` Ard Biesheuvel
  2016-08-31 14:11   ` Laszlo Ersek
  2016-08-22 11:58 ` [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Laszlo Ersek
  5 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-22  6:35 UTC (permalink / raw)
  To: edk2-devel, lersek; +Cc: Ard Biesheuvel

This code is now no longer used, so remove it.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c      | 1458 -------------
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h      |  499 -----
 ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf |   64 -
 ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c    | 2144 --------------------
 4 files changed, 4165 deletions(-)

diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
deleted file mode 100644
index 669c90355889..000000000000
--- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
+++ /dev/null
@@ -1,1458 +0,0 @@
-/** @file
-  Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
-
-Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are
-licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "PciHostBridge.h"
-
-//
-// Hard code: Root Bridge Number within the host bridge
-//            Root Bridge's attribute
-//            Root Bridge's device path
-//            Root Bridge's resource aperture
-//
-UINTN RootBridgeNumber[1] = { 1 };
-
-UINT64 RootBridgeAttribute[1][1] = { { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM } };
-
-EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
-  {
-    {
-      {
-        {
-          ACPI_DEVICE_PATH,
-          ACPI_DP,
-          {
-            (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
-            (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
-          }
-        },
-        EISA_PNP_ID(0x0A03),
-        0
-      },
-
-      {
-        END_DEVICE_PATH_TYPE,
-        END_ENTIRE_DEVICE_PATH_SUBTYPE,
-        {
-          END_DEVICE_PATH_LENGTH,
-          0
-        }
-      }
-    }
-  }
-};
-
-STATIC PCI_ROOT_BRIDGE_RESOURCE_APERTURE  mResAperture[1][1];
-
-EFI_HANDLE mDriverImageHandle;
-
-PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
-  PCI_HOST_BRIDGE_SIGNATURE,  // Signature
-  NULL,                       // HostBridgeHandle
-  0,                          // RootBridgeNumber
-  {NULL, NULL},               // Head
-  FALSE,                      // ResourceSubiteed
-  TRUE,                       // CanRestarted
-  {
-    NotifyPhase,
-    GetNextRootBridge,
-    GetAttributes,
-    StartBusEnumeration,
-    SetBusNumbers,
-    SubmitResources,
-    GetProposedResources,
-    PreprocessController
-  }
-};
-
-//
-// Implementation
-//
-
-//
-// We expect the "ranges" property of "pci-host-ecam-generic" to consist of
-// records like this.
-//
-#pragma pack (1)
-typedef struct {
-  UINT32 Type;
-  UINT64 ChildBase;
-  UINT64 CpuBase;
-  UINT64 Size;
-} DTB_PCI_HOST_RANGE_RECORD;
-#pragma pack ()
-
-#define DTB_PCI_HOST_RANGE_RELOCATABLE  BIT31
-#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
-#define DTB_PCI_HOST_RANGE_ALIASED      BIT29
-#define DTB_PCI_HOST_RANGE_MMIO32       BIT25
-#define DTB_PCI_HOST_RANGE_MMIO64       (BIT25 | BIT24)
-#define DTB_PCI_HOST_RANGE_IO           BIT24
-#define DTB_PCI_HOST_RANGE_TYPEMASK     (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
-
-STATIC
-EFI_STATUS
-ProcessPciHost (
-  OUT  UINT64    *IoBase,
-  OUT  UINT64    *IoSize,
-  OUT  UINT64    *IoTranslation,
-  OUT  UINT64    *MmioBase,
-  OUT  UINT64    *MmioSize,
-  OUT  UINT64    *MmioTranslation,
-  OUT  UINT32    *BusMin,
-  OUT  UINT32    *BusMax
-  )
-{
-  FDT_CLIENT_PROTOCOL         *FdtClient;
-  INT32                       Node;
-  UINT64                      ConfigBase, ConfigSize;
-  CONST VOID                  *Prop;
-  UINT32                      Len;
-  UINT32                      RecordIdx;
-  EFI_STATUS                  Status;
-
-  //
-  // The following output arguments are initialized only in
-  // order to suppress '-Werror=maybe-uninitialized' warnings
-  // *incorrectly* emitted by some gcc versions.
-  //
-  *IoBase = 0;
-  *IoTranslation = 0;
-  *MmioBase = 0;
-  *MmioTranslation = 0;
-  *BusMin = 0;
-  *BusMax = 0;
-
-  //
-  // *IoSize and *MmioSize are initialized to zero because the logic below
-  // requires it. However, since they are also affected by the issue reported
-  // above, they are initialized early.
-  //
-  *IoSize = 0;
-  *MmioSize = 0;
-
-  Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
-                  (VOID **)&FdtClient);
-  ASSERT_EFI_ERROR (Status);
-
-  Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",
-                        &Node);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_INFO,
-      "%a: No 'pci-host-ecam-generic' compatible DT node found\n",
-      __FUNCTION__));
-    return EFI_NOT_FOUND;
-  }
-
-  DEBUG_CODE (
-    INT32 Tmp;
-
-    //
-    // A DT can legally describe multiple PCI host bridges, but we are not
-    // equipped to deal with that. So assert that there is only one.
-    //
-    Status = FdtClient->FindNextCompatibleNode (FdtClient,
-                          "pci-host-ecam-generic", Node, &Tmp);
-    ASSERT (Status == EFI_NOT_FOUND);
-  );
-
-  Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);
-  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {
-    DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",
-      __FUNCTION__));
-    return EFI_PROTOCOL_ERROR;
-  }
-
-  //
-  // Fetch the ECAM window.
-  //
-  ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);
-  ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);
-
-  //
-  // Fetch the bus range (note: inclusive).
-  //
-  Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,
-                        &Len);
-  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {
-    DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",
-      __FUNCTION__));
-    return EFI_PROTOCOL_ERROR;
-  }
-  *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);
-  *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);
-
-  //
-  // Sanity check: the config space must accommodate all 4K register bytes of
-  // all 8 functions of all 32 devices of all buses.
-  //
-  if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||
-      DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {
-    DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",
-      __FUNCTION__));
-    return EFI_PROTOCOL_ERROR;
-  }
-
-  //
-  // Iterate over "ranges".
-  //
-  Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);
-  if (EFI_ERROR (Status) || Len == 0 ||
-      Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {
-    DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));
-    return EFI_PROTOCOL_ERROR;
-  }
-
-  for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);
-       ++RecordIdx) {
-    CONST DTB_PCI_HOST_RANGE_RECORD *Record;
-
-    Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;
-    switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {
-    case DTB_PCI_HOST_RANGE_IO:
-      *IoBase = SwapBytes64 (Record->ChildBase);
-      *IoSize = SwapBytes64 (Record->Size);
-      *IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;
-      break;
-
-    case DTB_PCI_HOST_RANGE_MMIO32:
-      *MmioBase = SwapBytes64 (Record->ChildBase);
-      *MmioSize = SwapBytes64 (Record->Size);
-      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
-
-      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
-          *MmioBase + *MmioSize > SIZE_4GB) {
-        DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
-        return EFI_PROTOCOL_ERROR;
-      }
-
-      if (*MmioTranslation != 0) {
-        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
-          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
-        return EFI_UNSUPPORTED;
-      }
-
-      break;
-    }
-  }
-  if (*IoSize == 0 || *MmioSize == 0) {
-    DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
-      (*IoSize == 0) ? "IO" : "MMIO32"));
-    return EFI_PROTOCOL_ERROR;
-  }
-
-  //
-  // The dynamic PCD PcdPciExpressBaseAddress should have already been set,
-  // and should match the value we found in the DT node.
-  //
-  ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
-
-  DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
-    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
-    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
-    *MmioSize, *MmioTranslation));
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Entry point of this driver
-
-  @param ImageHandle     Handle of driver image
-  @param SystemTable     Point to EFI_SYSTEM_TABLE
-
-  @retval EFI_ABORTED           PCI host bridge not present
-  @retval EFI_OUT_OF_RESOURCES  Can not allocate memory resource
-  @retval EFI_DEVICE_ERROR      Can not install the protocol instance
-  @retval EFI_SUCCESS           Success to initialize the Pci host bridge.
-**/
-EFI_STATUS
-EFIAPI
-InitializePciHostBridge (
-  IN EFI_HANDLE        ImageHandle,
-  IN EFI_SYSTEM_TABLE  *SystemTable
-  )
-{
-  UINT64                      MmioAttributes;
-  EFI_STATUS                  Status;
-  UINTN                       Loop1;
-  UINTN                       Loop2;
-  PCI_HOST_BRIDGE_INSTANCE    *HostBridge;
-  PCI_ROOT_BRIDGE_INSTANCE    *PrivateData;
-  UINT64                      IoBase, IoSize, IoTranslation;
-  UINT64                      MmioBase, MmioSize, MmioTranslation;
-  UINT32                      BusMin, BusMax;
-
-  if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {
-    DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));
-    return EFI_ABORTED;
-  }
-
-  Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &MmioBase,
-             &MmioSize, &MmioTranslation, &BusMin, &BusMax);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  mDriverImageHandle = ImageHandle;
-
-  mResAperture[0][0].BusBase  = BusMin;
-  mResAperture[0][0].BusLimit = BusMax;
-
-  mResAperture[0][0].MemBase  = MmioBase;
-  mResAperture[0][0].MemLimit = MmioBase + MmioSize - 1;
-
-  mResAperture[0][0].IoBase        = IoBase;
-  mResAperture[0][0].IoLimit       = IoBase + IoSize - 1;
-  mResAperture[0][0].IoTranslation = IoTranslation;
-
-  //
-  // Add IO and MMIO memory space, so that resources can be allocated in the
-  // EfiPciHostBridgeAllocateResources phase.
-  //
-  Status = gDS->AddIoSpace (
-                  EfiGcdIoTypeIo,
-                  IoBase,
-                  IoSize
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  MmioAttributes = EFI_MEMORY_UC;
-
-  Status = gDS->AddMemorySpace (
-                  EfiGcdMemoryTypeMemoryMappedIo,
-                  MmioBase,
-                  MmioSize,
-                  MmioAttributes
-                  );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "%a: AddMemorySpace: %r\n", __FUNCTION__, Status));
-    return Status;
-  }
-
-  Status = gDS->SetMemorySpaceAttributes (
-                  MmioBase,
-                  MmioSize,
-                  MmioAttributes
-                  );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "%a: SetMemorySpaceAttributes: %r\n", __FUNCTION__,
-      Status));
-    return Status;
-  }
-
-  //
-  // Create Host Bridge Device Handle
-  //
-  for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
-    HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
-    if (HostBridge == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-
-    HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
-    InitializeListHead (&HostBridge->Head);
-
-    Status = gBS->InstallMultipleProtocolInterfaces (
-                    &HostBridge->HostBridgeHandle,
-                    &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
-                    NULL
-                    );
-    if (EFI_ERROR (Status)) {
-      FreePool (HostBridge);
-      return EFI_DEVICE_ERROR;
-    }
-
-    //
-    // Create Root Bridge Device Handle in this Host Bridge
-    //
-
-    for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
-      PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
-      if (PrivateData == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
-      PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
-
-      RootBridgeConstructor (
-        &PrivateData->Io,
-        HostBridge->HostBridgeHandle,
-        RootBridgeAttribute[Loop1][Loop2],
-        &mResAperture[Loop1][Loop2]
-        );
-
-      Status = gBS->InstallMultipleProtocolInterfaces(
-                      &PrivateData->Handle,
-                      &gEfiDevicePathProtocolGuid,      PrivateData->DevicePath,
-                      &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
-                      NULL
-                      );
-      if (EFI_ERROR (Status)) {
-        FreePool(PrivateData);
-        return EFI_DEVICE_ERROR;
-      }
-
-      InsertTailList (&HostBridge->Head, &PrivateData->Link);
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-   These are the notifications from the PCI bus driver that it is about to enter a certain
-   phase of the PCI enumeration process.
-
-   This member function can be used to notify the host bridge driver to perform specific actions,
-   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
-   Eight notification points are defined at this time. See belows:
-   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
-                                          structures. The PCI enumerator should issue this notification
-                                          before starting a fresh enumeration process. Enumeration cannot
-                                          be restarted after sending any other notification such as
-                                          EfiPciHostBridgeBeginBusAllocation.
-   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
-                                          required here. This notification can be used to perform any
-                                          chipset-specific programming.
-   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
-                                          specific action is required here. This notification can be used to
-                                          perform any chipset-specific programming.
-   EfiPciHostBridgeBeginResourceAllocation
-                                          The resource allocation phase is about to begin. No specific
-                                          action is required here. This notification can be used to perform
-                                          any chipset-specific programming.
-   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
-                                          root bridges. These resource settings are returned on the next call to
-                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of
-                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
-                                          for gathering I/O and memory requests for
-                                          all the PCI root bridges and submitting these requests using
-                                          SubmitResources(). This function pads the resource amount
-                                          to suit the root bridge hardware, takes care of dependencies between
-                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)
-                                          with the allocation request. In the case of padding, the allocated range
-                                          could be bigger than what was requested.
-   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
-                                          resources (proposed resources) for all the PCI root bridges. After the
-                                          hardware is programmed, reassigning resources will not be supported.
-                                          The bus settings are not affected.
-   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
-                                          root bridges and resets the I/O and memory apertures to their initial
-                                          state. The bus settings are not affected. If the request to allocate
-                                          resources fails, the PCI enumerator can use this notification to
-                                          deallocate previous resources, adjust the requests, and retry
-                                          allocation.
-   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
-                                          required here. This notification can be used to perform any chipsetspecific
-                                          programming.
-
-   @param[in] This                The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in] Phase               The phase during enumeration
-
-   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
-                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if
-                                  SubmitResources() has not been called for one or more
-                                  PCI root bridges before this call
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
-                                  for a Phase of EfiPciHostBridgeSetResources.
-   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
-                                  previously submitted resource requests cannot be fulfilled or
-                                  were only partially fulfilled.
-   @retval EFI_SUCCESS            The notification was accepted without any errors.
-
-**/
-EFI_STATUS
-EFIAPI
-NotifyPhase(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
-  )
-{
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  PCI_RESOURCE_TYPE                     Index;
-  LIST_ENTRY                            *List;
-  EFI_PHYSICAL_ADDRESS                  BaseAddress;
-  UINT64                                AddrLen;
-  UINTN                                 BitsOfAlignment;
-  EFI_STATUS                            Status;
-  EFI_STATUS                            ReturnStatus;
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-
-  switch (Phase) {
-
-  case EfiPciHostBridgeBeginEnumeration:
-    if (HostBridgeInstance->CanRestarted) {
-      //
-      // Reset the Each Root Bridge
-      //
-      List = HostBridgeInstance->Head.ForwardLink;
-
-      while (List != &HostBridgeInstance->Head) {
-        RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-        for (Index = TypeIo; Index < TypeMax; Index++) {
-          RootBridgeInstance->ResAllocNode[Index].Type      = Index;
-          RootBridgeInstance->ResAllocNode[Index].Base      = 0;
-          RootBridgeInstance->ResAllocNode[Index].Length    = 0;
-          RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
-        }
-
-        List = List->ForwardLink;
-      }
-
-      HostBridgeInstance->ResourceSubmited = FALSE;
-      HostBridgeInstance->CanRestarted     = TRUE;
-    } else {
-      //
-      // Can not restart
-      //
-      return EFI_NOT_READY;
-    }
-    break;
-
-  case EfiPciHostBridgeEndEnumeration:
-    break;
-
-  case EfiPciHostBridgeBeginBusAllocation:
-    //
-    // No specific action is required here, can perform any chipset specific programing
-    //
-    HostBridgeInstance->CanRestarted = FALSE;
-    break;
-
-  case EfiPciHostBridgeEndBusAllocation:
-    //
-    // No specific action is required here, can perform any chipset specific programing
-    //
-    //HostBridgeInstance->CanRestarted = FALSE;
-    break;
-
-  case EfiPciHostBridgeBeginResourceAllocation:
-    //
-    // No specific action is required here, can perform any chipset specific programing
-    //
-    //HostBridgeInstance->CanRestarted = FALSE;
-    break;
-
-  case EfiPciHostBridgeAllocateResources:
-    ReturnStatus = EFI_SUCCESS;
-    if (HostBridgeInstance->ResourceSubmited) {
-      //
-      // Take care of the resource dependencies between the root bridges
-      //
-      List = HostBridgeInstance->Head.ForwardLink;
-
-      while (List != &HostBridgeInstance->Head) {
-        RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-        for (Index = TypeIo; Index < TypeBus; Index++) {
-          if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
-
-            AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
-
-            //
-            // Get the number of '1' in Alignment.
-            //
-            BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1);
-
-            switch (Index) {
-
-              case TypeIo:
-                //
-                // It is impossible for this chipset to align 0xFFFF for IO16
-                // So clear it
-                //
-                if (BitsOfAlignment >= 16) {
-                  BitsOfAlignment = 0;
-                }
-
-                BaseAddress = mResAperture[0][0].IoLimit;
-                Status = gDS->AllocateIoSpace (
-                                EfiGcdAllocateMaxAddressSearchTopDown,
-                                EfiGcdIoTypeIo,
-                                BitsOfAlignment,
-                                AddrLen,
-                                &BaseAddress,
-                                mDriverImageHandle,
-                                NULL
-                                );
-
-                if (!EFI_ERROR (Status)) {
-                  RootBridgeInstance->ResAllocNode[Index].Base   = (UINTN)BaseAddress;
-                  RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
-                } else {
-                  ReturnStatus = Status;
-                  if (Status != EFI_OUT_OF_RESOURCES) {
-                    RootBridgeInstance->ResAllocNode[Index].Length = 0;
-                  }
-                }
-
-                break;
-
-
-              case TypeMem32:
-                //
-                // It is impossible for this chipset to align 0xFFFFFFFF for Mem32
-                // So clear it
-                //
-
-                if (BitsOfAlignment >= 32) {
-                  BitsOfAlignment = 0;
-                }
-
-                BaseAddress = mResAperture[0][0].MemLimit;
-                Status = gDS->AllocateMemorySpace (
-                                EfiGcdAllocateMaxAddressSearchTopDown,
-                                EfiGcdMemoryTypeMemoryMappedIo,
-                                BitsOfAlignment,
-                                AddrLen,
-                                &BaseAddress,
-                                mDriverImageHandle,
-                                NULL
-                                );
-
-                if (!EFI_ERROR (Status)) {
-                  // We were able to allocate the PCI memory
-                  RootBridgeInstance->ResAllocNode[Index].Base   = (UINTN)BaseAddress;
-                  RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
-
-                } else {
-                  // Not able to allocate enough PCI memory
-                  ReturnStatus = Status;
-
-                  if (Status != EFI_OUT_OF_RESOURCES) {
-                    RootBridgeInstance->ResAllocNode[Index].Length = 0;
-                  }
-                  ASSERT (FALSE);
-                }
-                break;
-
-              case TypePMem32:
-              case TypeMem64:
-              case TypePMem64:
-                  ReturnStatus = EFI_ABORTED;
-                  break;
-              default:
-                ASSERT (FALSE);
-                break;
-              }; //end switch
-          }
-        }
-
-        List = List->ForwardLink;
-      }
-
-      return ReturnStatus;
-    } else {
-      return EFI_NOT_READY;
-    }
-
-  case EfiPciHostBridgeSetResources:
-    break;
-
-  case EfiPciHostBridgeFreeResources:
-    ReturnStatus = EFI_SUCCESS;
-    List = HostBridgeInstance->Head.ForwardLink;
-    while (List != &HostBridgeInstance->Head) {
-      RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-      for (Index = TypeIo; Index < TypeBus; Index++) {
-        if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
-          AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
-          BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
-          switch (Index) {
-
-          case TypeIo:
-            Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
-            if (EFI_ERROR (Status)) {
-              ReturnStatus = Status;
-            }
-            break;
-
-          case TypeMem32:
-            Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
-            if (EFI_ERROR (Status)) {
-              ReturnStatus = Status;
-            }
-            break;
-
-          case TypePMem32:
-            break;
-
-          case TypeMem64:
-            break;
-
-          case TypePMem64:
-            break;
-
-          default:
-            ASSERT (FALSE);
-            break;
-
-          }; //end switch
-          RootBridgeInstance->ResAllocNode[Index].Type      = Index;
-          RootBridgeInstance->ResAllocNode[Index].Base      = 0;
-          RootBridgeInstance->ResAllocNode[Index].Length    = 0;
-          RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
-        }
-      }
-
-      List = List->ForwardLink;
-    }
-
-    HostBridgeInstance->ResourceSubmited = FALSE;
-    HostBridgeInstance->CanRestarted     = TRUE;
-    return ReturnStatus;
-
-  case EfiPciHostBridgeEndResourceAllocation:
-    HostBridgeInstance->CanRestarted = FALSE;
-    break;
-
-  default:
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
-
-   This function is called multiple times to retrieve the device handles of all the PCI root bridges that
-   are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
-   root bridges. On each call, the handle that was returned by the previous call is passed into the
-   interface, and on output the interface returns the device handle of the next PCI root bridge. The
-   caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-   for that root bridge. When there are no more PCI root bridges to report, the interface returns
-   EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
-   are returned by this function.
-   For D945 implementation, there is only one root bridge in PCI host bridge.
-
-   @param[in]       This              The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI root bridge.
-
-   @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
-                                  specific Host bridge and return EFI_SUCCESS.
-   @retval EFI_NOT_FOUND          Can not find the any more root bridge in specific host bridge.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
-                                  returned on a previous call to GetNextRootBridge().
-**/
-EFI_STATUS
-EFIAPI
-GetNextRootBridge(
-  IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN OUT   EFI_HANDLE                                       *RootBridgeHandle
-  )
-{
-  BOOLEAN                               NoRootBridge;
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-
-  NoRootBridge = TRUE;
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-
-  while (List != &HostBridgeInstance->Head) {
-    NoRootBridge = FALSE;
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (*RootBridgeHandle == NULL) {
-      //
-      // Return the first Root Bridge Handle of the Host Bridge
-      //
-      *RootBridgeHandle = RootBridgeInstance->Handle;
-      return EFI_SUCCESS;
-    } else {
-      if (*RootBridgeHandle == RootBridgeInstance->Handle) {
-        //
-        // Get next if have
-        //
-        List = List->ForwardLink;
-        if (List!=&HostBridgeInstance->Head) {
-          RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-          *RootBridgeHandle = RootBridgeInstance->Handle;
-          return EFI_SUCCESS;
-        } else {
-          return EFI_NOT_FOUND;
-        }
-      }
-    }
-
-    List = List->ForwardLink;
-  } //end while
-
-  if (NoRootBridge) {
-    return EFI_NOT_FOUND;
-  } else {
-    return EFI_INVALID_PARAMETER;
-  }
-}
-
-/**
-   Returns the allocation attributes of a PCI root bridge.
-
-   The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
-   from one PCI root bridge to another. These attributes are different from the decode-related
-   attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
-   RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
-   handles of all the root bridges that are associated with this host bridge must be obtained by calling
-   GetNextRootBridge(). The attributes are static in the sense that they do not change during or
-   after the enumeration process. The hardware may provide mechanisms to change the attributes on
-   the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
-   installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
-   "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
-   For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
-   include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
-   prefetchable memory.
-      Attribute                                 Description
-   ------------------------------------         ----------------------------------------------------------------------
-   EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM         If this bit is set, then the PCI root bridge does not support separate
-                                                windows for nonprefetchable and prefetchable memory. A PCI bus
-                                                driver needs to include requests for prefetchable memory in the
-                                                nonprefetchable memory pool.
-
-   EFI_PCI_HOST_BRIDGE_MEM64_DECODE             If this bit is set, then the PCI root bridge supports 64-bit memory
-                                                windows. If this bit is not set, the PCI bus driver needs to include
-                                                requests for a 64-bit memory address in the corresponding 32-bit
-                                                memory pool.
-
-   @param[in]   This               The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in which the caller is interested. Type
-                                   EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param[out]  Attributes         The pointer to attribte of root bridge, it is output parameter
-
-   @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
-   @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
-   @retval EFI_SUCCESS             Success to get attribute of interested root bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-GetAttributes(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT UINT64                                           *Attributes
-  )
-{
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-
-  if (Attributes == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      *Attributes = RootBridgeInstance->RootBridgeAttrib;
-      return EFI_SUCCESS;
-    }
-    List = List->ForwardLink;
-  }
-
-  //
-  // RootBridgeHandle is not an EFI_HANDLE
-  // that was returned on a previous call to GetNextRootBridge()
-  //
-  return EFI_INVALID_PARAMETER;
-}
-
-/**
-   Sets up the specified PCI root bridge for the bus enumeration process.
-
-   This member function sets up the root bridge for bus enumeration and returns the PCI bus range
-   over which the search should be performed in ACPI 2.0 resource descriptor format.
-
-   @param[in]   This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
-   @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
-   @param[out]  Configuration     Pointer to the pointer to the PCI bus resource descriptor.
-
-   @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
-   @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
-   @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
-
-**/
-EFI_STATUS
-EFIAPI
-StartBusEnumeration(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT VOID                                             **Configuration
-  )
-{
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  VOID                                  *Buffer;
-  UINT8                                 *Temp;
-  UINT64                                BusStart;
-  UINT64                                BusEnd;
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      //
-      // Set up the Root Bridge for Bus Enumeration
-      //
-      BusStart = RootBridgeInstance->BusBase;
-      BusEnd   = RootBridgeInstance->BusLimit;
-      //
-      // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
-      //
-
-      Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
-      if (Buffer == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      Temp = (UINT8 *)Buffer;
-
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len  = 0x2B;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
-      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
-
-      Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
-      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
-      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
-
-      *Configuration = Buffer;
-      return EFI_SUCCESS;
-    }
-    List = List->ForwardLink;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-/**
-   Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
-
-   This member function programs the specified PCI root bridge to decode the bus range that is
-   specified by the input parameter Configuration.
-   The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
-
-   @param[in] This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
-   @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be programmed
-   @param[in] Configuration     The pointer to the PCI bus resource descriptor
-
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI 2.0 resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI 2.0 bus resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource descriptors other than
-                                  bus descriptors.
-   @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid ACPI resource descriptors.
-   @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this root bridge.
-   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this root bridge.
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
-   @retval EFI_SUCCESS            The bus range for the PCI root bridge was programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-SetBusNumbers(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_HANDLE                                       RootBridgeHandle,
-  IN VOID                                             *Configuration
-  )
-{
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  UINT8                                 *Ptr;
-  UINTN                                 BusStart;
-  UINTN                                 BusEnd;
-  UINTN                                 BusLen;
-
-  if (Configuration == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Ptr = Configuration;
-
-  //
-  // Check the Configuration is valid
-  //
-  if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
-  if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  Ptr = Configuration;
-
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
-      BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
-      BusEnd = BusStart + BusLen - 1;
-
-      if (BusStart > BusEnd) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
-        return EFI_INVALID_PARAMETER;
-      }
-
-      //
-      // Update the Bus Range
-      //
-      RootBridgeInstance->ResAllocNode[TypeBus].Base   = BusStart;
-      RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
-      RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
-
-      //
-      // Program the Root Bridge Hardware
-      //
-
-      return EFI_SUCCESS;
-    }
-
-    List = List->ForwardLink;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-
-/**
-   Submits the I/O and memory resource requirements for the specified PCI root bridge.
-
-   This function is used to submit all the I/O and memory resources that are required by the specified
-   PCI root bridge. The input parameter Configuration is used to specify the following:
-   - The various types of resources that are required
-   - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
-   @param[in] This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory resource requirements are being submitted.
-   @param[in] Configuration     The pointer to the PCI I/O and PCI memory resource descriptor.
-
-   @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI root bridge were accepted.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI 2.0 resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or more resource types that are
-                                  not supported by this PCI root bridge. This error will happen if the caller
-                                  did not combine resources according to Attributes that were returned by
-                                  GetAllocAttributes().
-   @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
-   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for this PCI root bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-SubmitResources(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_HANDLE                                       RootBridgeHandle,
-  IN VOID                                             *Configuration
-  )
-{
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  UINT8                                 *Temp;
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
-  UINT64                                AddrLen;
-  UINT64                                Alignment;
-
-  //
-  // Check the input parameter: Configuration
-  //
-  if (Configuration == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  Temp = (UINT8 *)Configuration;
-  while ( *Temp == 0x8A) {
-    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
-  }
-  if (*Temp != 0x79) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Temp = (UINT8 *)Configuration;
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      for (;
-           *Temp == 0x8A;
-           Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)
-           ) {
-        Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
-
-        //
-        // Check Address Length
-        //
-        if (Ptr->AddrLen == 0) {
-          HostBridgeInstance->ResourceSubmited = TRUE;
-          continue;
-        }
-        if (Ptr->AddrLen > 0xffffffff) {
-          return EFI_INVALID_PARAMETER;
-        }
-
-        //
-        // Check address range alignment
-        //
-        if (Ptr->AddrRangeMax >= 0xffffffff || Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) {
-          return EFI_INVALID_PARAMETER;
-        }
-
-        switch (Ptr->ResType) {
-
-        case 0:
-
-          //
-          // Check invalid Address Sapce Granularity
-          //
-          if (Ptr->AddrSpaceGranularity != 32) {
-            return EFI_INVALID_PARAMETER;
-          }
-
-          //
-          // check the memory resource request is supported by PCI root bridge
-          //
-          if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
-               Ptr->SpecificFlag == 0x06) {
-            return EFI_INVALID_PARAMETER;
-          }
-
-          AddrLen = Ptr->AddrLen;
-          Alignment = Ptr->AddrRangeMax;
-          if (Ptr->AddrSpaceGranularity == 32) {
-            if (Ptr->SpecificFlag == 0x06) {
-              //
-              // Apply from GCD
-              //
-              RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
-            } else {
-              RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
-              RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
-              RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
-              HostBridgeInstance->ResourceSubmited = TRUE;
-            }
-          }
-
-          if (Ptr->AddrSpaceGranularity == 64) {
-            if (Ptr->SpecificFlag == 0x06) {
-              RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
-            } else {
-              RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
-            }
-          }
-          break;
-
-        case 1:
-          AddrLen = (UINTN) Ptr->AddrLen;
-          Alignment = (UINTN) Ptr->AddrRangeMax;
-          RootBridgeInstance->ResAllocNode[TypeIo].Length  = AddrLen;
-          RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
-          RootBridgeInstance->ResAllocNode[TypeIo].Status  = ResRequested;
-          HostBridgeInstance->ResourceSubmited = TRUE;
-          break;
-
-        default:
-            break;
-        };
-      }
-
-      return EFI_SUCCESS;
-    }
-
-    List = List->ForwardLink;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-/**
-   Returns the proposed resource settings for the specified PCI root bridge.
-
-   This member function returns the proposed resource settings for the specified PCI root bridge. The
-   proposed resource settings are prepared when NotifyPhase() is called with a Phase of
-   EfiPciHostBridgeAllocateResources. The output parameter Configuration
-   specifies the following:
-   - The various types of resources, excluding bus resources, that are allocated
-   - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
-   @param[in]  This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param[out] Configuration     The pointer to the pointer to the PCI I/O and memory resource descriptor.
-
-   @retval EFI_SUCCESS            The requested parameters were returned.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-GetProposedResources(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT VOID                                             **Configuration
-  )
-{
-  LIST_ENTRY                            *List;
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  UINTN                                 Index;
-  UINTN                                 Number;
-  VOID                                  *Buffer;
-  UINT8                                 *Temp;
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
-  UINT64                                ResStatus;
-
-  Buffer = NULL;
-  Number = 0;
-  //
-  // Get the Host Bridge Instance from the resource allocation protocol
-  //
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  //
-  // Enumerate the root bridges in this host bridge
-  //
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      for (Index = 0; Index < TypeBus; Index ++) {
-        if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
-          Number ++;
-        }
-      }
-
-      if (Number ==  0) {
-        EFI_ACPI_END_TAG_DESCRIPTOR *End;
-
-        End = AllocateZeroPool (sizeof *End);
-        if (End == NULL) {
-          return EFI_OUT_OF_RESOURCES;
-        }
-        End->Desc = ACPI_END_TAG_DESCRIPTOR;
-        *Configuration = End;
-        return EFI_SUCCESS;
-      }
-
-      Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
-      if (Buffer == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-
-      Temp = Buffer;
-      for (Index = 0; Index < TypeBus; Index ++) {
-        if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
-          Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
-          ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
-
-          switch (Index) {
-
-          case TypeIo:
-            //
-            // Io
-            //
-            Ptr->Desc = 0x8A;
-            Ptr->Len  = 0x2B;
-            Ptr->ResType = 1;
-            Ptr->GenFlag = 0;
-            Ptr->SpecificFlag = 0;
-            Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
-            Ptr->AddrRangeMax = 0;
-            Ptr->AddrTranslationOffset = \
-                 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
-            Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
-            break;
-
-          case TypeMem32:
-            //
-            // Memory 32
-            //
-            Ptr->Desc = 0x8A;
-            Ptr->Len  = 0x2B;
-            Ptr->ResType = 0;
-            Ptr->GenFlag = 0;
-            Ptr->SpecificFlag = 0;
-            Ptr->AddrSpaceGranularity = 32;
-            Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
-            Ptr->AddrRangeMax = 0;
-            Ptr->AddrTranslationOffset = \
-                 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
-            Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
-            break;
-
-          case TypePMem32:
-            //
-            // Prefetch memory 32
-            //
-            Ptr->Desc = 0x8A;
-            Ptr->Len  = 0x2B;
-            Ptr->ResType = 0;
-            Ptr->GenFlag = 0;
-            Ptr->SpecificFlag = 6;
-            Ptr->AddrSpaceGranularity = 32;
-            Ptr->AddrRangeMin = 0;
-            Ptr->AddrRangeMax = 0;
-            Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
-            Ptr->AddrLen = 0;
-            break;
-
-          case TypeMem64:
-            //
-            // Memory 64
-            //
-            Ptr->Desc = 0x8A;
-            Ptr->Len  = 0x2B;
-            Ptr->ResType = 0;
-            Ptr->GenFlag = 0;
-            Ptr->SpecificFlag = 0;
-            Ptr->AddrSpaceGranularity = 64;
-            Ptr->AddrRangeMin = 0;
-            Ptr->AddrRangeMax = 0;
-            Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
-            Ptr->AddrLen = 0;
-            break;
-
-          case TypePMem64:
-            //
-            // Prefetch memory 64
-            //
-            Ptr->Desc = 0x8A;
-            Ptr->Len  = 0x2B;
-            Ptr->ResType = 0;
-            Ptr->GenFlag = 0;
-            Ptr->SpecificFlag = 6;
-            Ptr->AddrSpaceGranularity = 64;
-            Ptr->AddrRangeMin = 0;
-            Ptr->AddrRangeMax = 0;
-            Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
-            Ptr->AddrLen = 0;
-            break;
-          };
-
-          Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
-        }
-      }
-
-      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
-      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
-
-      *Configuration = Buffer;
-
-      return EFI_SUCCESS;
-    }
-
-    List = List->ForwardLink;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-/**
-   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
-   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
-   PCI controllers before enumeration.
-
-   This function is called during the PCI enumeration process. No specific action is expected from this
-   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
-   enumeration.
-
-   @param This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param RootBridgeHandle  The associated PCI root bridge handle. Type EFI_HANDLE is defined in
-                            InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param PciAddress        The address of the PCI device on the PCI bus. This address can be passed to the
-                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
-                            configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
-                            the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
-   @param Phase             The phase of the PCI device enumeration.
-
-   @retval EFI_SUCCESS              The requested parameters were returned.
-   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
-                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
-   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
-                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
-                                    bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-PreprocessController (
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
-  IN  EFI_HANDLE                                                RootBridgeHandle,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
-  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
-  )
-{
-  PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
-  PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
-  LIST_ENTRY                            *List;
-
-  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
-  List = HostBridgeInstance->Head.ForwardLink;
-
-  //
-  // Enumerate the root bridges in this host bridge
-  //
-  while (List != &HostBridgeInstance->Head) {
-    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
-    if (RootBridgeHandle == RootBridgeInstance->Handle) {
-      break;
-    }
-    List = List->ForwardLink;
-  }
-  if (List == &HostBridgeInstance->Head) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return EFI_SUCCESS;
-}
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
deleted file mode 100644
index 647fe1a52a7d..000000000000
--- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
+++ /dev/null
@@ -1,499 +0,0 @@
-/** @file
-  The Header file of the Pci Host Bridge Driver
-
-  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
-  This program and the accompanying materials are
-  licensed and made available under the terms and conditions of the BSD License
-  which accompanies this distribution.  The full text of the license may be found at
-  http://opensource.org/licenses/bsd-license.php
-
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _PCI_HOST_BRIDGE_H_
-#define _PCI_HOST_BRIDGE_H_
-
-#include <PiDxe.h>
-
-#include <IndustryStandard/Pci.h>
-#include <IndustryStandard/Acpi.h>
-
-#include <Protocol/PciHostBridgeResourceAllocation.h>
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/Metronome.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/FdtClient.h>
-
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/IoLib.h>
-#include <Library/PciLib.h>
-#include <Library/PcdLib.h>
-
-//
-// Hard code the host bridge number in the platform.
-// In this chipset, there is only one host bridge.
-//
-#define HOST_BRIDGE_NUMBER  1
-
-#define MAX_PCI_DEVICE_NUMBER      31
-#define MAX_PCI_FUNCTION_NUMBER    7
-#define MAX_PCI_REG_ADDRESS        (SIZE_4KB - 1)
-
-typedef enum {
-  IoOperation,
-  MemOperation,
-  PciOperation
-} OPERATION_TYPE;
-
-#define PCI_HOST_BRIDGE_SIGNATURE  SIGNATURE_32('e', 'h', 's', 't')
-typedef struct {
-  UINTN                                             Signature;
-  EFI_HANDLE                                        HostBridgeHandle;
-  UINTN                                             RootBridgeNumber;
-  LIST_ENTRY                                        Head;
-  BOOLEAN                                           ResourceSubmited;
-  BOOLEAN                                           CanRestarted;
-  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  ResAlloc;
-} PCI_HOST_BRIDGE_INSTANCE;
-
-#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
-  CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
-
-//
-//  HostBridge Resource Allocation interface
-//
-
-/**
-   These are the notifications from the PCI bus driver that it is about to enter a certain
-   phase of the PCI enumeration process.
-
-   This member function can be used to notify the host bridge driver to perform specific actions,
-   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
-   Eight notification points are defined at this time. See belows:
-   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
-                                          structures. The PCI enumerator should issue this notification
-                                          before starting a fresh enumeration process. Enumeration cannot
-                                          be restarted after sending any other notification such as
-                                          EfiPciHostBridgeBeginBusAllocation.
-   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
-                                          required here. This notification can be used to perform any
-                                          chipset-specific programming.
-   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
-                                          specific action is required here. This notification can be used to
-                                          perform any chipset-specific programming.
-   EfiPciHostBridgeBeginResourceAllocation
-                                          The resource allocation phase is about to begin. No specific
-                                          action is required here. This notification can be used to perform
-                                          any chipset-specific programming.
-   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
-                                          root bridges. These resource settings are returned on the next call to
-                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of
-                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
-                                          for gathering I/O and memory requests for
-                                          all the PCI root bridges and submitting these requests using
-                                          SubmitResources(). This function pads the resource amount
-                                          to suit the root bridge hardware, takes care of dependencies between
-                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)
-                                          with the allocation request. In the case of padding, the allocated range
-                                          could be bigger than what was requested.
-   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
-                                          resources (proposed resources) for all the PCI root bridges. After the
-                                          hardware is programmed, reassigning resources will not be supported.
-                                          The bus settings are not affected.
-   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
-                                          root bridges and resets the I/O and memory apertures to their initial
-                                          state. The bus settings are not affected. If the request to allocate
-                                          resources fails, the PCI enumerator can use this notification to
-                                          deallocate previous resources, adjust the requests, and retry
-                                          allocation.
-   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
-                                          required here. This notification can be used to perform any chipsetspecific
-                                          programming.
-
-   @param[in] This                The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in] Phase               The phase during enumeration
-
-   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
-                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if
-                                  SubmitResources() has not been called for one or more
-                                  PCI root bridges before this call
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
-                                  for a Phase of EfiPciHostBridgeSetResources.
-   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
-                                  previously submitted resource requests cannot be fulfilled or
-                                  were only partially fulfilled.
-   @retval EFI_SUCCESS            The notification was accepted without any errors.
-
-**/
-EFI_STATUS
-EFIAPI
-NotifyPhase(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
-  );
-
-/**
-   Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
-
-   This function is called multiple times to retrieve the device handles of all the PCI root bridges that
-   are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
-   root bridges. On each call, the handle that was returned by the previous call is passed into the
-   interface, and on output the interface returns the device handle of the next PCI root bridge. The
-   caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-   for that root bridge. When there are no more PCI root bridges to report, the interface returns
-   EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
-   are returned by this function.
-   For D945 implementation, there is only one root bridge in PCI host bridge.
-
-   @param[in]       This              The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI root bridge.
-
-   @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
-                                  specific Host bridge and return EFI_SUCCESS.
-   @retval EFI_NOT_FOUND          Can not find the any more root bridge in specific host bridge.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
-                                  returned on a previous call to GetNextRootBridge().
-**/
-EFI_STATUS
-EFIAPI
-GetNextRootBridge(
-  IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN OUT   EFI_HANDLE                                       *RootBridgeHandle
-  );
-
-/**
-   Returns the allocation attributes of a PCI root bridge.
-
-   The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
-   from one PCI root bridge to another. These attributes are different from the decode-related
-   attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
-   RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
-   handles of all the root bridges that are associated with this host bridge must be obtained by calling
-   GetNextRootBridge(). The attributes are static in the sense that they do not change during or
-   after the enumeration process. The hardware may provide mechanisms to change the attributes on
-   the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
-   installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
-   "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
-   For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
-   include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
-   prefetchable memory.
-      Attribute                                 Description
-   ------------------------------------         ----------------------------------------------------------------------
-   EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM         If this bit is set, then the PCI root bridge does not support separate
-                                                windows for nonprefetchable and prefetchable memory. A PCI bus
-                                                driver needs to include requests for prefetchable memory in the
-                                                nonprefetchable memory pool.
-
-   EFI_PCI_HOST_BRIDGE_MEM64_DECODE             If this bit is set, then the PCI root bridge supports 64-bit memory
-                                                windows. If this bit is not set, the PCI bus driver needs to include
-                                                requests for a 64-bit memory address in the corresponding 32-bit
-                                                memory pool.
-
-   @param[in]   This               The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
-   @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in which the caller is interested. Type
-                                   EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param[out]  Attributes         The pointer to attribte of root bridge, it is output parameter
-
-   @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
-   @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
-   @retval EFI_SUCCESS             Success to get attribute of interested root bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-GetAttributes(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT UINT64                                           *Attributes
-  );
-
-/**
-   Sets up the specified PCI root bridge for the bus enumeration process.
-
-   This member function sets up the root bridge for bus enumeration and returns the PCI bus range
-   over which the search should be performed in ACPI 2.0 resource descriptor format.
-
-   @param[in]   This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
-   @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
-   @param[out]  Configuration     Pointer to the pointer to the PCI bus resource descriptor.
-
-   @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
-   @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
-   @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
-
-**/
-EFI_STATUS
-EFIAPI
-StartBusEnumeration(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT VOID                                             **Configuration
-  );
-
-/**
-   Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
-
-   This member function programs the specified PCI root bridge to decode the bus range that is
-   specified by the input parameter Configuration.
-   The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
-
-   @param[in] This              The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
-   @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be programmed
-   @param[in] Configuration     The pointer to the PCI bus resource descriptor
-
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI 2.0 resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI 2.0 bus resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource descriptors other than
-                                  bus descriptors.
-   @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid ACPI resource descriptors.
-   @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this root bridge.
-   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this root bridge.
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
-   @retval EFI_SUCCESS            The bus range for the PCI root bridge was programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-SetBusNumbers(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_HANDLE                                       RootBridgeHandle,
-  IN VOID                                             *Configuration
-  );
-
-/**
-   Submits the I/O and memory resource requirements for the specified PCI root bridge.
-
-   This function is used to submit all the I/O and memory resources that are required by the specified
-   PCI root bridge. The input parameter Configuration is used to specify the following:
-   - The various types of resources that are required
-   - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
-   @param[in] This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory resource requirements are being submitted.
-   @param[in] Configuration     The pointer to the PCI I/O and PCI memory resource descriptor.
-
-   @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI root bridge were accepted.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
-   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI 2.0 resource descriptor.
-   @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or more resource types that are
-                                  not supported by this PCI root bridge. This error will happen if the caller
-                                  did not combine resources according to Attributes that were returned by
-                                  GetAllocAttributes().
-   @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
-   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for this PCI root bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-SubmitResources(
-  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN EFI_HANDLE                                       RootBridgeHandle,
-  IN VOID                                             *Configuration
-  );
-
-/**
-   Returns the proposed resource settings for the specified PCI root bridge.
-
-   This member function returns the proposed resource settings for the specified PCI root bridge. The
-   proposed resource settings are prepared when NotifyPhase() is called with a Phase of
-   EfiPciHostBridgeAllocateResources. The output parameter Configuration
-   specifies the following:
-   - The various types of resources, excluding bus resources, that are allocated
-   - The associated lengths in terms of ACPI 2.0 resource descriptor format
-
-   @param[in]  This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param[out] Configuration     The pointer to the pointer to the PCI I/O and memory resource descriptor.
-
-   @retval EFI_SUCCESS            The requested parameters were returned.
-   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-GetProposedResources(
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
-  IN  EFI_HANDLE                                       RootBridgeHandle,
-  OUT VOID                                             **Configuration
-  );
-
-/**
-   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
-   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
-   PCI controllers before enumeration.
-
-   This function is called during the PCI enumeration process. No specific action is expected from this
-   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
-   enumeration.
-
-   @param This              Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
-   @param RootBridgeHandle  The associated PCI root bridge handle. Type EFI_HANDLE is defined in
-                            InstallProtocolInterface() in the UEFI 2.0 Specification.
-   @param PciAddress        The address of the PCI device on the PCI bus. This address can be passed to the
-                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
-                            configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
-                            the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
-   @param Phase             The phase of the PCI device enumeration.
-
-   @retval EFI_SUCCESS              The requested parameters were returned.
-   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
-   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
-                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
-   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
-                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
-                                    bridge.
-
-**/
-EFI_STATUS
-EFIAPI
-PreprocessController (
-  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
-  IN  EFI_HANDLE                                        RootBridgeHandle,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       PciAddress,
-  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE      Phase
-  );
-
-
-//
-// Define resource status constant
-//
-#define EFI_RESOURCE_NONEXISTENT   0xFFFFFFFFFFFFFFFFULL
-#define EFI_RESOURCE_LESS          0xFFFFFFFFFFFFFFFEULL
-
-
-//
-// Driver Instance Data Prototypes
-//
-
-typedef struct {
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation;
-  UINTN                                      NumberOfBytes;
-  UINTN                                      NumberOfPages;
-  EFI_PHYSICAL_ADDRESS                       HostAddress;
-  EFI_PHYSICAL_ADDRESS                       MappedHostAddress;
-} MAP_INFO;
-
-typedef struct {
-  ACPI_HID_DEVICE_PATH              AcpiDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL          EndDevicePath;
-} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
-
-typedef struct {
-  UINT64          BusBase;
-  UINT64          BusLimit;
-
-  UINT64          MemBase;
-  UINT64          MemLimit;
-
-  UINT64          IoBase;
-  UINT64          IoLimit;
-  UINT64          IoTranslation;
-} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
-
-typedef enum {
-  TypeIo = 0,
-  TypeMem32,
-  TypePMem32,
-  TypeMem64,
-  TypePMem64,
-  TypeBus,
-  TypeMax
-} PCI_RESOURCE_TYPE;
-
-typedef enum {
-  ResNone = 0,
-  ResSubmitted,
-  ResRequested,
-  ResAllocated,
-  ResStatusMax
-} RES_STATUS;
-
-typedef struct {
-  PCI_RESOURCE_TYPE Type;
-  UINT64            Base;
-  UINT64            Length;
-  UINT64            Alignment;
-  RES_STATUS        Status;
-} PCI_RES_NODE;
-
-#define PCI_ROOT_BRIDGE_SIGNATURE  SIGNATURE_32('e', '2', 'p', 'b')
-
-typedef struct {
-  UINT32                 Signature;
-  LIST_ENTRY             Link;
-  EFI_HANDLE             Handle;
-  UINT64                 RootBridgeAttrib;
-  UINT64                 Attributes;
-  UINT64                 Supports;
-
-  //
-  // Specific for this memory controller: Bus, I/O, Mem
-  //
-  PCI_RES_NODE           ResAllocNode[6];
-
-  //
-  // Addressing for Memory and I/O and Bus arrange
-  //
-  UINT64                 BusBase;
-  UINT64                 MemBase;
-  UINT64                 IoBase;
-  UINT64                 BusLimit;
-  UINT64                 MemLimit;
-  UINT64                 IoLimit;
-  UINT64                 IoTranslation;
-
-  EFI_DEVICE_PATH_PROTOCOL                *DevicePath;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         Io;
-
-} PCI_ROOT_BRIDGE_INSTANCE;
-
-
-//
-// Driver Instance Data Macros
-//
-#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
-  CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
-
-
-#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \
-  CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
-
-/**
-
-  Construct the Pci Root Bridge Io protocol
-
-  @param Protocol         Point to protocol instance
-  @param HostBridgeHandle Handle of host bridge
-  @param Attri            Attribute of host bridge
-  @param ResAperture      ResourceAperture for host bridge
-
-  @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
-
-**/
-EFI_STATUS
-RootBridgeConstructor (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
-  IN EFI_HANDLE                         HostBridgeHandle,
-  IN UINT64                             Attri,
-  IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *ResAperture
-  );
-
-#endif
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
deleted file mode 100644
index 8c75eda3deb5..000000000000
--- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
+++ /dev/null
@@ -1,64 +0,0 @@
-## @file
-#  The basic interfaces implementation to a single segment PCI Host Bridge driver.
-#
-#  Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
-#  This program and the accompanying materials
-#  are licensed and made available under the terms and conditions of the BSD License
-#  which accompanies this distribution.  The full text of the license may be found at
-#  http://opensource.org/licenses/bsd-license.php
-#
-#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = PciHostBridge
-  FILE_GUID                      = 9f609346-37cb-4eb7-801f-f55099373998
-  MODULE_TYPE                    = DXE_DRIVER
-  VERSION_STRING                 = 1.0
-
-  ENTRY_POINT                    = InitializePciHostBridge
-
-[Packages]
-  MdeModulePkg/MdeModulePkg.dec
-  MdePkg/MdePkg.dec
-  ArmVirtPkg/ArmVirtPkg.dec
-
-[LibraryClasses]
-  UefiDriverEntryPoint
-  UefiBootServicesTableLib
-  DxeServicesTableLib
-  UefiLib
-  MemoryAllocationLib
-  BaseMemoryLib
-  BaseLib
-  DebugLib
-  DevicePathLib
-  IoLib
-  PciLib
-  PcdLib
-
-[Sources]
-  PciHostBridge.c
-  PciRootBridgeIo.c
-  PciHostBridge.h
-
-[Protocols]
-  gEfiPciHostBridgeResourceAllocationProtocolGuid       ## PRODUCES
-  gEfiPciRootBridgeIoProtocolGuid                       ## PRODUCES
-  gEfiMetronomeArchProtocolGuid                         ## CONSUMES
-  gEfiDevicePathProtocolGuid                            ## PRODUCES
-  gFdtClientProtocolGuid                                ## CONSUMES
-
-[Pcd]
-  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
-
-[FeaturePcd]
-  gArmVirtTokenSpaceGuid.PcdPureAcpiBoot
-
-[depex]
-  gEfiMetronomeArchProtocolGuid AND
-  gEfiCpuArchProtocolGuid AND
-  gFdtClientProtocolGuid
diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c b/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c
deleted file mode 100644
index c86788795038..000000000000
--- a/ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+++ /dev/null
@@ -1,2144 +0,0 @@
-/** @file
-  PCI Root Bridge Io Protocol implementation
-
-Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials are
-licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "PciHostBridge.h"
-
-typedef struct {
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     SpaceDesp[TypeMax];
-  EFI_ACPI_END_TAG_DESCRIPTOR           EndDesp;
-} RESOURCE_CONFIGURATION;
-
-RESOURCE_CONFIGURATION Configuration = {
-  {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
-  {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
-  {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
-  {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
-  {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
-  {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
-  {0x79, 0}
-};
-
-//
-// Protocol Member Function Prototypes
-//
-
-/**
-   Polls an address in memory mapped I/O space until an exit condition is met, or
-   a timeout occurs.
-
-   This function provides a standard way to poll a PCI memory location. A PCI memory read
-   operation is performed at the PCI memory address specified by Address for the width specified
-   by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
-   read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
-   Mask) is equal to Value.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The base address of the memory operations. The caller is
-                          responsible for aligning Address if required.
-   @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
-                          are ignored. The bits in the bytes below Width which are zero in
-                          Mask are ignored when polling the memory address.
-   @param[in]   Value     The comparison value used for the polling exit criteria.
-   @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
-                          be of poorer granularity.
-   @param[out]  Result    Pointer to the last value read from the memory location.
-
-   @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
-   @retval EFI_INVALID_PARAMETER  Width is invalid.
-   @retval EFI_INVALID_PARAMETER  Result is NULL.
-   @retval EFI_TIMEOUT            Delay expired before a match occurred.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPollMem (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  );
-
-/**
-   Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
-   satisfied or after a defined duration.
-
-   This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
-   performed at the PCI I/O address specified by Address for the width specified by Width.
-   The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
-   repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
-   to Value.
-
-   @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in] Width     Signifies the width of the I/O operations.
-   @param[in] Address   The base address of the I/O operations. The caller is responsible
-                        for aligning Address if required.
-   @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
-                        are ignored. The bits in the bytes below Width which are zero in
-                        Mask are ignored when polling the I/O address.
-   @param[in] Value     The comparison value used for the polling exit criteria.
-   @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
-                        be of poorer granularity.
-   @param[out] Result   Pointer to the last value read from the memory location.
-
-   @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
-   @retval EFI_INVALID_PARAMETER  Width is invalid.
-   @retval EFI_INVALID_PARAMETER  Result is NULL.
-   @retval EFI_TIMEOUT            Delay expired before a match occurred.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPollIo (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-   The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
-   registers in the PCI root bridge memory space.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operation.
-   @param[in]   Address   The base address of the memory operation. The caller is
-                          responsible for aligning the Address if required.
-   @param[in]   Count     The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at Address.
-   @param[out]  Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMemRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  OUT    VOID                                   *Buffer
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-   The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
-   registers in the PCI root bridge memory space.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operation.
-   @param[in]   Address   The base address of the memory operation. The caller is
-                          responsible for aligning the Address if required.
-   @param[in]   Count     The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at Address.
-   @param[in]   Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMemWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN     VOID                                   *Buffer
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width       Signifies the width of the memory operations.
-   @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
-                            aligning the Address if required.
-   @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
-                            size * Count, starting at Address.
-   @param[out]  UserBuffer  For read operations, the destination buffer to store the results. For
-                            write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoIoRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 UserAddress,
-  IN     UINTN                                  Count,
-  OUT    VOID                                   *UserBuffer
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width       Signifies the width of the memory operations.
-   @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
-                            aligning the Address if required.
-   @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
-                            size * Count, starting at Address.
-   @param[in]   UserBuffer  For read operations, the destination buffer to store the results. For
-                            write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoIoWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 UserAddress,
-  IN     UINTN                                  Count,
-  IN     VOID                                   *UserBuffer
-  );
-
-/**
-   Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
-   root bridge memory space.
-
-   The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
-   space to another region of PCI root bridge memory space. This is especially useful for video scroll
-   operation on a memory mapped video buffer.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI root bridge on a platform might require.
-
-   @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
-   @param[in] Width       Signifies the width of the memory operations.
-   @param[in] DestAddress The destination address of the memory operation. The caller is
-                          responsible for aligning the DestAddress if required.
-   @param[in] SrcAddress  The source address of the memory operation. The caller is
-                          responsible for aligning the SrcAddress if required.
-   @param[in] Count       The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at DestAddress and SrcAddress.
-
-   @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
-   @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
-   @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoCopyMem (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 DestAddress,
-  IN     UINT64                                 SrcAddress,
-  IN     UINTN                                  Count
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
-   The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
-   registers for a PCI controller.
-   The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
-   any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
-   require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count     The number of PCI configuration operations to perform. Bytes
-                          moved is Width size * Count, starting at Address.
-   @param[out]  Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPciRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  OUT    VOID                                   *Buffer
-  );
-
-/**
-   Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
-   The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
-   registers for a PCI controller.
-   The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
-   any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
-   require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count     The number of PCI configuration operations to perform. Bytes
-                          moved is Width size * Count, starting at Address.
-   @param[in]   Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPciWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN     VOID                                   *Buffer
-  );
-
-/**
-   Provides the PCI controller-specific addresses required to access system memory from a
-   DMA bus master.
-
-   The Map() function provides the PCI controller specific addresses needed to access system
-   memory. This function is used to map system memory for PCI bus master DMA accesses.
-
-   @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
-   @param[in]       HostAddress     The system memory address to map to the PCI controller.
-   @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
-   @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
-                                    to access the system memory's HostAddress.
-   @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
-
-   @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
-   @retval EFI_INVALID_PARAMETER  Operation is invalid.
-   @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
-   @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
-   @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
-   @retval EFI_INVALID_PARAMETER  Mapping is NULL.
-   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
-   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMap (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
-  IN     VOID                                       *HostAddress,
-  IN OUT UINTN                                      *NumberOfBytes,
-  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
-  OUT    VOID                                       **Mapping
-  );
-
-/**
-   Completes the Map() operation and releases any corresponding resources.
-
-   The Unmap() function completes the Map() operation and releases any corresponding resources.
-   If the operation was an EfiPciOperationBusMasterWrite or
-   EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
-   Any resources used for the mapping are freed.
-
-   @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in] Mapping   The mapping value returned from Map().
-
-   @retval EFI_SUCCESS            The range was unmapped.
-   @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
-   @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoUnmap (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  VOID                             *Mapping
-  );
-
-/**
-   Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
-   EfiPciOperationBusMasterCommonBuffer64 mapping.
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Type        This parameter is not used and must be ignored.
-   @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
-   @param Pages       The number of pages to allocate.
-   @param HostAddress A pointer to store the base system memory address of the allocated range.
-   @param Attributes  The requested bit mask of attributes for the allocated range. Only
-                      the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
-                      and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
-
-   @retval EFI_SUCCESS            The requested memory pages were allocated.
-   @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
-   @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
-   @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
-                                  MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
-   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoAllocateBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  EFI_ALLOCATE_TYPE                Type,
-  IN  EFI_MEMORY_TYPE                  MemoryType,
-  IN  UINTN                            Pages,
-  OUT VOID                             **HostAddress,
-  IN  UINT64                           Attributes
-  );
-
-/**
-   Frees memory that was allocated with AllocateBuffer().
-
-   The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Pages       The number of pages to free.
-   @param HostAddress The base system memory address of the allocated range.
-
-   @retval EFI_SUCCESS            The requested memory pages were freed.
-   @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
-                                  was not allocated with AllocateBuffer().
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoFreeBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  UINTN                            Pages,
-  OUT VOID                             *HostAddress
-  );
-
-/**
-   Flushes all PCI posted write transactions from a PCI host bridge to system memory.
-
-   The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
-   memory. Posted write transactions are generated by PCI bus masters when they perform write
-   transactions to target addresses in system memory.
-   This function does not flush posted write transactions from any PCI bridges. A PCI controller
-   specific action must be taken to guarantee that the posted write transactions have been flushed from
-   the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
-   a PCI read transaction from the PCI controller prior to calling Flush().
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-
-   @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
-                              bridge to system memory.
-   @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
-                              host bridge due to a hardware error.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoFlush (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
-  );
-
-/**
-   Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
-   attributes that a PCI root bridge is currently using.
-
-   The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
-   and the mask of attributes that the PCI root bridge is currently using.
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Supported   A pointer to the mask of attributes that this PCI root bridge
-                      supports setting with SetAttributes().
-   @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
-                      currently using.
-
-   @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
-                                  bridge supports is returned in Supports. If Attributes is
-                                  not NULL, then the attributes that the PCI root bridge is currently
-                                  using is returned in Attributes.
-   @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoGetAttributes (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  OUT UINT64                           *Supported,
-  OUT UINT64                           *Attributes
-  );
-
-/**
-   Sets attributes for a resource range on a PCI root bridge.
-
-   The SetAttributes() function sets the attributes specified in Attributes for the PCI root
-   bridge on the resource range specified by ResourceBase and ResourceLength. Since the
-   granularity of setting these attributes may vary from resource type to resource type, and from
-   platform to platform, the actual resource range and the one passed in by the caller may differ. As a
-   result, this function may set the attributes specified by Attributes on a larger resource range
-   than the caller requested. The actual range is returned in ResourceBase and
-   ResourceLength. The caller is responsible for verifying that the actual range for which the
-   attributes were set is acceptable.
-
-   @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]       Attributes      The mask of attributes to set. If the attribute bit
-                                    MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
-                                    MEMORY_DISABLE is set, then the resource range is specified by
-                                    ResourceBase and ResourceLength. If
-                                    MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
-                                    MEMORY_DISABLE are not set, then ResourceBase and
-                                    ResourceLength are ignored, and may be NULL.
-   @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
-                                    by the attributes specified by Attributes.
-   @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
-                                    attributes specified by Attributes.
-
-   @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
-   @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
-   @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoSetAttributes (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN     UINT64                           Attributes,
-  IN OUT UINT64                           *ResourceBase,
-  IN OUT UINT64                           *ResourceLength
-  );
-
-/**
-   Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
-   resource descriptors.
-
-   There are only two resource descriptor types from the ACPI Specification that may be used to
-   describe the current resources allocated to a PCI root bridge. These are the QWORD Address
-   Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
-   QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
-   or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
-   Address Space Descriptors followed by an End Tag.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
-                            current configuration of this PCI root bridge. The storage for the
-                            ACPI 2.0 resource descriptors is allocated by this function. The
-                            caller must treat the return buffer as read-only data, and the buffer
-                            must not be freed by the caller.
-
-   @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
-   @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
-   @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoConfiguration (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  OUT    VOID                             **Resources
-  );
-
-//
-// Memory Controller Pci Root Bridge Io Module Variables
-//
-EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
-
-//
-// Lookup table for increment values based on transfer widths
-//
-UINT8 mInStride[] = {
-  1, // EfiPciWidthUint8
-  2, // EfiPciWidthUint16
-  4, // EfiPciWidthUint32
-  8, // EfiPciWidthUint64
-  0, // EfiPciWidthFifoUint8
-  0, // EfiPciWidthFifoUint16
-  0, // EfiPciWidthFifoUint32
-  0, // EfiPciWidthFifoUint64
-  1, // EfiPciWidthFillUint8
-  2, // EfiPciWidthFillUint16
-  4, // EfiPciWidthFillUint32
-  8  // EfiPciWidthFillUint64
-};
-
-//
-// Lookup table for increment values based on transfer widths
-//
-UINT8 mOutStride[] = {
-  1, // EfiPciWidthUint8
-  2, // EfiPciWidthUint16
-  4, // EfiPciWidthUint32
-  8, // EfiPciWidthUint64
-  1, // EfiPciWidthFifoUint8
-  2, // EfiPciWidthFifoUint16
-  4, // EfiPciWidthFifoUint32
-  8, // EfiPciWidthFifoUint64
-  0, // EfiPciWidthFillUint8
-  0, // EfiPciWidthFillUint16
-  0, // EfiPciWidthFillUint32
-  0  // EfiPciWidthFillUint64
-};
-
-/**
-
-  Construct the Pci Root Bridge Io protocol
-
-  @param Protocol         Point to protocol instance
-  @param HostBridgeHandle Handle of host bridge
-  @param Attri            Attribute of host bridge
-  @param ResAperture      ResourceAperture for host bridge
-
-  @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
-
-**/
-EFI_STATUS
-RootBridgeConstructor (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
-  IN EFI_HANDLE                         HostBridgeHandle,
-  IN UINT64                             Attri,
-  IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *ResAperture
-  )
-{
-  EFI_STATUS                        Status;
-  PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
-  PCI_RESOURCE_TYPE                 Index;
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
-
-  //
-  // The host to PCI bridge. The host memory addresses are direct mapped to PCI
-  // addresses, so there's no need to translate them. IO addresses need
-  // translation however.
-  //
-  PrivateData->MemBase       = ResAperture->MemBase;
-  PrivateData->IoBase        = ResAperture->IoBase;
-  PrivateData->IoTranslation = ResAperture->IoTranslation;
-
-  //
-  // The host bridge only supports 32bit addressing for memory
-  // and standard IA32 16bit io
-  //
-  PrivateData->MemLimit = ResAperture->MemLimit;
-  PrivateData->IoLimit  = ResAperture->IoLimit;
-
-  //
-  // Bus Aperture for this Root Bridge (Possible Range)
-  //
-  PrivateData->BusBase  = ResAperture->BusBase;
-  PrivateData->BusLimit = ResAperture->BusLimit;
-
-  //
-  // Specific for this chipset
-  //
-  for (Index = TypeIo; Index < TypeMax; Index++) {
-    PrivateData->ResAllocNode[Index].Type      = Index;
-    PrivateData->ResAllocNode[Index].Base      = 0;
-    PrivateData->ResAllocNode[Index].Length    = 0;
-    PrivateData->ResAllocNode[Index].Status    = ResNone;
-  }
-
-  PrivateData->RootBridgeAttrib = Attri;
-
-  PrivateData->Supports    = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
-                             EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
-                             EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
-                             EFI_PCI_ATTRIBUTE_VGA_IO_16  | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
-  PrivateData->Attributes  = PrivateData->Supports;
-
-  Protocol->ParentHandle   = HostBridgeHandle;
-
-  Protocol->PollMem        = RootBridgeIoPollMem;
-  Protocol->PollIo         = RootBridgeIoPollIo;
-
-  Protocol->Mem.Read       = RootBridgeIoMemRead;
-  Protocol->Mem.Write      = RootBridgeIoMemWrite;
-
-  Protocol->Io.Read        = RootBridgeIoIoRead;
-  Protocol->Io.Write       = RootBridgeIoIoWrite;
-
-  Protocol->CopyMem        = RootBridgeIoCopyMem;
-
-  Protocol->Pci.Read       = RootBridgeIoPciRead;
-  Protocol->Pci.Write      = RootBridgeIoPciWrite;
-
-  Protocol->Map            = RootBridgeIoMap;
-  Protocol->Unmap          = RootBridgeIoUnmap;
-
-  Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
-  Protocol->FreeBuffer     = RootBridgeIoFreeBuffer;
-
-  Protocol->Flush          = RootBridgeIoFlush;
-
-  Protocol->GetAttributes  = RootBridgeIoGetAttributes;
-  Protocol->SetAttributes  = RootBridgeIoSetAttributes;
-
-  Protocol->Configuration  = RootBridgeIoConfiguration;
-
-  Protocol->SegmentNumber  = 0;
-
-  Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
-  ASSERT_EFI_ERROR (Status);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
-
-  The I/O operations are carried out exactly as requested. The caller is responsible
-  for satisfying any alignment and I/O width restrictions that a PI System on a
-  platform might require. For example on some platforms, width requests of
-  EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
-  be handled by the driver.
-
-  @param[in] This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-  @param[in] OperationType  I/O operation type: IO/MMIO/PCI.
-  @param[in] Width          Signifies the width of the I/O or Memory operation.
-  @param[in] Address        The base address of the I/O operation.
-  @param[in] Count          The number of I/O operations to perform. The number of
-                            bytes moved is Width size * Count, starting at Address.
-  @param[in] Buffer         For read operations, the destination buffer to store the results.
-                            For write operations, the source buffer from which to write data.
-
-  @retval EFI_SUCCESS            The parameters for this request pass the checks.
-  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
-  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
-  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
-                                 and Count is not valid for this PI system.
-
-**/
-EFI_STATUS
-RootBridgeIoCheckParameter (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN OPERATION_TYPE                         OperationType,
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN UINT64                                 Address,
-  IN UINTN                                  Count,
-  IN VOID                                   *Buffer
-  )
-{
-  PCI_ROOT_BRIDGE_INSTANCE                     *PrivateData;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
-  UINT32                                       Stride;
-  UINT64                                       Base;
-  UINT64                                       Limit;
-
-  //
-  // Check to see if Buffer is NULL
-  //
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Check to see if Width is in the valid range
-  //
-  if ((UINT32)Width >= EfiPciWidthMaximum) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // For FIFO type, the target address won't increase during the access,
-  // so treat Count as 1
-  //
-  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
-    Count = 1;
-  }
-
-  //
-  // Check to see if Width is in the valid range for I/O Port operations
-  //
-  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
-  if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
-    ASSERT (FALSE);
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Check to see if Address is aligned
-  //
-  Stride = mInStride[Width];
-  if ((Address & (UINT64)(Stride - 1)) != 0) {
-    return EFI_UNSUPPORTED;
-  }
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
-  //
-  // Check to see if any address associated with this transfer exceeds the maximum
-  // allowed address.  The maximum address implied by the parameters passed in is
-  // Address + Size * Count.  If the following condition is met, then the transfer
-  // is not supported.
-  //
-  //    Address + Size * Count > Limit + 1
-  //
-  // Since Limit can be the maximum integer value supported by the CPU and Count
-  // can also be the maximum integer value supported by the CPU, this range
-  // check must be adjusted to avoid all oveflow conditions.
-  //
-  if (OperationType == IoOperation) {
-    Base = PrivateData->IoBase;
-    Limit = PrivateData->IoLimit;
-  } else if (OperationType == MemOperation) {
-    Base = PrivateData->MemBase;
-    Limit = PrivateData->MemLimit;
-  } else {
-    PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
-    if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
-      return EFI_INVALID_PARAMETER;
-    }
-
-    if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
-      return EFI_INVALID_PARAMETER;
-    }
-
-    if (PciRbAddr->ExtendedRegister != 0) {
-      Address = PciRbAddr->ExtendedRegister;
-    } else {
-      Address = PciRbAddr->Register;
-    }
-    Base = 0;
-    Limit = MAX_PCI_REG_ADDRESS;
-  }
-
-  if (Limit < Address) {
-      return EFI_INVALID_PARAMETER;
-  }
-
-  if (Address < Base) {
-      return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Base <= Address <= Limit
-  //
-  if (Address == 0 && Limit == MAX_UINT64) {
-    //
-    // 2^64 bytes are valid to transfer. With Stride == 1, that's simply
-    // impossible to reach in Count; with Stride in {2, 4, 8}, we can divide
-    // both 2^64 and Stride with 2.
-    //
-    if (Stride > 1 && Count > DivU64x32 (BIT63, Stride / 2)) {
-      return EFI_UNSUPPORTED;
-    }
-  } else {
-    //
-    // (Limit - Address) does not wrap, and it is smaller than MAX_UINT64.
-    //
-    if (Count > DivU64x32 (Limit - Address + 1, Stride)) {
-      return EFI_UNSUPPORTED;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Internal help function for read and write memory space.
-
-   @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Write         Switch value for Read or Write.
-   @param[in]   Width         Signifies the width of the memory operations.
-   @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count         The number of PCI configuration operations to perform. Bytes
-                              moved is Width size * Count, starting at Address.
-   @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
-                              write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-RootBridgeIoMemRW (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     BOOLEAN                                Write,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  EFI_STATUS                             Status;
-  UINT8                                  InStride;
-  UINT8                                  OutStride;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
-  UINT8                                  *Uint8Buffer;
-
-  Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  InStride = mInStride[Width];
-  OutStride = mOutStride[Width];
-  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
-  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
-    if (Write) {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          MmioWrite8 ((UINTN)Address, *Uint8Buffer);
-          break;
-        case EfiPciWidthUint16:
-          MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
-          break;
-        case EfiPciWidthUint32:
-          MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
-          break;
-        case EfiPciWidthUint64:
-          MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    } else {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          *Uint8Buffer = MmioRead8 ((UINTN)Address);
-          break;
-        case EfiPciWidthUint16:
-          *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
-          break;
-        case EfiPciWidthUint32:
-          *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
-          break;
-        case EfiPciWidthUint64:
-          *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    }
-  }
-  return EFI_SUCCESS;
-}
-
-/**
-   Internal help function for read and write IO space.
-
-   @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Write         Switch value for Read or Write.
-   @param[in]   Width         Signifies the width of the memory operations.
-   @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count         The number of PCI configuration operations to perform. Bytes
-                              moved is Width size * Count, starting at Address.
-   @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
-                              write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-RootBridgeIoIoRW (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     BOOLEAN                                Write,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  EFI_STATUS                             Status;
-  PCI_ROOT_BRIDGE_INSTANCE               *PrivateData;
-  UINT8                                  InStride;
-  UINT8                                  OutStride;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
-  UINT8                                  *Uint8Buffer;
-
-  Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-  //
-  // The addition below is performed in UINT64 modular arithmetic, in
-  // accordance with the definition of PcdPciIoTranslation in
-  // "ArmPlatformPkg.dec". Meaning, the addition below may in fact *decrease*
-  // Address, implementing a negative offset translation.
-  //
-  Address += PrivateData->IoTranslation;
-
-  InStride = mInStride[Width];
-  OutStride = mOutStride[Width];
-  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
-
-  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
-    if (Write) {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          MmioWrite8 ((UINTN)Address, *Uint8Buffer);
-          break;
-        case EfiPciWidthUint16:
-          MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
-          break;
-        case EfiPciWidthUint32:
-          MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    } else {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          *Uint8Buffer = MmioRead8 ((UINTN)Address);
-          break;
-        case EfiPciWidthUint16:
-          *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
-          break;
-        case EfiPciWidthUint32:
-          *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    }
-  }
-  return EFI_SUCCESS;
-}
-
-/**
-   Internal help function for read and write PCI configuration space.
-
-   @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Write         Switch value for Read or Write.
-   @param[in]   Width         Signifies the width of the memory operations.
-   @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count         The number of PCI configuration operations to perform. Bytes
-                              moved is Width size * Count, starting at Address.
-   @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
-                              write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-RootBridgeIoPciRW (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN BOOLEAN                                Write,
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN UINT64                                 Address,
-  IN UINTN                                  Count,
-  IN OUT VOID                               *Buffer
-  )
-{
-  EFI_STATUS                                   Status;
-  UINT8                                        InStride;
-  UINT8                                        OutStride;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        OperationWidth;
-  UINT8                                        *Uint8Buffer;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
-  UINTN                                        PcieRegAddr;
-
-  Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
-
-  PcieRegAddr = (UINTN) PCI_LIB_ADDRESS (
-                          PciRbAddr->Bus,
-                          PciRbAddr->Device,
-                          PciRbAddr->Function,
-                          (PciRbAddr->ExtendedRegister != 0) ? \
-                            PciRbAddr->ExtendedRegister :
-                            PciRbAddr->Register
-                          );
-
-  InStride = mInStride[Width];
-  OutStride = mOutStride[Width];
-  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
-  for (Uint8Buffer = Buffer; Count > 0; PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {
-    if (Write) {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          PciWrite8 (PcieRegAddr, *Uint8Buffer);
-          break;
-        case EfiPciWidthUint16:
-          PciWrite16 (PcieRegAddr, *((UINT16 *)Uint8Buffer));
-          break;
-        case EfiPciWidthUint32:
-          PciWrite32 (PcieRegAddr, *((UINT32 *)Uint8Buffer));
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    } else {
-      switch (OperationWidth) {
-        case EfiPciWidthUint8:
-          *Uint8Buffer = PciRead8 (PcieRegAddr);
-          break;
-        case EfiPciWidthUint16:
-          *((UINT16 *)Uint8Buffer) = PciRead16 (PcieRegAddr);
-          break;
-        case EfiPciWidthUint32:
-          *((UINT32 *)Uint8Buffer) = PciRead32 (PcieRegAddr);
-          break;
-        default:
-          //
-          // The RootBridgeIoCheckParameter call above will ensure that this
-          // path is not taken.
-          //
-          ASSERT (FALSE);
-          break;
-      }
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Polls an address in memory mapped I/O space until an exit condition is met, or
-   a timeout occurs.
-
-   This function provides a standard way to poll a PCI memory location. A PCI memory read
-   operation is performed at the PCI memory address specified by Address for the width specified
-   by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
-   read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
-   Mask) is equal to Value.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The base address of the memory operations. The caller is
-                          responsible for aligning Address if required.
-   @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
-                          are ignored. The bits in the bytes below Width which are zero in
-                          Mask are ignored when polling the memory address.
-   @param[in]   Value     The comparison value used for the polling exit criteria.
-   @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
-                          be of poorer granularity.
-   @param[out]  Result    Pointer to the last value read from the memory location.
-
-   @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
-   @retval EFI_INVALID_PARAMETER  Width is invalid.
-   @retval EFI_INVALID_PARAMETER  Result is NULL.
-   @retval EFI_TIMEOUT            Delay expired before a match occurred.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPollMem (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  )
-{
-  EFI_STATUS  Status;
-  UINT64      NumberOfTicks;
-  UINT32      Remainder;
-
-  if (Result == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((UINT32)Width > EfiPciWidthUint64) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // No matter what, always do a single poll.
-  //
-  Status = This->Mem.Read (This, Width, Address, 1, Result);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if ((*Result & Mask) == Value) {
-    return EFI_SUCCESS;
-  }
-
-  if (Delay == 0) {
-    return EFI_SUCCESS;
-
-  } else {
-
-    //
-    // Determine the proper # of metronome ticks to wait for polling the
-    // location.  The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
-    // The "+1" to account for the possibility of the first tick being short
-    // because we started in the middle of a tick.
-    //
-    // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
-    // protocol definition is updated.
-    //
-    NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
-    if (Remainder != 0) {
-      NumberOfTicks += 1;
-    }
-    NumberOfTicks += 1;
-
-    while (NumberOfTicks != 0) {
-
-      mMetronome->WaitForTick (mMetronome, 1);
-
-      Status = This->Mem.Read (This, Width, Address, 1, Result);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if ((*Result & Mask) == Value) {
-        return EFI_SUCCESS;
-      }
-
-      NumberOfTicks -= 1;
-    }
-  }
-  return EFI_TIMEOUT;
-}
-
-/**
-   Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
-   satisfied or after a defined duration.
-
-   This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
-   performed at the PCI I/O address specified by Address for the width specified by Width.
-   The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
-   repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
-   to Value.
-
-   @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in] Width     Signifies the width of the I/O operations.
-   @param[in] Address   The base address of the I/O operations. The caller is responsible
-                        for aligning Address if required.
-   @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
-                        are ignored. The bits in the bytes below Width which are zero in
-                        Mask are ignored when polling the I/O address.
-   @param[in] Value     The comparison value used for the polling exit criteria.
-   @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
-                        be of poorer granularity.
-   @param[out] Result   Pointer to the last value read from the memory location.
-
-   @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
-   @retval EFI_INVALID_PARAMETER  Width is invalid.
-   @retval EFI_INVALID_PARAMETER  Result is NULL.
-   @retval EFI_TIMEOUT            Delay expired before a match occurred.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPollIo (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  )
-{
-  EFI_STATUS  Status;
-  UINT64      NumberOfTicks;
-  UINT32      Remainder;
-
-  //
-  // No matter what, always do a single poll.
-  //
-
-  if (Result == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((UINT32)Width > EfiPciWidthUint64) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Status = This->Io.Read (This, Width, Address, 1, Result);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  if ((*Result & Mask) == Value) {
-    return EFI_SUCCESS;
-  }
-
-  if (Delay == 0) {
-    return EFI_SUCCESS;
-
-  } else {
-
-    //
-    // Determine the proper # of metronome ticks to wait for polling the
-    // location.  The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
-    // The "+1" to account for the possibility of the first tick being short
-    // because we started in the middle of a tick.
-    //
-    NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
-    if (Remainder != 0) {
-      NumberOfTicks += 1;
-    }
-    NumberOfTicks += 1;
-
-    while (NumberOfTicks != 0) {
-
-      mMetronome->WaitForTick (mMetronome, 1);
-
-      Status = This->Io.Read (This, Width, Address, 1, Result);
-      if (EFI_ERROR (Status)) {
-        return Status;
-      }
-
-      if ((*Result & Mask) == Value) {
-        return EFI_SUCCESS;
-      }
-
-      NumberOfTicks -= 1;
-    }
-  }
-  return EFI_TIMEOUT;
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-   The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
-   registers in the PCI root bridge memory space.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operation.
-   @param[in]   Address   The base address of the memory operation. The caller is
-                          responsible for aligning the Address if required.
-   @param[in]   Count     The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at Address.
-   @param[out]  Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMemRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  OUT    VOID                                   *Buffer
-  )
-{
-  return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-   The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
-   registers in the PCI root bridge memory space.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operation.
-   @param[in]   Address   The base address of the memory operation. The caller is
-                          responsible for aligning the Address if required.
-   @param[in]   Count     The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at Address.
-   @param[in]   Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMemWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN     VOID                                   *Buffer
-  )
-{
-  return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width       Signifies the width of the memory operations.
-   @param[in]   Address     The base address of the I/O operation. The caller is responsible for
-                            aligning the Address if required.
-   @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
-                            size * Count, starting at Address.
-   @param[out]  Buffer      For read operations, the destination buffer to store the results. For
-                            write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoIoRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  OUT    VOID                                   *Buffer
-  )
-{
-  return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width       Signifies the width of the memory operations.
-   @param[in]   Address     The base address of the I/O operation. The caller is responsible for
-                            aligning the Address if required.
-   @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
-                            size * Count, starting at Address.
-   @param[in]   Buffer       For read operations, the destination buffer to store the results. For
-                            write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER    Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoIoWrite (
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,
-  IN       UINT64                                  Address,
-  IN       UINTN                                   Count,
-  IN       VOID                                    *Buffer
-  )
-{
-  return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-/**
-   Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
-   root bridge memory space.
-
-   The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
-   space to another region of PCI root bridge memory space. This is especially useful for video scroll
-   operation on a memory mapped video buffer.
-   The memory operations are carried out exactly as requested. The caller is responsible for satisfying
-   any alignment and memory width restrictions that a PCI root bridge on a platform might require.
-
-   @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
-   @param[in] Width       Signifies the width of the memory operations.
-   @param[in] DestAddress The destination address of the memory operation. The caller is
-                          responsible for aligning the DestAddress if required.
-   @param[in] SrcAddress  The source address of the memory operation. The caller is
-                          responsible for aligning the SrcAddress if required.
-   @param[in] Count       The number of memory operations to perform. Bytes moved is
-                          Width size * Count, starting at DestAddress and SrcAddress.
-
-   @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
-   @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
-   @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoCopyMem (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        Width,
-  IN UINT64                                       DestAddress,
-  IN UINT64                                       SrcAddress,
-  IN UINTN                                        Count
-  )
-{
-  EFI_STATUS  Status;
-  BOOLEAN     Direction;
-  UINTN       Stride;
-  UINTN       Index;
-  UINT64      Result;
-
-  if ((UINT32)Width > EfiPciWidthUint64) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (DestAddress == SrcAddress) {
-    return EFI_SUCCESS;
-  }
-
-  Stride = (UINTN)(1 << Width);
-
-  Direction = TRUE;
-  if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
-    Direction   = FALSE;
-    SrcAddress  = SrcAddress  + (Count-1) * Stride;
-    DestAddress = DestAddress + (Count-1) * Stride;
-  }
-
-  for (Index = 0;Index < Count;Index++) {
-    Status = RootBridgeIoMemRead (
-               This,
-               Width,
-               SrcAddress,
-               1,
-               &Result
-               );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-    Status = RootBridgeIoMemWrite (
-               This,
-               Width,
-               DestAddress,
-               1,
-               &Result
-               );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-    if (Direction) {
-      SrcAddress  += Stride;
-      DestAddress += Stride;
-    } else {
-      SrcAddress  -= Stride;
-      DestAddress -= Stride;
-    }
-  }
-  return EFI_SUCCESS;
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
-   The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
-   registers for a PCI controller.
-   The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
-   any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
-   require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count     The number of PCI configuration operations to perform. Bytes
-                          moved is Width size * Count, starting at Address.
-   @param[out]  Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPciRead (
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN       UINT64                                 Address,
-  IN       UINTN                                  Count,
-  OUT      VOID                                   *Buffer
-  )
-{
-  return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-/**
-   Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
-
-   The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
-   registers for a PCI controller.
-   The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
-   any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
-   require.
-
-   @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]   Width     Signifies the width of the memory operations.
-   @param[in]   Address   The address within the PCI configuration space for the PCI controller.
-   @param[in]   Count     The number of PCI configuration operations to perform. Bytes
-                          moved is Width size * Count, starting at Address.
-   @param[in]   Buffer    For read operations, the destination buffer to store the results. For
-                          write operations, the source buffer to write data from.
-
-   @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
-   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoPciWrite (
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN       UINT64                                 Address,
-  IN       UINTN                                  Count,
-  IN       VOID                                   *Buffer
-  )
-{
-  return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-/**
-   Provides the PCI controller-specific addresses required to access system memory from a
-   DMA bus master.
-
-   The Map() function provides the PCI controller specific addresses needed to access system
-   memory. This function is used to map system memory for PCI bus master DMA accesses.
-
-   @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
-   @param[in]       HostAddress     The system memory address to map to the PCI controller.
-   @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
-   @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
-                                    to access the system memory's HostAddress.
-   @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
-
-   @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
-   @retval EFI_INVALID_PARAMETER  Operation is invalid.
-   @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
-   @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
-   @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
-   @retval EFI_INVALID_PARAMETER  Mapping is NULL.
-   @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
-   @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
-   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoMap (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
-  IN     VOID                                       *HostAddress,
-  IN OUT UINTN                                      *NumberOfBytes,
-  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
-  OUT    VOID                                       **Mapping
-  )
-{
-  EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
-  MAP_INFO              *MapInfo;
-
-  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Initialize the return values to their defaults
-  //
-  *Mapping = NULL;
-
-  //
-  // Make sure that Operation is valid
-  //
-  if ((UINT32)Operation >= EfiPciOperationMaximum) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Most PCAT like chipsets can not handle performing DMA above 4GB.
-  // If any part of the DMA transfer being mapped is above 4GB, then
-  // map the DMA transfer to a buffer below 4GB.
-  //
-  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
-  if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
-
-    //
-    // Common Buffer operations can not be remapped.  If the common buffer
-    // if above 4GB, then it is not possible to generate a mapping, so return
-    // an error.
-    //
-    if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
-      return EFI_UNSUPPORTED;
-    }
-
-    //
-    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
-    // called later.
-    //
-    Status = gBS->AllocatePool (
-                    EfiBootServicesData,
-                    sizeof(MAP_INFO),
-                    (VOID **)&MapInfo
-                    );
-    if (EFI_ERROR (Status)) {
-      *NumberOfBytes = 0;
-      return Status;
-    }
-
-    //
-    // Return a pointer to the MAP_INFO structure in Mapping
-    //
-    *Mapping = MapInfo;
-
-    //
-    // Initialize the MAP_INFO structure
-    //
-    MapInfo->Operation         = Operation;
-    MapInfo->NumberOfBytes     = *NumberOfBytes;
-    MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);
-    MapInfo->HostAddress       = PhysicalAddress;
-    MapInfo->MappedHostAddress = 0x00000000ffffffff;
-
-    //
-    // Allocate a buffer below 4GB to map the transfer to.
-    //
-    Status = gBS->AllocatePages (
-                    AllocateMaxAddress,
-                    EfiBootServicesData,
-                    MapInfo->NumberOfPages,
-                    &MapInfo->MappedHostAddress
-                    );
-    if (EFI_ERROR (Status)) {
-      gBS->FreePool (MapInfo);
-      *NumberOfBytes = 0;
-      return Status;
-    }
-
-    //
-    // If this is a read operation from the Bus Master's point of view,
-    // then copy the contents of the real buffer into the mapped buffer
-    // so the Bus Master can read the contents of the real buffer.
-    //
-    if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
-      CopyMem (
-        (VOID *)(UINTN)MapInfo->MappedHostAddress,
-        (VOID *)(UINTN)MapInfo->HostAddress,
-        MapInfo->NumberOfBytes
-        );
-    }
-
-    //
-    // The DeviceAddress is the address of the maped buffer below 4GB
-    //
-    *DeviceAddress = MapInfo->MappedHostAddress;
-  } else {
-    //
-    // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
-    //
-    *DeviceAddress = PhysicalAddress;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Completes the Map() operation and releases any corresponding resources.
-
-   The Unmap() function completes the Map() operation and releases any corresponding resources.
-   If the operation was an EfiPciOperationBusMasterWrite or
-   EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
-   Any resources used for the mapping are freed.
-
-   @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in] Mapping   The mapping value returned from Map().
-
-   @retval EFI_SUCCESS            The range was unmapped.
-   @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
-   @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoUnmap (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN VOID                             *Mapping
-  )
-{
-  MAP_INFO    *MapInfo;
-
-  //
-  // See if the Map() operation associated with this Unmap() required a mapping buffer.
-  // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
-  //
-  if (Mapping != NULL) {
-    //
-    // Get the MAP_INFO structure from Mapping
-    //
-    MapInfo = (MAP_INFO *)Mapping;
-
-    //
-    // If this is a write operation from the Bus Master's point of view,
-    // then copy the contents of the mapped buffer into the real buffer
-    // so the processor can read the contents of the real buffer.
-    //
-    if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
-      CopyMem (
-        (VOID *)(UINTN)MapInfo->HostAddress,
-        (VOID *)(UINTN)MapInfo->MappedHostAddress,
-        MapInfo->NumberOfBytes
-        );
-    }
-
-    //
-    // Free the mapped buffer and the MAP_INFO structure.
-    //
-    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
-    gBS->FreePool (Mapping);
-  }
-  return EFI_SUCCESS;
-}
-
-/**
-   Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
-   EfiPciOperationBusMasterCommonBuffer64 mapping.
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Type        This parameter is not used and must be ignored.
-   @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
-   @param Pages       The number of pages to allocate.
-   @param HostAddress A pointer to store the base system memory address of the allocated range.
-   @param Attributes  The requested bit mask of attributes for the allocated range. Only
-                      the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
-                      and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
-
-   @retval EFI_SUCCESS            The requested memory pages were allocated.
-   @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
-   @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
-   @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
-                                  MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
-   @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoAllocateBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  EFI_ALLOCATE_TYPE                Type,
-  IN  EFI_MEMORY_TYPE                  MemoryType,
-  IN  UINTN                            Pages,
-  OUT VOID                             **HostAddress,
-  IN  UINT64                           Attributes
-  )
-{
-  EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
-
-  //
-  // Validate Attributes
-  //
-  if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
-    return EFI_UNSUPPORTED;
-  }
-
-  //
-  // Check for invalid inputs
-  //
-  if (HostAddress == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
-  //
-  if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Limit allocations to memory below 4GB
-  //
-  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
-
-  Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  *HostAddress = (VOID *)(UINTN)PhysicalAddress;
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Frees memory that was allocated with AllocateBuffer().
-
-   The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Pages       The number of pages to free.
-   @param HostAddress The base system memory address of the allocated range.
-
-   @retval EFI_SUCCESS            The requested memory pages were freed.
-   @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
-                                  was not allocated with AllocateBuffer().
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoFreeBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  UINTN                            Pages,
-  OUT VOID                             *HostAddress
-  )
-{
-  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
-}
-
-/**
-   Flushes all PCI posted write transactions from a PCI host bridge to system memory.
-
-   The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
-   memory. Posted write transactions are generated by PCI bus masters when they perform write
-   transactions to target addresses in system memory.
-   This function does not flush posted write transactions from any PCI bridges. A PCI controller
-   specific action must be taken to guarantee that the posted write transactions have been flushed from
-   the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
-   a PCI read transaction from the PCI controller prior to calling Flush().
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-
-   @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
-                              bridge to system memory.
-   @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
-                              host bridge due to a hardware error.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoFlush (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This
-  )
-{
-  //
-  // not supported yet
-  //
-  return EFI_SUCCESS;
-}
-
-/**
-   Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
-   attributes that a PCI root bridge is currently using.
-
-   The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
-   and the mask of attributes that the PCI root bridge is currently using.
-
-   @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param Supported   A pointer to the mask of attributes that this PCI root bridge
-                      supports setting with SetAttributes().
-   @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
-                      currently using.
-
-   @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
-                                  bridge supports is returned in Supports. If Attributes is
-                                  not NULL, then the attributes that the PCI root bridge is currently
-                                  using is returned in Attributes.
-   @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoGetAttributes (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  OUT UINT64                           *Supported,
-  OUT UINT64                           *Attributes
-  )
-{
-  PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
-
-  if (Attributes == NULL && Supported == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Set the return value for Supported and Attributes
-  //
-  if (Supported != NULL) {
-    *Supported  = PrivateData->Supports;
-  }
-
-  if (Attributes != NULL) {
-    *Attributes = PrivateData->Attributes;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Sets attributes for a resource range on a PCI root bridge.
-
-   The SetAttributes() function sets the attributes specified in Attributes for the PCI root
-   bridge on the resource range specified by ResourceBase and ResourceLength. Since the
-   granularity of setting these attributes may vary from resource type to resource type, and from
-   platform to platform, the actual resource range and the one passed in by the caller may differ. As a
-   result, this function may set the attributes specified by Attributes on a larger resource range
-   than the caller requested. The actual range is returned in ResourceBase and
-   ResourceLength. The caller is responsible for verifying that the actual range for which the
-   attributes were set is acceptable.
-
-   @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[in]       Attributes      The mask of attributes to set. If the attribute bit
-                                    MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
-                                    MEMORY_DISABLE is set, then the resource range is specified by
-                                    ResourceBase and ResourceLength. If
-                                    MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
-                                    MEMORY_DISABLE are not set, then ResourceBase and
-                                    ResourceLength are ignored, and may be NULL.
-   @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
-                                    by the attributes specified by Attributes.
-   @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
-                                    attributes specified by Attributes.
-
-   @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
-   @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
-   @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoSetAttributes (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN     UINT64                           Attributes,
-  IN OUT UINT64                           *ResourceBase,
-  IN OUT UINT64                           *ResourceLength
-  )
-{
-  PCI_ROOT_BRIDGE_INSTANCE            *PrivateData;
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
-
-  if (Attributes != 0) {
-    if ((Attributes & (~(PrivateData->Supports))) != 0) {
-      return EFI_UNSUPPORTED;
-    }
-  }
-
-  //
-  // This is a generic driver for a PC-AT class system.  It does not have any
-  // chipset specific knowlegde, so none of the attributes can be set or
-  // cleared.  Any attempt to set attribute that are already set will succeed,
-  // and any attempt to set an attribute that is not supported will fail.
-  //
-  if (Attributes & (~PrivateData->Attributes)) {
-    return EFI_UNSUPPORTED;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-   Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
-   resource descriptors.
-
-   There are only two resource descriptor types from the ACPI Specification that may be used to
-   describe the current resources allocated to a PCI root bridge. These are the QWORD Address
-   Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
-   QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
-   or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
-   Address Space Descriptors followed by an End Tag.
-
-   @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-   @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
-                            current configuration of this PCI root bridge. The storage for the
-                            ACPI 2.0 resource descriptors is allocated by this function. The
-                            caller must treat the return buffer as read-only data, and the buffer
-                            must not be freed by the caller.
-
-   @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
-   @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
-   @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
-
-**/
-EFI_STATUS
-EFIAPI
-RootBridgeIoConfiguration (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,
-  OUT VOID                                **Resources
-  )
-{
-  PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
-  UINTN                                 Index;
-
-  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
-  for (Index = 0; Index < TypeMax; Index++) {
-    if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
-      Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
-      Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
-      Configuration.SpaceDesp[Index].AddrLen      = PrivateData->ResAllocNode[Index].Length;
-    }
-  }
-
-  *Resources = &Configuration;
-  return EFI_SUCCESS;
-}
-
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe
  2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2016-08-22  6:35 ` [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe Ard Biesheuvel
@ 2016-08-22 11:58 ` Laszlo Ersek
  5 siblings, 0 replies; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-22 11:58 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel

On 08/22/16 02:35, Ard Biesheuvel wrote:
> Now that Laszlo's virtio-gpu-pci have removed the last remaining obstacle,
> we can get rid of the special PciHostBridgeDxe implementation in ArmVirtPkg,
> and move to the generic one. This will allow us to perform DMA above 4GB
> without bounce buffering, and use 64-bit MMIO BARs.
> 
> Patch #1 removes the linux,pci-probe-only override which does more harm than
> good now that we switched to virtio-gp-pci, which does not expose a raw
> framebuffer.
> 
> Patch #2 implements PciHostBridgeLib for platforms exposing a PCI host bridge
> using a pci-host-ecam-generic DT node.
> 
> Patch #3 switches to the generic PciHostBridgeDxe, with no change in
> functionality other than support for DMA above 4 GB without bounce buffering.
> 
> Patch #4 adds support for 64-bit MMIO BARs
> 
> Patch #5 removes the now obsolete PciHostBridgeDxe from ArmVirPkg.
> 
> Ard Biesheuvel (5):
>   ArmVirtPkg/PciHostBridgeDxe: don't set linux,pci-probe-only DT
>     property
>   ArmVirtPkg: implement FdtPciHostBridgeLib
>   ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe
>   ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support
>   ArmVirtPkg: remove now unused PciHostBridgeDxe
> 
>  ArmVirtPkg/ArmVirtQemu.dsc                                     |    7 +-
>  ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc                           |    3 +-
>  ArmVirtPkg/ArmVirtQemuKernel.dsc                               |    7 +-
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c   |  417 ++++
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf |   56 +
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c                    | 1496 --------------
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h                    |  499 -----
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf               |   64 -
>  ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c                  | 2144 --------------------
>  9 files changed, 487 insertions(+), 4206 deletions(-)
>  create mode 100644 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>  create mode 100644 ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>  delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
>  delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h
>  delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
>  delete mode 100644 ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c
> 

Awesome! I'm unsure when I'll have time to review this series during the
Forum, but I should (and will) say that I'm very grateful to you for
picking this up!

Cheers
Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe
  2016-08-22  6:35 ` [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe Ard Biesheuvel
@ 2016-08-23 18:04   ` Ard Biesheuvel
  2016-08-31 12:24     ` Laszlo Ersek
  0 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-23 18:04 UTC (permalink / raw)
  To: edk2-devel-01, Laszlo Ersek; +Cc: Ard Biesheuvel

On 22 August 2016 at 08:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Wire up the FdtPciHostBridgeLib introduced in the previous patch
> to the generic PciHostBridgeDxe implementation, and drop the special
> ArmVirtPkg version. The former's dependency on gEfiCpuIo2ProtocolGuid
> is satisfied by adding ArmPciCpuIo2Dxe.inf as well, and adding the PCD
> gArmTokenSpaceGuid.PcdPciIoTranslation as a dynamic PCD.
>
> In terms of functionality, the only effect this change should have is
> that we will no longer use bounce buffers for DMA above 4 GB. Other
> than that, no functional changes are intended.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmVirtPkg/ArmVirtQemu.dsc                                   | 7 ++++++-
>  ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc                         | 3 ++-
>  ArmVirtPkg/ArmVirtQemuKernel.dsc                             | 7 ++++++-
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 4 ++--
>  4 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
> index 1d459756f61b..ddc72e7044f7 100644
> --- a/ArmVirtPkg/ArmVirtQemu.dsc
> +++ b/ArmVirtPkg/ArmVirtQemu.dsc
> @@ -69,6 +69,8 @@ [LibraryClasses.common]
>    QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>    PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
> +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
> +  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>
>  [LibraryClasses.common.UEFI_DRIVER]
>    UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
> @@ -210,6 +212,8 @@ [PcdsDynamicDefault.common]
>    # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
>    gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
>
> +  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
> +
>    #
>    # Set video resolution for boot options and for text setup.
>    # PlatformDxe can set the former at runtime.
> @@ -363,7 +367,8 @@ [Components.common]
>    #
>    # PCI support
>    #
> -  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
>        NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
> diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
> index 01e650d9e333..c56188f347ec 100644
> --- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
> +++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
> @@ -151,7 +151,8 @@ [FV.FvMain]
>    #
>    # PCI support
>    #
> -  INF ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> +  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>    INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
>    INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
>    INF OvmfPkg/Virtio10Dxe/Virtio10.inf
> diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
> index 99d2feba202b..305aa5bacb32 100644
> --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
> +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
> @@ -71,6 +71,8 @@ [LibraryClasses.common]
>    QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>    PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
> +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
> +  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>
>  [LibraryClasses.common.UEFI_DRIVER]
>    UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
> @@ -203,6 +205,8 @@ [PcdsDynamicDefault.common]
>    # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
>    gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
>
> +  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
> +
>    #
>    # Set video resolution for boot options and for text setup.
>    # PlatformDxe can set the former at runtime.
> @@ -349,7 +353,8 @@ [Components.common]
>    #
>    # PCI support
>    #
> -  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
> +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
>        NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> index 887ddb01f586..0aff149e8029 100644
> --- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> @@ -304,8 +304,8 @@ PciHostBridgeGetRootBridges (
>    RootBridge->Io.Limit              = IoBase + IoSize - 1;
>    RootBridge->Mem.Base              = Mmio32Base;
>    RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
> -  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
> -  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;
> +  RootBridge->MemAbove4G.Base       = MAX_UINT64;
> +  RootBridge->MemAbove4G.Limit      = 0;
>

This hunk was intended as a fixup for the previous patch, but I
accidentally folded it here instead.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property
  2016-08-22  6:35 ` [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property Ard Biesheuvel
@ 2016-08-23 21:23   ` Laszlo Ersek
  2016-08-24  5:30     ` Ard Biesheuvel
  0 siblings, 1 reply; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-23 21:23 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel

On 08/22/16 02:35, Ard Biesheuvel wrote:
> Setting the linux,pci-probe-only was intended to align OSes booting via
> DT with OSes booting via ACPI in the way they honor the PCI configuration
> performed by the firmware. However, ACPI on arm64 does not currently honor
> the firmware's PCI configuration, and the linux,pci-probe-only completely
> prevents any PCI reconfiguration from occurring under the OS, including
> what is needed to support PCI hotplug.
> 
> Since the primary use case was OS access to the GOP framebuffer (which
> breaks when the framebuffer BAR is moved when the OS reconfigures the
> PCI), we can undo this change now that ArmVirtQemu has moved to a GOP
> implementation that does not expose a raw framebuffer in the first place.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c | 38 --------------------
>  1 file changed, 38 deletions(-)
> 
> diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
> index 5063782bb392..669c90355889 100644
> --- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
> +++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
> @@ -79,42 +79,6 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
>  // Implementation
>  //
>  
> -STATIC
> -VOID
> -SetLinuxPciProbeOnlyProperty (
> -  IN FDT_CLIENT_PROTOCOL         *FdtClient
> -  )
> -{
> -  INT32         Node;
> -  UINT32        Tmp;
> -  EFI_STATUS    Status;
> -
> -  if (!FeaturePcdGet (PcdPureAcpiBoot)) {
> -    //
> -    // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI
> -    // setup we will perform in the firmware is honored by the Linux OS,
> -    // rather than torn down and done from scratch. This is generally a more
> -    // sensible approach, and aligns with what ACPI based OSes do typically.
> -    //
> -    // In case we are exposing an emulated VGA PCI device to the guest, which
> -    // may subsequently get exposed via the Graphics Output protocol and
> -    // driven as an efifb by Linux, we need this setting to prevent the
> -    // framebuffer from becoming unresponsive.
> -    //
> -    Status = FdtClient->GetOrInsertChosenNode (FdtClient, &Node);
> -
> -    if (!EFI_ERROR (Status)) {
> -      Tmp = SwapBytes32 (1);
> -      Status = FdtClient->SetNodeProperty (FdtClient, Node,
> -                            "linux,pci-probe-only", &Tmp, sizeof (Tmp));
> -    }
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((EFI_D_WARN,
> -        "Failed to set /chosen/linux,pci-probe-only property\n"));
> -    }
> -  }
> -}
> -
>  //
>  // We expect the "ranges" property of "pci-host-ecam-generic" to consist of
>  // records like this.
> @@ -293,8 +257,6 @@ ProcessPciHost (
>    //
>    ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
>  
> -  SetLinuxPciProbeOnlyProperty (FdtClient);
> -
>    DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
>      "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
>      ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
> 

I suggest to note in the commit message that this patch effectively
undoes commit 8b816c624dd407e1590d7c399c69ab307af3ef33. Can be done
without a resend, if you agree.

Reviewed-by: Laszlo Ersek <lersek@redhat.com>0

(Further review feedback will likely be very slow, for the known reasons
-- I try to process my email backlog whenever I find a reasonable time
slot. For larger patches, larger slots are necessary.)

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property
  2016-08-23 21:23   ` Laszlo Ersek
@ 2016-08-24  5:30     ` Ard Biesheuvel
  0 siblings, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-24  5:30 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: edk2-devel@lists.01.org

On 23 August 2016 at 23:23, Laszlo Ersek <lersek@redhat.com> wrote:
> On 08/22/16 02:35, Ard Biesheuvel wrote:
>> Setting the linux,pci-probe-only was intended to align OSes booting via
>> DT with OSes booting via ACPI in the way they honor the PCI configuration
>> performed by the firmware. However, ACPI on arm64 does not currently honor
>> the firmware's PCI configuration, and the linux,pci-probe-only completely
>> prevents any PCI reconfiguration from occurring under the OS, including
>> what is needed to support PCI hotplug.
>>
>> Since the primary use case was OS access to the GOP framebuffer (which
>> breaks when the framebuffer BAR is moved when the OS reconfigures the
>> PCI), we can undo this change now that ArmVirtQemu has moved to a GOP
>> implementation that does not expose a raw framebuffer in the first place.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c | 38 --------------------
>>  1 file changed, 38 deletions(-)
>>
>> diff --git a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
>> index 5063782bb392..669c90355889 100644
>> --- a/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
>> +++ b/ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
>> @@ -79,42 +79,6 @@ PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
>>  // Implementation
>>  //
>>
>> -STATIC
>> -VOID
>> -SetLinuxPciProbeOnlyProperty (
>> -  IN FDT_CLIENT_PROTOCOL         *FdtClient
>> -  )
>> -{
>> -  INT32         Node;
>> -  UINT32        Tmp;
>> -  EFI_STATUS    Status;
>> -
>> -  if (!FeaturePcdGet (PcdPureAcpiBoot)) {
>> -    //
>> -    // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI
>> -    // setup we will perform in the firmware is honored by the Linux OS,
>> -    // rather than torn down and done from scratch. This is generally a more
>> -    // sensible approach, and aligns with what ACPI based OSes do typically.
>> -    //
>> -    // In case we are exposing an emulated VGA PCI device to the guest, which
>> -    // may subsequently get exposed via the Graphics Output protocol and
>> -    // driven as an efifb by Linux, we need this setting to prevent the
>> -    // framebuffer from becoming unresponsive.
>> -    //
>> -    Status = FdtClient->GetOrInsertChosenNode (FdtClient, &Node);
>> -
>> -    if (!EFI_ERROR (Status)) {
>> -      Tmp = SwapBytes32 (1);
>> -      Status = FdtClient->SetNodeProperty (FdtClient, Node,
>> -                            "linux,pci-probe-only", &Tmp, sizeof (Tmp));
>> -    }
>> -    if (EFI_ERROR (Status)) {
>> -      DEBUG ((EFI_D_WARN,
>> -        "Failed to set /chosen/linux,pci-probe-only property\n"));
>> -    }
>> -  }
>> -}
>> -
>>  //
>>  // We expect the "ranges" property of "pci-host-ecam-generic" to consist of
>>  // records like this.
>> @@ -293,8 +257,6 @@ ProcessPciHost (
>>    //
>>    ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
>>
>> -  SetLinuxPciProbeOnlyProperty (FdtClient);
>> -
>>    DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
>>      "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
>>      ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
>>
>
> I suggest to note in the commit message that this patch effectively
> undoes commit 8b816c624dd407e1590d7c399c69ab307af3ef33. Can be done
> without a resend, if you agree.
>

Yes, that makes sense.

> Reviewed-by: Laszlo Ersek <lersek@redhat.com>0
>

Thanks


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib
  2016-08-22  6:35 ` [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib Ard Biesheuvel
@ 2016-08-24 15:01   ` Laszlo Ersek
  2016-08-24 15:19     ` Ard Biesheuvel
  0 siblings, 1 reply; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-24 15:01 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel

On 08/22/16 02:35, Ard Biesheuvel wrote:
> Implement PciHostBridgeLib for DT platforms that expose a PCI root bridge
> via a pci-host-ecam-generic DT node. The DT parsing logic is copied from
> the PciHostBridgeDxe implementation in ArmVirtPkg, with the one notable
> difference that we don't set the various legacy PCI attributes for IDE
> and VGA I/O ranges.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c   | 400 ++++++++++++++++++++
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf |  56 +++
>  2 files changed, 456 insertions(+)
> 
> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> new file mode 100644
> index 000000000000..887ddb01f586
> --- /dev/null
> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> @@ -0,0 +1,400 @@
> +/** @file
> +  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
> +
> +  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
> +
> +  This program and the accompanying materials are licensed and made available
> +  under the terms and conditions of the BSD License which accompanies this
> +  distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> +  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +#include <PiDxe.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include <Protocol/FdtClient.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +
> +#pragma pack(1)
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +#pragma pack ()
> +
> +STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
> +        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    EISA_PNP_ID(0x0A08), // PCI Express

Differs from 0x0A03, but this change is valid -- not only because we
have PCI Express here, but also because QEMU's ACPI generator produces
PNP0A08 as _HID (and PNP0A03 only as _CID) for PCI0, in acpi_dsdt_add_pci().

> +    0
> +  },
> +
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +//
> +// We expect the "ranges" property of "pci-host-ecam-generic" to consist of
> +// records like this.
> +//
> +#pragma pack (1)
> +typedef struct {
> +  UINT32 Type;
> +  UINT64 ChildBase;
> +  UINT64 CpuBase;
> +  UINT64 Size;
> +} DTB_PCI_HOST_RANGE_RECORD;
> +#pragma pack ()
> +
> +#define DTB_PCI_HOST_RANGE_RELOCATABLE  BIT31
> +#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
> +#define DTB_PCI_HOST_RANGE_ALIASED      BIT29
> +#define DTB_PCI_HOST_RANGE_MMIO32       BIT25
> +#define DTB_PCI_HOST_RANGE_MMIO64       (BIT25 | BIT24)
> +#define DTB_PCI_HOST_RANGE_IO           BIT24
> +#define DTB_PCI_HOST_RANGE_TYPEMASK     (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
> +
> +STATIC
> +EFI_STATUS
> +ProcessPciHost (
> +  OUT  UINT64    *IoBase,
> +  OUT  UINT64    *IoSize,
> +  OUT  UINT64    *IoTranslation,
> +  OUT  UINT64    *MmioBase,
> +  OUT  UINT64    *MmioSize,
> +  OUT  UINT64    *MmioTranslation,
> +  OUT  UINT32    *BusMin,
> +  OUT  UINT32    *BusMax
> +  )
> +{
> +  FDT_CLIENT_PROTOCOL         *FdtClient;
> +  INT32                       Node;
> +  UINT64                      ConfigBase, ConfigSize;
> +  CONST VOID                  *Prop;
> +  UINT32                      Len;
> +  UINT32                      RecordIdx;
> +  EFI_STATUS                  Status;
> +
> +  //
> +  // The following output arguments are initialized only in
> +  // order to suppress '-Werror=maybe-uninitialized' warnings
> +  // *incorrectly* emitted by some gcc versions.
> +  //
> +  *IoBase = 0;
> +  *IoTranslation = 0;
> +  *MmioBase = 0;
> +  *MmioTranslation = 0;
> +  *BusMin = 0;
> +  *BusMax = 0;
> +
> +  //
> +  // *IoSize and *MmioSize are initialized to zero because the logic below
> +  // requires it. However, since they are also affected by the issue reported
> +  // above, they are initialized early.
> +  //
> +  *IoSize = 0;
> +  *MmioSize = 0;
> +
> +  Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
> +                  (VOID **)&FdtClient);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",
> +                        &Node);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO,
> +      "%a: No 'pci-host-ecam-generic' compatible DT node found\n",
> +      __FUNCTION__));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG_CODE (
> +    INT32 Tmp;
> +
> +    //
> +    // A DT can legally describe multiple PCI host bridges, but we are not
> +    // equipped to deal with that. So assert that there is only one.
> +    //
> +    Status = FdtClient->FindNextCompatibleNode (FdtClient,
> +                          "pci-host-ecam-generic", Node, &Tmp);
> +    ASSERT (Status == EFI_NOT_FOUND);
> +  );
> +
> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);
> +  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {
> +    DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",
> +      __FUNCTION__));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  //
> +  // Fetch the ECAM window.
> +  //
> +  ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);
> +  ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);
> +
> +  //
> +  // Fetch the bus range (note: inclusive).
> +  //
> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,
> +                        &Len);
> +  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {
> +    DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",
> +      __FUNCTION__));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +  *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);
> +  *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);
> +
> +  //
> +  // Sanity check: the config space must accommodate all 4K register bytes of
> +  // all 8 functions of all 32 devices of all buses.
> +  //
> +  if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||
> +      DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {
> +    DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",
> +      __FUNCTION__));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  //
> +  // Iterate over "ranges".
> +  //
> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);
> +  if (EFI_ERROR (Status) || Len == 0 ||
> +      Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {
> +    DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);
> +       ++RecordIdx) {
> +    CONST DTB_PCI_HOST_RANGE_RECORD *Record;
> +
> +    Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;
> +    switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {
> +    case DTB_PCI_HOST_RANGE_IO:
> +      *IoBase = SwapBytes64 (Record->ChildBase);
> +      *IoSize = SwapBytes64 (Record->Size);
> +      *IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;
> +      break;
> +
> +    case DTB_PCI_HOST_RANGE_MMIO32:
> +      *MmioBase = SwapBytes64 (Record->ChildBase);
> +      *MmioSize = SwapBytes64 (Record->Size);
> +      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
> +
> +      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
> +          *MmioBase + *MmioSize > SIZE_4GB) {
> +        DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
> +        return EFI_PROTOCOL_ERROR;
> +      }
> +
> +      if (*MmioTranslation != 0) {
> +        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
> +          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
> +        return EFI_UNSUPPORTED;
> +      }
> +
> +      break;
> +    }
> +  }
> +  if (*IoSize == 0 || *MmioSize == 0) {
> +    DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
> +      (*IoSize == 0) ? "IO" : "MMIO32"));
> +    return EFI_PROTOCOL_ERROR;
> +  }
> +
> +  //
> +  // The dynamic PCD PcdPciExpressBaseAddress should have already been set,
> +  // and should match the value we found in the DT node.
> +  //
> +  ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
> +
> +  DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
> +    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
> +    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
> +    *MmioSize, *MmioTranslation));
> +  return EFI_SUCCESS;
> +}

Okay, the above seems to be preserved identically from
"ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c".

> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +          The array should be passed into PciHostBridgeFreeRootBridges()
> +          when it's not used.
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  UINTN *Count
> +  )
> +{
> +  PCI_ROOT_BRIDGE     *RootBridge;
> +  UINT64              IoBase, IoSize, IoTranslation;
> +  UINT64              Mmio32Base, Mmio32Size, Mmio32Translation;
> +  UINT32              BusMin, BusMax;
> +  EFI_STATUS          Status;
> +
> +  if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {
> +    DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));
> +
> +    *Count = 0;
> +    return NULL;
> +  }
> +
> +  Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &Mmio32Base,
> +             &Mmio32Size, &Mmio32Translation, &BusMin, &BusMax);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((EFI_D_INFO,

I propose to turn this into EFI_D_ERROR. At this point
FdtPciPcdProducerLib has located "pci-host-ecam-generic" and set
PcdPciExpressBaseAddress to a nonzero value, so any failure to process
the FDT node correctly should be reported on the ERROR level.

> +      "%a: failed to discover PCI host bridge: %s not present\n",
> +      __FUNCTION__, Status));

The "%s" format spec takes a CHAR16* argument, but Status has type
EFI_STATUS.

I would replace

  %s not present

with

  %r

in the format string.

> +    *Count = 0;
> +    return NULL;
> +  }
> +
> +  PcdSet64 (PcdPciIoTranslation, IoTranslation);

I agree this is necessary, but it's not in the right place, plus as-is,
it is not sufficient.

In <https://tianocore.acgmultimedia.com/show_bug.cgi?id=65#c0> I wrote
-- and I'm slightly reformatting it here, because the formatting got
lost in the GitHub -> BZ migration --:

    The main customization in ArmVirtPkg/PciHostBridgeDxe is that it
    emulates IO port accesses with an MMIO range, whose base address is
    parsed from the DTB.

    The core PciHostBridgeDxe driver delegates the IO port access
    implementation to EFI_CPU_IO2_PROTOCOL. @ardbiesheuvel recently
    implemented ArmPkg/Drivers/ArmPciCpuIo2Dxe (in commit 3dece14)
    which provides this protocol, backed by the same kind of
    translation as described above. The base address comes from
    gArmTokenSpaceGuid.PcdPciIoTranslation.

    Therefore:

    (1) We should extend our ArmVirtPkg/Library/FdtPciPcdProducerLib
        plugin library to locate the IO translation offset in the DTB,
        and store it in the above PCD.

    (2) We should include ArmPciCpuIo2Dxe in the ArmVirtQemu builds,
        plugging the above library into it.

    (3) We should implement a PciHostBridgeLib instance, and plug it
        into the core PciHostBridgeDxe driver.

        We should create one PCI_ROOT_BRIDGE object, populating it with
        the FTD Client code we are currently using in
        ArmVirtPkg/PciHostBridgeDxe.

    (4) Extra benefit: the core PciHostBridgeDxe driver supports 64-bit
        MMIO, we just have to parse those values from the DTB as well.

Steps (2) through (4) are implemented by this series, but I don't think
the above PcdSet64() call satisfies (1). What guarantees that by the
time ArmPciCpuIo2Dxe looks at it, PcdPciIoTranslation will be set?

... Especially because PciHostBridgeDxe.inf has a DEPEX on
gEfiCpuIo2ProtocolGuid, so the PcdSet64() above is bound to run *after*
ArmPciCpuIo2Dxe is dispatched?

Hmmmm... Are you making the argument that the PCD is set *between*
ArmPciCpuIo2Dxe's dispatch and actual use of the PCD? That is:

- ArmPciCpuIo2Dxe is dispatched
- PciHostBridgeDxe is dispatched
- we set the PCD in this lib (as part of PciHostBridgeDxe's startup)
- (much later) something makes a PCI IO or MEM access that causes
  PciHostBridgeDxe to talk to ArmPciCpuIo2Dxe
- ArmPciCpuIo2Dxe consumes the PCD

I think this is a valid argument to make -- I've even checked:
ArmPciCpuIo2Dxe indeed performs a PcdGet64() on every CpuIoServiceRead()
/ CpuIoServiceWrite(), and none in its entry point --, but it has to be
explained in detail.

This borders on a hack -- because ArmPciCpuIo2Dxe is not actually ready
for use when its entry point exits with success --, but I think we can
allow it, both ArmPciCpuIo2Dxe and this lib being platform specific, as
long as we document it profusely.

So please describe this quirk in the commit message, and add a large
comment right above the PcdSet64() call.

(Also, did you test this series with std VGA, on TCG? That will actually
put the IO translation to use.)

The alternative to the commit msg addition / code comment would be my
suggestion in (1), that is, to extend FdtPciPcdProducerLib with setting
PcdPciIoTranslation, and to link it into ArmPciCpuIo2Dxe via NULL
library resolution. I guess you don't like that, which is fine, but then
please add the docs. Thanks.


Independent request (just because I referenced the edk2 BZ above):
please add something like this to all of the commit messages:

Ref: https://tianocore.acgmultimedia.com/show_bug.cgi?id=65

> +
> +  *Count = 1;
> +  RootBridge = AllocateZeroPool (*Count * sizeof *RootBridge);

Please check for memory allocation failure here, and return in the usual
way if it fails.

Alternatively, you can do the exact same thing as with the device path:
give this singleton root bridge object static storage duration, and make
PciHostBridgeFreeRootBridges() a no-op.

> +
> +  RootBridge->Segment     = 0;
> +  RootBridge->Supports    = 0;
> +  RootBridge->Attributes  = RootBridge->Supports;

Hmmm, not so sure about this. This change breaks away from what we
currently have in "ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c",
function RootBridgeConstructor().

The attributes are documented in the UEFI spec (v2.6), "13.2 PCI Root
Bridge I/O Protocol". We do support IO emulation, so I think at least
some of those attributes should be preserved. Honestly, given that we
intend to support std VGA on at least TCG, I would keep all the current
attributes, except the IDE ones. Hmmm, I'd also drop
EFI_PCI_ATTRIBUTE_VGA_MEMORY. So, I'd keep:

  EFI_PCI_ATTRIBUTE_ISA_IO_16 |
  EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
  EFI_PCI_ATTRIBUTE_VGA_IO_16  |
  EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16

According to your commit message, these were dropped deliberately. Can
you please elaborate why we shouldn't keep the above four flags, despite
wanting to support stdvga on TCG? For now I think we should preserve
them, and the commit message should be updated.

> +
> +  RootBridge->DmaAbove4G  = TRUE;

OK, I think.

... Here you skip setting NoExtendedConfigSpace explicitly to FALSE. I
think that's fine (due to AllocateZeroPool() above, or else due to the
automatic zero-init of the (proposed) static variable), functionally
speaking. OK.

Same for ResourceAssigned -- defaults to FALSE, good.

> +
> +  RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
> +                                      EFI_PCI_HOST_BRIDGE_MEM64_DECODE ;

Here the EFI_PCI_HOST_BRIDGE_MEM64_DECODE bit belongs to patch #4 ("add
MMIO64 support"), not here, in my opinion. It should depend on whether
the FDT provides a 64-bit MMIO range.

(Also, gratuitous whitespace before the semicolon.)

> +
> +  RootBridge->Bus.Base              = BusMin;
> +  RootBridge->Bus.Limit             = BusMax;
> +  RootBridge->Io.Base               = IoBase;
> +  RootBridge->Io.Limit              = IoBase + IoSize - 1;
> +  RootBridge->Mem.Base              = Mmio32Base;
> +  RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
> +  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
> +  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;

This is valid for disabling the 64-bit MMIO range (temporarily), but
it's not consistent with how the prefetchable stuff is disabled below
(with MAX_UINT64 and 0). I suspect this is going to be modified in patch
#4 anyway, but I suggest to keep the consistency here.

> +
> +  //
> +  // No separate ranges for prefetchable and non-prefetchable BARs
> +  //
> +  RootBridge->PMem.Base             = MAX_UINT64;
> +  RootBridge->PMem.Limit            = 0;
> +  RootBridge->PMemAbove4G.Base      = MAX_UINT64;
> +  RootBridge->PMemAbove4G.Limit     = 0;
> +
> +  ASSERT (FixedPcdGet64 (PcdPciMmio32Translation) == 0);
> +  ASSERT (FixedPcdGet64 (PcdPciMmio64Translation) == 0);

OK.

> +
> +  RootBridge->NoExtendedConfigSpace = FALSE;

Ah! So here it is. How about moving it up to where the structure
definition would suggest it? Not too important, of course.

> +
> +  RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
> +
> +  return RootBridge;
> +}

Looks good.

> +
> +/**
> +  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().

This line is too long. Doesn't justify a repost on its own, but if you
repost for other reasons, it would be nice to wrap this.

> +
> +  @param Bridges The root bridge instances array.
> +  @param Count   The count of the array.
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> +  PCI_ROOT_BRIDGE *Bridges,
> +  UINTN           Count
> +  )
> +{
> +  FreePool (Bridges);
> +}

Good if we stick with AllocateZeroPool() -- augmented with error
checking --; otherwise, if you opt for the static object, this should
become an empty function.

> +
> +/**
> +  Inform the platform that the resource conflict happens.
> +
> +  @param HostBridgeHandle Handle of the Host Bridge.
> +  @param Configuration    Pointer to PCI I/O and PCI memory resource
> +                          descriptors. The Configuration contains the resources
> +                          for all the root bridges. The resource for each root
> +                          bridge is terminated with END descriptor and an
> +                          additional END is appended indicating the end of the
> +                          entire resources. The resource descriptor field
> +                          values follow the description in
> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +                          .SubmitResources().
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> +  EFI_HANDLE                        HostBridgeHandle,
> +  VOID                              *Configuration
> +  )
> +{
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> +  UINTN                             RootBridgeIndex;
> +  DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +    DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
> +      ASSERT (Descriptor->ResType <
> +              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
> +               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
> +               )
> +              );
> +      DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> +              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> +              Descriptor->AddrLen, Descriptor->AddrRangeMax
> +              ));
> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +        DEBUG ((EFI_D_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
> +                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
> +                ((Descriptor->SpecificFlag &
> +                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
> +                  ) != 0) ? L" (Prefetchable)" : L""
> +                ));
> +      }
> +    }
> +    //
> +    // Skip the END descriptor for root bridge
> +    //
> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
> +                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
> +                   );
> +  }
> +}

Okay, this function is directly copied from
"OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c".

> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
> new file mode 100644
> index 000000000000..16beef0c2425
> --- /dev/null
> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
> @@ -0,0 +1,56 @@
> +## @file
> +#  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
> +#
> +#  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
> +#
> +#  This program and the accompanying materials are licensed and made available
> +#  under the terms and conditions of the BSD License which accompanies this
> +#  distribution. The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
> +#  IMPLIED.
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = AmdStyxPciHostBridgeLib

The BASE_NAME is wrong.

> +  FILE_GUID                      = 05E7AB83-EF8D-482D-80F8-905B73377A15
> +  MODULE_TYPE                    = BASE

I think this should be DXE_DRIVER, for consistency. The parameter list
of the entry point function is irrelevant here, but in a BASE type
library, we are supposed to use RETURN_STATUS, not EFI_STATUS (although
those types and their values are identical). The C file added above uses
EFI_STATUS in a bunch of places, so I'd make the module type DXE_DRIVER,
for consistency.

> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib
> +
> +#
> +# The following information is for reference only and not required by the build
> +# tools.
> +#
> +#  VALID_ARCHITECTURES           = AARCH64

Not to be used in the ARM build of ArmVirtQemu?

> +#
> +
> +[Sources]
> +  FdtPciHostBridgeLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  ArmPkg/ArmPkg.dec
> +  ArmVirtPkg/ArmVirtPkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  DevicePathLib
> +  MemoryAllocationLib
> +  PciPcdProducerLib
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdPciMmio32Translation
> +  gArmTokenSpaceGuid.PcdPciMmio64Translation
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +  gArmTokenSpaceGuid.PcdPciIoTranslation
> +
> +[Depex]
> +  gFdtClientProtocolGuid
> 

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib
  2016-08-24 15:01   ` Laszlo Ersek
@ 2016-08-24 15:19     ` Ard Biesheuvel
  2016-08-31 13:51       ` Laszlo Ersek
  0 siblings, 1 reply; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-24 15:19 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: edk2-devel@lists.01.org

On 24 August 2016 at 17:01, Laszlo Ersek <lersek@redhat.com> wrote:
> On 08/22/16 02:35, Ard Biesheuvel wrote:
>> Implement PciHostBridgeLib for DT platforms that expose a PCI root bridge
>> via a pci-host-ecam-generic DT node. The DT parsing logic is copied from
>> the PciHostBridgeDxe implementation in ArmVirtPkg, with the one notable
>> difference that we don't set the various legacy PCI attributes for IDE
>> and VGA I/O ranges.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c   | 400 ++++++++++++++++++++
>>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf |  56 +++
>>  2 files changed, 456 insertions(+)
>>
>> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>> new file mode 100644
>> index 000000000000..887ddb01f586
>> --- /dev/null
>> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>> @@ -0,0 +1,400 @@
>> +/** @file
>> +  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
>> +
>> +  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>> +
>> +  This program and the accompanying materials are licensed and made available
>> +  under the terms and conditions of the BSD License which accompanies this
>> +  distribution.  The full text of the license may be found at
>> +  http://opensource.org/licenses/bsd-license.php.
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
>> +  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +
>> +**/
>> +#include <PiDxe.h>
>> +#include <Library/PciHostBridgeLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/DevicePathLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Library/PcdLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +
>> +#include <Protocol/FdtClient.h>
>> +#include <Protocol/PciRootBridgeIo.h>
>> +#include <Protocol/PciHostBridgeResourceAllocation.h>
>> +
>> +#pragma pack(1)
>> +typedef struct {
>> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
>> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
>> +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
>> +#pragma pack ()
>> +
>> +STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
>> +  {
>> +    {
>> +      ACPI_DEVICE_PATH,
>> +      ACPI_DP,
>> +      {
>> +        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
>> +        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
>> +      }
>> +    },
>> +    EISA_PNP_ID(0x0A08), // PCI Express
>
> Differs from 0x0A03, but this change is valid -- not only because we
> have PCI Express here, but also because QEMU's ACPI generator produces
> PNP0A08 as _HID (and PNP0A03 only as _CID) for PCI0, in acpi_dsdt_add_pci().
>
>> +    0
>> +  },
>> +
>> +  {
>> +    END_DEVICE_PATH_TYPE,
>> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
>> +    {
>> +      END_DEVICE_PATH_LENGTH,
>> +      0
>> +    }
>> +  }
>> +};
>> +
>> +GLOBAL_REMOVE_IF_UNREFERENCED
>> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
>> +  L"Mem", L"I/O", L"Bus"
>> +};
>> +
>> +//
>> +// We expect the "ranges" property of "pci-host-ecam-generic" to consist of
>> +// records like this.
>> +//
>> +#pragma pack (1)
>> +typedef struct {
>> +  UINT32 Type;
>> +  UINT64 ChildBase;
>> +  UINT64 CpuBase;
>> +  UINT64 Size;
>> +} DTB_PCI_HOST_RANGE_RECORD;
>> +#pragma pack ()
>> +
>> +#define DTB_PCI_HOST_RANGE_RELOCATABLE  BIT31
>> +#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
>> +#define DTB_PCI_HOST_RANGE_ALIASED      BIT29
>> +#define DTB_PCI_HOST_RANGE_MMIO32       BIT25
>> +#define DTB_PCI_HOST_RANGE_MMIO64       (BIT25 | BIT24)
>> +#define DTB_PCI_HOST_RANGE_IO           BIT24
>> +#define DTB_PCI_HOST_RANGE_TYPEMASK     (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
>> +
>> +STATIC
>> +EFI_STATUS
>> +ProcessPciHost (
>> +  OUT  UINT64    *IoBase,
>> +  OUT  UINT64    *IoSize,
>> +  OUT  UINT64    *IoTranslation,
>> +  OUT  UINT64    *MmioBase,
>> +  OUT  UINT64    *MmioSize,
>> +  OUT  UINT64    *MmioTranslation,
>> +  OUT  UINT32    *BusMin,
>> +  OUT  UINT32    *BusMax
>> +  )
>> +{
>> +  FDT_CLIENT_PROTOCOL         *FdtClient;
>> +  INT32                       Node;
>> +  UINT64                      ConfigBase, ConfigSize;
>> +  CONST VOID                  *Prop;
>> +  UINT32                      Len;
>> +  UINT32                      RecordIdx;
>> +  EFI_STATUS                  Status;
>> +
>> +  //
>> +  // The following output arguments are initialized only in
>> +  // order to suppress '-Werror=maybe-uninitialized' warnings
>> +  // *incorrectly* emitted by some gcc versions.
>> +  //
>> +  *IoBase = 0;
>> +  *IoTranslation = 0;
>> +  *MmioBase = 0;
>> +  *MmioTranslation = 0;
>> +  *BusMin = 0;
>> +  *BusMax = 0;
>> +
>> +  //
>> +  // *IoSize and *MmioSize are initialized to zero because the logic below
>> +  // requires it. However, since they are also affected by the issue reported
>> +  // above, they are initialized early.
>> +  //
>> +  *IoSize = 0;
>> +  *MmioSize = 0;
>> +
>> +  Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
>> +                  (VOID **)&FdtClient);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",
>> +                        &Node);
>> +  if (EFI_ERROR (Status)) {
>> +    DEBUG ((EFI_D_INFO,
>> +      "%a: No 'pci-host-ecam-generic' compatible DT node found\n",
>> +      __FUNCTION__));
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  DEBUG_CODE (
>> +    INT32 Tmp;
>> +
>> +    //
>> +    // A DT can legally describe multiple PCI host bridges, but we are not
>> +    // equipped to deal with that. So assert that there is only one.
>> +    //
>> +    Status = FdtClient->FindNextCompatibleNode (FdtClient,
>> +                          "pci-host-ecam-generic", Node, &Tmp);
>> +    ASSERT (Status == EFI_NOT_FOUND);
>> +  );
>> +
>> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);
>> +  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {
>> +    DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",
>> +      __FUNCTION__));
>> +    return EFI_PROTOCOL_ERROR;
>> +  }
>> +
>> +  //
>> +  // Fetch the ECAM window.
>> +  //
>> +  ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);
>> +  ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);
>> +
>> +  //
>> +  // Fetch the bus range (note: inclusive).
>> +  //
>> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,
>> +                        &Len);
>> +  if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {
>> +    DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",
>> +      __FUNCTION__));
>> +    return EFI_PROTOCOL_ERROR;
>> +  }
>> +  *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);
>> +  *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);
>> +
>> +  //
>> +  // Sanity check: the config space must accommodate all 4K register bytes of
>> +  // all 8 functions of all 32 devices of all buses.
>> +  //
>> +  if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||
>> +      DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {
>> +    DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",
>> +      __FUNCTION__));
>> +    return EFI_PROTOCOL_ERROR;
>> +  }
>> +
>> +  //
>> +  // Iterate over "ranges".
>> +  //
>> +  Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);
>> +  if (EFI_ERROR (Status) || Len == 0 ||
>> +      Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {
>> +    DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));
>> +    return EFI_PROTOCOL_ERROR;
>> +  }
>> +
>> +  for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);
>> +       ++RecordIdx) {
>> +    CONST DTB_PCI_HOST_RANGE_RECORD *Record;
>> +
>> +    Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;
>> +    switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {
>> +    case DTB_PCI_HOST_RANGE_IO:
>> +      *IoBase = SwapBytes64 (Record->ChildBase);
>> +      *IoSize = SwapBytes64 (Record->Size);
>> +      *IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;
>> +      break;
>> +
>> +    case DTB_PCI_HOST_RANGE_MMIO32:
>> +      *MmioBase = SwapBytes64 (Record->ChildBase);
>> +      *MmioSize = SwapBytes64 (Record->Size);
>> +      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
>> +
>> +      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
>> +          *MmioBase + *MmioSize > SIZE_4GB) {
>> +        DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
>> +        return EFI_PROTOCOL_ERROR;
>> +      }
>> +
>> +      if (*MmioTranslation != 0) {
>> +        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
>> +          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
>> +        return EFI_UNSUPPORTED;
>> +      }
>> +
>> +      break;
>> +    }
>> +  }
>> +  if (*IoSize == 0 || *MmioSize == 0) {
>> +    DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
>> +      (*IoSize == 0) ? "IO" : "MMIO32"));
>> +    return EFI_PROTOCOL_ERROR;
>> +  }
>> +
>> +  //
>> +  // The dynamic PCD PcdPciExpressBaseAddress should have already been set,
>> +  // and should match the value we found in the DT node.
>> +  //
>> +  ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
>> +
>> +  DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
>> +    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
>> +    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
>> +    *MmioSize, *MmioTranslation));
>> +  return EFI_SUCCESS;
>> +}
>
> Okay, the above seems to be preserved identically from
> "ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c".
>

Yes. That is why I decided to remove the linux,pci-probe-only hack first.

>> +/**
>> +  Return all the root bridge instances in an array.
>> +
>> +  @param Count  Return the count of root bridge instances.
>> +
>> +  @return All the root bridge instances in an array.
>> +          The array should be passed into PciHostBridgeFreeRootBridges()
>> +          when it's not used.
>> +**/
>> +PCI_ROOT_BRIDGE *
>> +EFIAPI
>> +PciHostBridgeGetRootBridges (
>> +  UINTN *Count
>> +  )
>> +{
>> +  PCI_ROOT_BRIDGE     *RootBridge;
>> +  UINT64              IoBase, IoSize, IoTranslation;
>> +  UINT64              Mmio32Base, Mmio32Size, Mmio32Translation;
>> +  UINT32              BusMin, BusMax;
>> +  EFI_STATUS          Status;
>> +
>> +  if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {
>> +    DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));
>> +
>> +    *Count = 0;
>> +    return NULL;
>> +  }
>> +
>> +  Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &Mmio32Base,
>> +             &Mmio32Size, &Mmio32Translation, &BusMin, &BusMax);
>> +  if (EFI_ERROR (Status)) {
>> +    DEBUG ((EFI_D_INFO,
>
> I propose to turn this into EFI_D_ERROR. At this point
> FdtPciPcdProducerLib has located "pci-host-ecam-generic" and set
> PcdPciExpressBaseAddress to a nonzero value, so any failure to process
> the FDT node correctly should be reported on the ERROR level.
>

Agreed.

>> +      "%a: failed to discover PCI host bridge: %s not present\n",
>> +      __FUNCTION__, Status));
>
> The "%s" format spec takes a CHAR16* argument, but Status has type
> EFI_STATUS.
>
> I would replace
>
>   %s not present
>
> with
>
>   %r
>
> in the format string.
>

Ah yes, I fudged that. Will fix.

>> +    *Count = 0;
>> +    return NULL;
>> +  }
>> +
>> +  PcdSet64 (PcdPciIoTranslation, IoTranslation);
>
> I agree this is necessary, but it's not in the right place, plus as-is,
> it is not sufficient.
>
> In <https://tianocore.acgmultimedia.com/show_bug.cgi?id=65#c0> I wrote
> -- and I'm slightly reformatting it here, because the formatting got
> lost in the GitHub -> BZ migration --:
>
>     The main customization in ArmVirtPkg/PciHostBridgeDxe is that it
>     emulates IO port accesses with an MMIO range, whose base address is
>     parsed from the DTB.
>
>     The core PciHostBridgeDxe driver delegates the IO port access
>     implementation to EFI_CPU_IO2_PROTOCOL. @ardbiesheuvel recently
>     implemented ArmPkg/Drivers/ArmPciCpuIo2Dxe (in commit 3dece14)
>     which provides this protocol, backed by the same kind of
>     translation as described above. The base address comes from
>     gArmTokenSpaceGuid.PcdPciIoTranslation.
>
>     Therefore:
>
>     (1) We should extend our ArmVirtPkg/Library/FdtPciPcdProducerLib
>         plugin library to locate the IO translation offset in the DTB,
>         and store it in the above PCD.
>
>     (2) We should include ArmPciCpuIo2Dxe in the ArmVirtQemu builds,
>         plugging the above library into it.
>
>     (3) We should implement a PciHostBridgeLib instance, and plug it
>         into the core PciHostBridgeDxe driver.
>
>         We should create one PCI_ROOT_BRIDGE object, populating it with
>         the FTD Client code we are currently using in
>         ArmVirtPkg/PciHostBridgeDxe.
>
>     (4) Extra benefit: the core PciHostBridgeDxe driver supports 64-bit
>         MMIO, we just have to parse those values from the DTB as well.
>
> Steps (2) through (4) are implemented by this series, but I don't think
> the above PcdSet64() call satisfies (1). What guarantees that by the
> time ArmPciCpuIo2Dxe looks at it, PcdPciIoTranslation will be set?
>
> ... Especially because PciHostBridgeDxe.inf has a DEPEX on
> gEfiCpuIo2ProtocolGuid, so the PcdSet64() above is bound to run *after*
> ArmPciCpuIo2Dxe is dispatched?
>
> Hmmmm... Are you making the argument that the PCD is set *between*
> ArmPciCpuIo2Dxe's dispatch and actual use of the PCD? That is:
>
> - ArmPciCpuIo2Dxe is dispatched
> - PciHostBridgeDxe is dispatched
> - we set the PCD in this lib (as part of PciHostBridgeDxe's startup)
> - (much later) something makes a PCI IO or MEM access that causes
>   PciHostBridgeDxe to talk to ArmPciCpuIo2Dxe
> - ArmPciCpuIo2Dxe consumes the PCD
>
> I think this is a valid argument to make -- I've even checked:
> ArmPciCpuIo2Dxe indeed performs a PcdGet64() on every CpuIoServiceRead()
> / CpuIoServiceWrite(), and none in its entry point --, but it has to be
> explained in detail.
>
> This borders on a hack -- because ArmPciCpuIo2Dxe is not actually ready
> for use when its entry point exits with success --, but I think we can
> allow it, both ArmPciCpuIo2Dxe and this lib being platform specific, as
> long as we document it profusely.
>
> So please describe this quirk in the commit message, and add a large
> comment right above the PcdSet64() call.
>
> (Also, did you test this series with std VGA, on TCG? That will actually
> put the IO translation to use.)
>
> The alternative to the commit msg addition / code comment would be my
> suggestion in (1), that is, to extend FdtPciPcdProducerLib with setting
> PcdPciIoTranslation, and to link it into ArmPciCpuIo2Dxe via NULL
> library resolution. I guess you don't like that, which is fine, but then
> please add the docs. Thanks.
>

Actually, I prefer your original suggestion, to add it to
FdtPciPcdProducerLib. That way, we no longer have to set any PCDs in
this code, which is much cleaner imo

>
> Independent request (just because I referenced the edk2 BZ above):
> please add something like this to all of the commit messages:
>
> Ref: https://tianocore.acgmultimedia.com/show_bug.cgi?id=65
>

Sure

>> +
>> +  *Count = 1;
>> +  RootBridge = AllocateZeroPool (*Count * sizeof *RootBridge);
>
> Please check for memory allocation failure here, and return in the usual
> way if it fails.
>
> Alternatively, you can do the exact same thing as with the device path:
> give this singleton root bridge object static storage duration, and make
> PciHostBridgeFreeRootBridges() a no-op.
>

For count == 1, that makes sense of course, and we currently don't
deal with anything else. I am not sure how likely that is to change,
though? I think it has been suggested to allow PCI pass through of
non-DMA coherent PCI devices using a separate PCI host, but I am not
sure if that is ever going to materialize, especially since host
systems that have an SMMU wired to their PCI rc (which I suppose is a
requirement for PCI pass through in real-world scenarios) should be
able to perform coherent DMA

>> +
>> +  RootBridge->Segment     = 0;
>> +  RootBridge->Supports    = 0;
>> +  RootBridge->Attributes  = RootBridge->Supports;
>
> Hmmm, not so sure about this. This change breaks away from what we
> currently have in "ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c",
> function RootBridgeConstructor().
>
> The attributes are documented in the UEFI spec (v2.6), "13.2 PCI Root
> Bridge I/O Protocol". We do support IO emulation, so I think at least
> some of those attributes should be preserved. Honestly, given that we
> intend to support std VGA on at least TCG, I would keep all the current
> attributes, except the IDE ones. Hmmm, I'd also drop
> EFI_PCI_ATTRIBUTE_VGA_MEMORY. So, I'd keep:
>
>   EFI_PCI_ATTRIBUTE_ISA_IO_16 |
>   EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
>   EFI_PCI_ATTRIBUTE_VGA_IO_16  |
>   EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16
>
> According to your commit message, these were dropped deliberately. Can
> you please elaborate why we shouldn't keep the above four flags, despite
> wanting to support stdvga on TCG? For now I think we should preserve
> them, and the commit message should be updated.
>

I simply thought we didn't need any of them, but I am happy to keep
all of them, or just the ones above.

>> +
>> +  RootBridge->DmaAbove4G  = TRUE;
>
> OK, I think.
>
> ... Here you skip setting NoExtendedConfigSpace explicitly to FALSE. I
> think that's fine (due to AllocateZeroPool() above, or else due to the
> automatic zero-init of the (proposed) static variable), functionally
> speaking. OK.
>
> Same for ResourceAssigned -- defaults to FALSE, good.
>
>> +
>> +  RootBridge->AllocationAttributes  = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM |
>> +                                      EFI_PCI_HOST_BRIDGE_MEM64_DECODE ;
>
> Here the EFI_PCI_HOST_BRIDGE_MEM64_DECODE bit belongs to patch #4 ("add
> MMIO64 support"), not here, in my opinion. It should depend on whether
> the FDT provides a 64-bit MMIO range.
>

OK, will fix that

> (Also, gratuitous whitespace before the semicolon.)
>
>> +
>> +  RootBridge->Bus.Base              = BusMin;
>> +  RootBridge->Bus.Limit             = BusMax;
>> +  RootBridge->Io.Base               = IoBase;
>> +  RootBridge->Io.Limit              = IoBase + IoSize - 1;
>> +  RootBridge->Mem.Base              = Mmio32Base;
>> +  RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
>> +  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
>> +  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;
>
> This is valid for disabling the 64-bit MMIO range (temporarily), but
> it's not consistent with how the prefetchable stuff is disabled below
> (with MAX_UINT64 and 0). I suspect this is going to be modified in patch
> #4 anyway, but I suggest to keep the consistency here.
>

Actually, I fixed that up but folded the hunk into the wrong patch.

>> +
>> +  //
>> +  // No separate ranges for prefetchable and non-prefetchable BARs
>> +  //
>> +  RootBridge->PMem.Base             = MAX_UINT64;
>> +  RootBridge->PMem.Limit            = 0;
>> +  RootBridge->PMemAbove4G.Base      = MAX_UINT64;
>> +  RootBridge->PMemAbove4G.Limit     = 0;
>> +
>> +  ASSERT (FixedPcdGet64 (PcdPciMmio32Translation) == 0);
>> +  ASSERT (FixedPcdGet64 (PcdPciMmio64Translation) == 0);
>
> OK.
>
>> +
>> +  RootBridge->NoExtendedConfigSpace = FALSE;
>
> Ah! So here it is. How about moving it up to where the structure
> definition would suggest it? Not too important, of course.
>
>> +
>> +  RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath;
>> +
>> +  return RootBridge;
>> +}
>
> Looks good.
>
>> +
>> +/**
>> +  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
>
> This line is too long. Doesn't justify a repost on its own, but if you
> repost for other reasons, it would be nice to wrap this.
>
>> +
>> +  @param Bridges The root bridge instances array.
>> +  @param Count   The count of the array.
>> +**/
>> +VOID
>> +EFIAPI
>> +PciHostBridgeFreeRootBridges (
>> +  PCI_ROOT_BRIDGE *Bridges,
>> +  UINTN           Count
>> +  )
>> +{
>> +  FreePool (Bridges);
>> +}
>
> Good if we stick with AllocateZeroPool() -- augmented with error
> checking --; otherwise, if you opt for the static object, this should
> become an empty function.
>
>> +
>> +/**
>> +  Inform the platform that the resource conflict happens.
>> +
>> +  @param HostBridgeHandle Handle of the Host Bridge.
>> +  @param Configuration    Pointer to PCI I/O and PCI memory resource
>> +                          descriptors. The Configuration contains the resources
>> +                          for all the root bridges. The resource for each root
>> +                          bridge is terminated with END descriptor and an
>> +                          additional END is appended indicating the end of the
>> +                          entire resources. The resource descriptor field
>> +                          values follow the description in
>> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
>> +                          .SubmitResources().
>> +**/
>> +VOID
>> +EFIAPI
>> +PciHostBridgeResourceConflict (
>> +  EFI_HANDLE                        HostBridgeHandle,
>> +  VOID                              *Configuration
>> +  )
>> +{
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
>> +  UINTN                             RootBridgeIndex;
>> +  DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
>> +
>> +  RootBridgeIndex = 0;
>> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
>> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
>> +    DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
>> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
>> +      ASSERT (Descriptor->ResType <
>> +              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
>> +               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
>> +               )
>> +              );
>> +      DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
>> +              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
>> +              Descriptor->AddrLen, Descriptor->AddrRangeMax
>> +              ));
>> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
>> +        DEBUG ((EFI_D_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
>> +                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
>> +                ((Descriptor->SpecificFlag &
>> +                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
>> +                  ) != 0) ? L" (Prefetchable)" : L""
>> +                ));
>> +      }
>> +    }
>> +    //
>> +    // Skip the END descriptor for root bridge
>> +    //
>> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
>> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
>> +                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
>> +                   );
>> +  }
>> +}
>
> Okay, this function is directly copied from
> "OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c".
>
>> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>> new file mode 100644
>> index 000000000000..16beef0c2425
>> --- /dev/null
>> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>> @@ -0,0 +1,56 @@
>> +## @file
>> +#  PCI Host Bridge Library instance for pci-ecam-generic DT nodes
>> +#
>> +#  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>> +#
>> +#  This program and the accompanying materials are licensed and made available
>> +#  under the terms and conditions of the BSD License which accompanies this
>> +#  distribution. The full text of the license may be found at
>> +#  http://opensource.org/licenses/bsd-license.php
>> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
>> +#  IMPLIED.
>> +#
>> +#
>> +##
>> +
>> +[Defines]
>> +  INF_VERSION                    = 0x00010005
>> +  BASE_NAME                      = AmdStyxPciHostBridgeLib
>
> The BASE_NAME is wrong.
>

Oops

>> +  FILE_GUID                      = 05E7AB83-EF8D-482D-80F8-905B73377A15
>> +  MODULE_TYPE                    = BASE
>
> I think this should be DXE_DRIVER, for consistency. The parameter list
> of the entry point function is irrelevant here, but in a BASE type
> library, we are supposed to use RETURN_STATUS, not EFI_STATUS (although
> those types and their values are identical). The C file added above uses
> EFI_STATUS in a bunch of places, so I'd make the module type DXE_DRIVER,
> for consistency.
>

Sure

>> +  VERSION_STRING                 = 1.0
>> +  LIBRARY_CLASS                  = PciHostBridgeLib
>> +
>> +#
>> +# The following information is for reference only and not required by the build
>> +# tools.
>> +#
>> +#  VALID_ARCHITECTURES           = AARCH64
>
> Not to be used in the ARM build of ArmVirtQemu?
>

Actually, it should but I haven't tried.

>> +#
>> +
>> +[Sources]
>> +  FdtPciHostBridgeLib.c
>> +
>> +[Packages]
>> +  MdePkg/MdePkg.dec
>> +  MdeModulePkg/MdeModulePkg.dec
>> +  ArmPkg/ArmPkg.dec
>> +  ArmVirtPkg/ArmVirtPkg.dec
>> +
>> +[LibraryClasses]
>> +  DebugLib
>> +  DevicePathLib
>> +  MemoryAllocationLib
>> +  PciPcdProducerLib
>> +
>> +[FixedPcd]
>> +  gArmTokenSpaceGuid.PcdPciMmio32Translation
>> +  gArmTokenSpaceGuid.PcdPciMmio64Translation
>> +
>> +[Pcd]
>> +  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
>> +  gArmTokenSpaceGuid.PcdPciIoTranslation
>> +
>> +[Depex]
>> +  gFdtClientProtocolGuid
>>
>
> Thanks!
> Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe
  2016-08-23 18:04   ` Ard Biesheuvel
@ 2016-08-31 12:24     ` Laszlo Ersek
  0 siblings, 0 replies; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-31 12:24 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel-01

On 08/23/16 20:04, Ard Biesheuvel wrote:
> On 22 August 2016 at 08:35, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> Wire up the FdtPciHostBridgeLib introduced in the previous patch
>> to the generic PciHostBridgeDxe implementation, and drop the special
>> ArmVirtPkg version. The former's dependency on gEfiCpuIo2ProtocolGuid
>> is satisfied by adding ArmPciCpuIo2Dxe.inf as well, and adding the PCD
>> gArmTokenSpaceGuid.PcdPciIoTranslation as a dynamic PCD.
>>
>> In terms of functionality, the only effect this change should have is
>> that we will no longer use bounce buffers for DMA above 4 GB. Other
>> than that, no functional changes are intended.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  ArmVirtPkg/ArmVirtQemu.dsc                                   | 7 ++++++-
>>  ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc                         | 3 ++-
>>  ArmVirtPkg/ArmVirtQemuKernel.dsc                             | 7 ++++++-
>>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 4 ++--
>>  4 files changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
>> index 1d459756f61b..ddc72e7044f7 100644
>> --- a/ArmVirtPkg/ArmVirtQemu.dsc
>> +++ b/ArmVirtPkg/ArmVirtQemu.dsc
>> @@ -69,6 +69,8 @@ [LibraryClasses.common]
>>    QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
>>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>>    PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
>> +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
>> +  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>>
>>  [LibraryClasses.common.UEFI_DRIVER]
>>    UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
>> @@ -210,6 +212,8 @@ [PcdsDynamicDefault.common]
>>    # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
>>    gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
>>
>> +  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
>> +
>>    #
>>    # Set video resolution for boot options and for text setup.
>>    # PlatformDxe can set the former at runtime.
>> @@ -363,7 +367,8 @@ [Components.common]
>>    #
>>    # PCI support
>>    #
>> -  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
>> +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
>> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>>      <LibraryClasses>
>>        NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
>> diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
>> index 01e650d9e333..c56188f347ec 100644
>> --- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
>> +++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
>> @@ -151,7 +151,8 @@ [FV.FvMain]
>>    #
>>    # PCI support
>>    #
>> -  INF ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
>> +  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
>> +  INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>>    INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
>>    INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
>>    INF OvmfPkg/Virtio10Dxe/Virtio10.inf
>> diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
>> index 99d2feba202b..305aa5bacb32 100644
>> --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
>> +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
>> @@ -71,6 +71,8 @@ [LibraryClasses.common]
>>    QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
>>    FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
>>    PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
>> +  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
>> +  PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
>>
>>  [LibraryClasses.common.UEFI_DRIVER]
>>    UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
>> @@ -203,6 +205,8 @@ [PcdsDynamicDefault.common]
>>    # PCD and PcdPciDisableBusEnumeration above have not been assigned yet
>>    gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xFFFFFFFFFFFFFFFF
>>
>> +  gArmTokenSpaceGuid.PcdPciIoTranslation|0x0
>> +
>>    #
>>    # Set video resolution for boot options and for text setup.
>>    # PlatformDxe can set the former at runtime.
>> @@ -349,7 +353,8 @@ [Components.common]
>>    #
>>    # PCI support
>>    #
>> -  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf
>> +  ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
>> +  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
>>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>>      <LibraryClasses>
>>        NULL|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
>> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>> index 887ddb01f586..0aff149e8029 100644
>> --- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
>> @@ -304,8 +304,8 @@ PciHostBridgeGetRootBridges (
>>    RootBridge->Io.Limit              = IoBase + IoSize - 1;
>>    RootBridge->Mem.Base              = Mmio32Base;
>>    RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
>> -  RootBridge->MemAbove4G.Base       = 0x100000000ULL;
>> -  RootBridge->MemAbove4G.Limit      = 0xFFFFFFFF;
>> +  RootBridge->MemAbove4G.Base       = MAX_UINT64;
>> +  RootBridge->MemAbove4G.Limit      = 0;
>>
> 
> This hunk was intended as a fixup for the previous patch, but I
> accidentally folded it here instead.

With that fixed up, for this patch:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib
  2016-08-24 15:19     ` Ard Biesheuvel
@ 2016-08-31 13:51       ` Laszlo Ersek
  2016-08-31 13:54         ` Ard Biesheuvel
  0 siblings, 1 reply; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-31 13:51 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel@lists.01.org

On 08/24/16 17:19, Ard Biesheuvel wrote:
> On 24 August 2016 at 17:01, Laszlo Ersek <lersek@redhat.com> wrote:
>> On 08/22/16 02:35, Ard Biesheuvel wrote:

>>> +  PcdSet64 (PcdPciIoTranslation, IoTranslation);
>>
>> I agree this is necessary, but it's not in the right place, plus as-is,
>> it is not sufficient.
>>
>> In <https://tianocore.acgmultimedia.com/show_bug.cgi?id=65#c0> I wrote
>> -- and I'm slightly reformatting it here, because the formatting got
>> lost in the GitHub -> BZ migration --:
>>
>>     The main customization in ArmVirtPkg/PciHostBridgeDxe is that it
>>     emulates IO port accesses with an MMIO range, whose base address is
>>     parsed from the DTB.
>>
>>     The core PciHostBridgeDxe driver delegates the IO port access
>>     implementation to EFI_CPU_IO2_PROTOCOL. @ardbiesheuvel recently
>>     implemented ArmPkg/Drivers/ArmPciCpuIo2Dxe (in commit 3dece14)
>>     which provides this protocol, backed by the same kind of
>>     translation as described above. The base address comes from
>>     gArmTokenSpaceGuid.PcdPciIoTranslation.
>>
>>     Therefore:
>>
>>     (1) We should extend our ArmVirtPkg/Library/FdtPciPcdProducerLib
>>         plugin library to locate the IO translation offset in the DTB,
>>         and store it in the above PCD.
>>
>>     (2) We should include ArmPciCpuIo2Dxe in the ArmVirtQemu builds,
>>         plugging the above library into it.
>>
>>     (3) We should implement a PciHostBridgeLib instance, and plug it
>>         into the core PciHostBridgeDxe driver.
>>
>>         We should create one PCI_ROOT_BRIDGE object, populating it with
>>         the FTD Client code we are currently using in
>>         ArmVirtPkg/PciHostBridgeDxe.
>>
>>     (4) Extra benefit: the core PciHostBridgeDxe driver supports 64-bit
>>         MMIO, we just have to parse those values from the DTB as well.
>>
>> Steps (2) through (4) are implemented by this series, but I don't think
>> the above PcdSet64() call satisfies (1). What guarantees that by the
>> time ArmPciCpuIo2Dxe looks at it, PcdPciIoTranslation will be set?
>>
>> ... Especially because PciHostBridgeDxe.inf has a DEPEX on
>> gEfiCpuIo2ProtocolGuid, so the PcdSet64() above is bound to run *after*
>> ArmPciCpuIo2Dxe is dispatched?
>>
>> Hmmmm... Are you making the argument that the PCD is set *between*
>> ArmPciCpuIo2Dxe's dispatch and actual use of the PCD? That is:
>>
>> - ArmPciCpuIo2Dxe is dispatched
>> - PciHostBridgeDxe is dispatched
>> - we set the PCD in this lib (as part of PciHostBridgeDxe's startup)
>> - (much later) something makes a PCI IO or MEM access that causes
>>   PciHostBridgeDxe to talk to ArmPciCpuIo2Dxe
>> - ArmPciCpuIo2Dxe consumes the PCD
>>
>> I think this is a valid argument to make -- I've even checked:
>> ArmPciCpuIo2Dxe indeed performs a PcdGet64() on every CpuIoServiceRead()
>> / CpuIoServiceWrite(), and none in its entry point --, but it has to be
>> explained in detail.
>>
>> This borders on a hack -- because ArmPciCpuIo2Dxe is not actually ready
>> for use when its entry point exits with success --, but I think we can
>> allow it, both ArmPciCpuIo2Dxe and this lib being platform specific, as
>> long as we document it profusely.
>>
>> So please describe this quirk in the commit message, and add a large
>> comment right above the PcdSet64() call.
>>
>> (Also, did you test this series with std VGA, on TCG? That will actually
>> put the IO translation to use.)
>>
>> The alternative to the commit msg addition / code comment would be my
>> suggestion in (1), that is, to extend FdtPciPcdProducerLib with setting
>> PcdPciIoTranslation, and to link it into ArmPciCpuIo2Dxe via NULL
>> library resolution. I guess you don't like that, which is fine, but then
>> please add the docs. Thanks.
>>
> 
> Actually, I prefer your original suggestion, to add it to
> FdtPciPcdProducerLib. That way, we no longer have to set any PCDs in
> this code, which is much cleaner imo

Sounds good, thanks!

In this case, the IoTranslation variable should become local to
ProcessPciHost() -- and ProcessPciHost() only -- in this patch, plus I
think we should also add

  ASSERT (PcdGet64 (PcdPciIoTranslation) == IoTranslation);

to ProcessPciHost() here, under the DTB_PCI_HOST_RANGE_IO branch.

Furthermore, the zero-assignment of the now-local IoTranslation variable
should probably be moved out from under the
'-Werror=maybe-uninitialized' comment, because it won't be an output
parameter any longer. What do you think?

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib
  2016-08-31 13:51       ` Laszlo Ersek
@ 2016-08-31 13:54         ` Ard Biesheuvel
  0 siblings, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2016-08-31 13:54 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: edk2-devel@lists.01.org

On 31 August 2016 at 14:51, Laszlo Ersek <lersek@redhat.com> wrote:
> On 08/24/16 17:19, Ard Biesheuvel wrote:
>> On 24 August 2016 at 17:01, Laszlo Ersek <lersek@redhat.com> wrote:
>>> On 08/22/16 02:35, Ard Biesheuvel wrote:
>
>>>> +  PcdSet64 (PcdPciIoTranslation, IoTranslation);
>>>
>>> I agree this is necessary, but it's not in the right place, plus as-is,
>>> it is not sufficient.
>>>
>>> In <https://tianocore.acgmultimedia.com/show_bug.cgi?id=65#c0> I wrote
>>> -- and I'm slightly reformatting it here, because the formatting got
>>> lost in the GitHub -> BZ migration --:
>>>
>>>     The main customization in ArmVirtPkg/PciHostBridgeDxe is that it
>>>     emulates IO port accesses with an MMIO range, whose base address is
>>>     parsed from the DTB.
>>>
>>>     The core PciHostBridgeDxe driver delegates the IO port access
>>>     implementation to EFI_CPU_IO2_PROTOCOL. @ardbiesheuvel recently
>>>     implemented ArmPkg/Drivers/ArmPciCpuIo2Dxe (in commit 3dece14)
>>>     which provides this protocol, backed by the same kind of
>>>     translation as described above. The base address comes from
>>>     gArmTokenSpaceGuid.PcdPciIoTranslation.
>>>
>>>     Therefore:
>>>
>>>     (1) We should extend our ArmVirtPkg/Library/FdtPciPcdProducerLib
>>>         plugin library to locate the IO translation offset in the DTB,
>>>         and store it in the above PCD.
>>>
>>>     (2) We should include ArmPciCpuIo2Dxe in the ArmVirtQemu builds,
>>>         plugging the above library into it.
>>>
>>>     (3) We should implement a PciHostBridgeLib instance, and plug it
>>>         into the core PciHostBridgeDxe driver.
>>>
>>>         We should create one PCI_ROOT_BRIDGE object, populating it with
>>>         the FTD Client code we are currently using in
>>>         ArmVirtPkg/PciHostBridgeDxe.
>>>
>>>     (4) Extra benefit: the core PciHostBridgeDxe driver supports 64-bit
>>>         MMIO, we just have to parse those values from the DTB as well.
>>>
>>> Steps (2) through (4) are implemented by this series, but I don't think
>>> the above PcdSet64() call satisfies (1). What guarantees that by the
>>> time ArmPciCpuIo2Dxe looks at it, PcdPciIoTranslation will be set?
>>>
>>> ... Especially because PciHostBridgeDxe.inf has a DEPEX on
>>> gEfiCpuIo2ProtocolGuid, so the PcdSet64() above is bound to run *after*
>>> ArmPciCpuIo2Dxe is dispatched?
>>>
>>> Hmmmm... Are you making the argument that the PCD is set *between*
>>> ArmPciCpuIo2Dxe's dispatch and actual use of the PCD? That is:
>>>
>>> - ArmPciCpuIo2Dxe is dispatched
>>> - PciHostBridgeDxe is dispatched
>>> - we set the PCD in this lib (as part of PciHostBridgeDxe's startup)
>>> - (much later) something makes a PCI IO or MEM access that causes
>>>   PciHostBridgeDxe to talk to ArmPciCpuIo2Dxe
>>> - ArmPciCpuIo2Dxe consumes the PCD
>>>
>>> I think this is a valid argument to make -- I've even checked:
>>> ArmPciCpuIo2Dxe indeed performs a PcdGet64() on every CpuIoServiceRead()
>>> / CpuIoServiceWrite(), and none in its entry point --, but it has to be
>>> explained in detail.
>>>
>>> This borders on a hack -- because ArmPciCpuIo2Dxe is not actually ready
>>> for use when its entry point exits with success --, but I think we can
>>> allow it, both ArmPciCpuIo2Dxe and this lib being platform specific, as
>>> long as we document it profusely.
>>>
>>> So please describe this quirk in the commit message, and add a large
>>> comment right above the PcdSet64() call.
>>>
>>> (Also, did you test this series with std VGA, on TCG? That will actually
>>> put the IO translation to use.)
>>>
>>> The alternative to the commit msg addition / code comment would be my
>>> suggestion in (1), that is, to extend FdtPciPcdProducerLib with setting
>>> PcdPciIoTranslation, and to link it into ArmPciCpuIo2Dxe via NULL
>>> library resolution. I guess you don't like that, which is fine, but then
>>> please add the docs. Thanks.
>>>
>>
>> Actually, I prefer your original suggestion, to add it to
>> FdtPciPcdProducerLib. That way, we no longer have to set any PCDs in
>> this code, which is much cleaner imo
>
> Sounds good, thanks!
>
> In this case, the IoTranslation variable should become local to
> ProcessPciHost() -- and ProcessPciHost() only -- in this patch, plus I
> think we should also add
>
>   ASSERT (PcdGet64 (PcdPciIoTranslation) == IoTranslation);
>
> to ProcessPciHost() here, under the DTB_PCI_HOST_RANGE_IO branch.
>
> Furthermore, the zero-assignment of the now-local IoTranslation variable
> should probably be moved out from under the
> '-Werror=maybe-uninitialized' comment, because it won't be an output
> parameter any longer. What do you think?
>

Yes, that was my idea as well. The FdtPciPcdProducerLib will need some
work, but it is ultimately a much cleaner approach.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support
  2016-08-22  6:35 ` [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support Ard Biesheuvel
@ 2016-08-31 14:06   ` Laszlo Ersek
  0 siblings, 0 replies; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-31 14:06 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel

On 08/22/16 08:35, Ard Biesheuvel wrote:
> If the pci-host-ecam-generic DT node describes a 64-bit MMIO region,
> account for it in the PCI_ROOT_BRIDGE description that we return to
> the generic PciHostBridgeDxe implementation, which will be able to
> allocate BARs from it without any further changes.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c | 59 +++++++++++++-------
>  1 file changed, 38 insertions(+), 21 deletions(-)

(1) So this patch will have to be rebased to the IoTranslation change
discussed under patch 2/5,

> diff --git a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> index 0aff149e8029..74fda4d23fa3 100644
> --- a/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> +++ b/ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.c
> @@ -87,9 +87,10 @@ ProcessPciHost (
>    OUT  UINT64    *IoBase,
>    OUT  UINT64    *IoSize,
>    OUT  UINT64    *IoTranslation,
> -  OUT  UINT64    *MmioBase,
> -  OUT  UINT64    *MmioSize,
> -  OUT  UINT64    *MmioTranslation,
> +  OUT  UINT64    *Mmio32Base,
> +  OUT  UINT64    *Mmio32Size,
> +  OUT  UINT64    *Mmio64Base,
> +  OUT  UINT64    *Mmio64Size,
>    OUT  UINT32    *BusMin,
>    OUT  UINT32    *BusMax
>    )
> @@ -101,6 +102,7 @@ ProcessPciHost (
>    UINT32                      Len;
>    UINT32                      RecordIdx;
>    EFI_STATUS                  Status;
> +  UINT64                      MmioTranslation;
>  
>    //
>    // The following output arguments are initialized only in
> @@ -109,8 +111,8 @@ ProcessPciHost (
>    //
>    *IoBase = 0;
>    *IoTranslation = 0;
> -  *MmioBase = 0;
> -  *MmioTranslation = 0;
> +  *Mmio32Base = 0;
> +  *Mmio64Base = MAX_UINT64;
>    *BusMin = 0;
>    *BusMax = 0;
>  
> @@ -120,7 +122,8 @@ ProcessPciHost (
>    // above, they are initialized early.
>    //
>    *IoSize = 0;
> -  *MmioSize = 0;
> +  *Mmio32Size = 0;
> +  *Mmio64Size = 0;

(2) and here the leading comment should be updated -- at the moment it
refers to IoSize and MmioSize.

>  
>    Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
>                    (VOID **)&FdtClient);
> @@ -207,26 +210,39 @@ ProcessPciHost (
>        break;
>  
>      case DTB_PCI_HOST_RANGE_MMIO32:
> -      *MmioBase = SwapBytes64 (Record->ChildBase);
> -      *MmioSize = SwapBytes64 (Record->Size);
> -      *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;
> +      *Mmio32Base = SwapBytes64 (Record->ChildBase);
> +      *Mmio32Size = SwapBytes64 (Record->Size);
> +      MmioTranslation = SwapBytes64 (Record->CpuBase) - *Mmio32Base;
>  
> -      if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||
> -          *MmioBase + *MmioSize > SIZE_4GB) {
> +      if (*Mmio32Base > MAX_UINT32 || *Mmio32Size > MAX_UINT32 ||
> +          *Mmio32Base + *Mmio32Size > SIZE_4GB) {
>          DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));
>          return EFI_PROTOCOL_ERROR;
>        }
>  
> -      if (*MmioTranslation != 0) {
> +      if (MmioTranslation != 0) {
>          DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "
> -          "0x%Lx\n", __FUNCTION__, *MmioTranslation));
> +          "0x%Lx\n", __FUNCTION__, MmioTranslation));
> +        return EFI_UNSUPPORTED;
> +      }
> +
> +      break;
> +
> +    case DTB_PCI_HOST_RANGE_MMIO64:
> +      *Mmio64Base = SwapBytes64 (Record->ChildBase);
> +      *Mmio64Size = SwapBytes64 (Record->Size);
> +      MmioTranslation = SwapBytes64 (Record->CpuBase) - *Mmio64Base;
> +
> +      if (MmioTranslation != 0) {
> +        DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO64 translation "
> +          "0x%Lx\n", __FUNCTION__, MmioTranslation));
>          return EFI_UNSUPPORTED;
>        }
>  
>        break;
>      }
>    }
> -  if (*IoSize == 0 || *MmioSize == 0) {
> +  if (*IoSize == 0 || *Mmio32Size == 0) {
>      DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,
>        (*IoSize == 0) ? "IO" : "MMIO32"));
>      return EFI_PROTOCOL_ERROR;
> @@ -239,9 +255,9 @@ ProcessPciHost (
>    ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
>  
>    DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
> -    "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,
> -    ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,
> -    *MmioSize, *MmioTranslation));
> +    "Io[0x%Lx+0x%Lx)@0x%Lx Mem32[0x%Lx+0x%Lx) Mem64[0x%Lx+0x%Lx)\n",
> +    __FUNCTION__, ConfigBase, ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize,
> +    *IoTranslation, *Mmio32Base, *Mmio32Size, *Mmio64Base, *Mmio64Size));
>    return EFI_SUCCESS;
>  }
>  
> @@ -263,7 +279,8 @@ PciHostBridgeGetRootBridges (
>  {
>    PCI_ROOT_BRIDGE     *RootBridge;
>    UINT64              IoBase, IoSize, IoTranslation;
> -  UINT64              Mmio32Base, Mmio32Size, Mmio32Translation;
> +  UINT64              Mmio32Base, Mmio32Size;
> +  UINT64              Mmio64Base, Mmio64Size;
>    UINT32              BusMin, BusMax;
>    EFI_STATUS          Status;
>  
> @@ -275,7 +292,7 @@ PciHostBridgeGetRootBridges (
>    }
>  
>    Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &Mmio32Base,
> -             &Mmio32Size, &Mmio32Translation, &BusMin, &BusMax);
> +             &Mmio32Size, &Mmio64Base, &Mmio64Size, &BusMin, &BusMax);
>    if (EFI_ERROR (Status)) {
>      DEBUG ((EFI_D_INFO,
>        "%a: failed to discover PCI host bridge: %s not present\n",
> @@ -304,8 +321,8 @@ PciHostBridgeGetRootBridges (
>    RootBridge->Io.Limit              = IoBase + IoSize - 1;
>    RootBridge->Mem.Base              = Mmio32Base;
>    RootBridge->Mem.Limit             = Mmio32Base + Mmio32Size - 1;
> -  RootBridge->MemAbove4G.Base       = MAX_UINT64;
> -  RootBridge->MemAbove4G.Limit      = 0;
> +  RootBridge->MemAbove4G.Base       = Mmio64Base;
> +  RootBridge->MemAbove4G.Limit      = Mmio64Base + Mmio64Size - 1;
>  
>    //
>    // No separate ranges for prefetchable and non-prefetchable BARs
> 

With those updates, the patch looks good to me:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe
  2016-08-22  6:35 ` [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe Ard Biesheuvel
@ 2016-08-31 14:11   ` Laszlo Ersek
  0 siblings, 0 replies; 17+ messages in thread
From: Laszlo Ersek @ 2016-08-31 14:11 UTC (permalink / raw)
  To: Ard Biesheuvel; +Cc: edk2-devel

On 08/22/16 08:35, Ard Biesheuvel wrote:
> This code is now no longer used, so remove it.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c      | 1458 -------------
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.h      |  499 -----
>  ArmVirtPkg/PciHostBridgeDxe/PciHostBridgeDxe.inf |   64 -
>  ArmVirtPkg/PciHostBridgeDxe/PciRootBridgeIo.c    | 2144 --------------------
>  4 files changed, 4165 deletions(-)

Reviewed-by: Laszlo Ersek <lersek@redhat.com>



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-08-31 14:11 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-22  6:35 [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Ard Biesheuvel
2016-08-22  6:35 ` [PATCH 1/5] ArmVirtPkg/PciHostBridgeDxe: don't set linux, pci-probe-only DT property Ard Biesheuvel
2016-08-23 21:23   ` Laszlo Ersek
2016-08-24  5:30     ` Ard Biesheuvel
2016-08-22  6:35 ` [PATCH 2/5] ArmVirtPkg: implement FdtPciHostBridgeLib Ard Biesheuvel
2016-08-24 15:01   ` Laszlo Ersek
2016-08-24 15:19     ` Ard Biesheuvel
2016-08-31 13:51       ` Laszlo Ersek
2016-08-31 13:54         ` Ard Biesheuvel
2016-08-22  6:35 ` [PATCH 3/5] ArmVirtPkg/ArmVirtQemu: switch to generic PciHostBridgeDxe Ard Biesheuvel
2016-08-23 18:04   ` Ard Biesheuvel
2016-08-31 12:24     ` Laszlo Ersek
2016-08-22  6:35 ` [PATCH 4/5] ArmVirtPkg/FdtPciHostBridgeLib: add MMIO64 support Ard Biesheuvel
2016-08-31 14:06   ` Laszlo Ersek
2016-08-22  6:35 ` [PATCH 5/5] ArmVirtPkg: remove now unused PciHostBridgeDxe Ard Biesheuvel
2016-08-31 14:11   ` Laszlo Ersek
2016-08-22 11:58 ` [PATCH 0/5] ArmVirtQemu: move to generic PciHostBridgeDxe Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox