[edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module

Zhai, MingXin (Duke) via groups.io posted 32 patches 7 months, 2 weeks ago
Only 28 patches received!
[edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module
Posted by Zhai, MingXin (Duke) via groups.io 7 months, 2 weeks ago
From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial PciHostBridge module. Provides the basic interfaces to abstract
  a PCI Host Bridge Resource Allocation.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Bus/Pci/PciHostBridgeDxe/IoFifo.h         |  170 ++
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 1370 ++++++++++
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.h  |  624 +++++
 .../Pci/PciHostBridgeDxe/PciHostBridge.uni    |  Bin 0 -> 1290 bytes
 .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   54 +
 .../PciHostBridgeDxe/PciHostBridgeExtra.uni   |  Bin 0 -> 826 bytes
 .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    | 2421 +++++++++++++++++
 7 files changed, 4639 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
new file mode 100644
index 0000000000..cd6ed34f22
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
@@ -0,0 +1,170 @@
+/** @file
+  Implementation of IoFifo.h
+  I/O FIFO routines
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef IO_FIFO_H_INCLUDED_
+#define IO_FIFO_H_INCLUDED_
+
+/**
+  Reads an 8-bit I/O port fifo into a block of memory.
+
+  Reads the 8-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 8-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo8 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Reads a 16-bit I/O port fifo into a block of memory.
+
+  Reads the 16-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 16-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo16 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Reads a 32-bit I/O port fifo into a block of memory.
+
+  Reads the 32-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 32-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo32 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into an 8-bit I/O port fifo.
+
+  Writes the 8-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 8-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo8 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into a 16-bit I/O port fifo.
+
+  Writes the 16-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 16-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo16 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into a 32-bit I/O port fifo.
+
+  Writes the 32-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 32-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo32 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644
index 0000000000..6fc9b22b8f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
@@ -0,0 +1,1370 @@
+/** @file
+  Implementation of PciHostBridge.c
+  Provides the basic interfaces to abstract a PCI Host Bridge Resource
+  Allocation
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciHostBridge.h"
+#define TOP_MEM  0xC001001Aul
+
+//
+// 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
+        }
+      }
+    }
+  }
+};
+
+PCI_ROOT_BRIDGE_RESOURCE_APERTURE  mResAperture[1][1] = {
+  {
+    { 0, 0xff, 0xE0000000, 0xffffffff, 0, 0xffff }
+  }
+};
+
+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
+//
+
+/**
+  Entry point of this driver
+
+  @param ImageHandle     Handle of driver image
+  @param SystemTable     Point to EFI_SYSTEM_TABLE
+
+  @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
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Loop1;
+  UINTN                     Loop2;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  EFI_PHYSICAL_ADDRESS      TopOfLowMem;
+
+  mDriverImageHandle         = ImageHandle;
+  TopOfLowMem                = AsmReadMsr64 (TOP_MEM);
+  mResAperture[0][0].MemBase = TopOfLowMem;
+
+  //
+  // 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);
+    }
+  }
+
+  Status = gDS->AddIoSpace (
+                  EfiGcdIoTypeIo,
+                  0x2000,
+                  0xFFFF-0x2000
+                  );
+  ASSERT_EFI_ERROR (Status);
+  TopOfLowMem = AsmReadMsr64 (TOP_MEM);
+  Status      = gDS->AddMemorySpace (
+                       EfiGcdMemoryTypeMemoryMappedIo,
+                       TopOfLowMem,
+                       0xF8000000-TopOfLowMem,
+                       0
+                       );
+
+  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;
+                  }
+
+                  Status = gDS->AllocateIoSpace (
+                                  EfiGcdAllocateAnySearchBottomUp,
+                                  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;
+                  }
+
+                  Status = gDS->AllocateMemorySpace (
+                                  EfiGcdAllocateAnySearchBottomUp,
+                                  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;
+      }
+
+      break;
+
+    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) {
+      EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Desc;
+
+      Desc     = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+      BusStart = (UINTN)Desc->AddrRangeMin;
+      BusLen   = (UINTN)Desc->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) {
+      while ( *Temp == 0x8A) {
+        Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp;
+
+        //
+        // Check Address Length
+        //
+        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;
+        }
+
+        Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+      }
+
+      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) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      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/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
new file mode 100644
index 0000000000..8182697994
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
@@ -0,0 +1,624 @@
+/** @file
+  Implementation of PciHostBridge.h
+  The Header file of the Pci Host Bridge Driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 <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>
+
+//
+// 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      0xFF
+
+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;
+} 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;
+
+  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/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni
new file mode 100644
index 0000000000000000000000000000000000000000..311a1c450d0faa5317ad3b254390f866e813e712
GIT binary patch
literal 1290
zcmdUt-%A2P5Xa{^=zm!BrJ_@d9wH*r3=;Ywo<VO>cWMWE#@#9O&sU$B+|wW<=%qOJ
zc6WAX=JTDMx7WJV#W8mHoSe!~5*f=tHe~~=o^@m*&t{uoPo<CtMj}(zj{lH<S0XGI
z>~hXplCg_r#QmDgxR<QN>&p{%Cy&I*If+;&7I%Q(5NpJFZr1NI7i4qXb`~Win{w-J
zz}mAa+Zh^MN#{QCIXIPej#mb)*X?JA_Z0mvc54KCL98vT+symYU>vY&5@!xgYV<Ld
zE7O)4Wt-@8+pDr&PCIt9W}ain-Aa7bp5dWNG9!y2JBGU_Cne!JvZy3$$RUvehH~z~
z=`$BZ)|{#>L!JJYulgIRW!*w5-<CV_UoMoVrYJyrOn&X8#QIHD9zoNR5RU-b0J1Se
zvxP_3=stXW20uIN-MZC9Z91y>6-3p(8WA~^KDE2&O>W3=3(+~dre)NVCi(i@TlZCs
zMq|w&(Y|)3ARt!Ax`OxL?dnQdo1fLCO?5&l(&MGNDC<zQ>o05bzw1)t-F(Nq10q7q
A8~^|S

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000000..05eec84d7e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,54 @@
+## @file
+# Platform Boot Manager Lib Module
+#  The basic interfaces implementation to a single segment PCI Host Bridge
+#  driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciHostBridge
+  MODULE_UNI_FILE                = PciHostBridge.uni
+  FILE_GUID                      = ACAB2797-6602-4B27-925F-B43483C630CE
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializePciHostBridge
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DxeServicesTableLib
+  UefiLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  DebugLib
+  DevicePathLib
+  IoLib
+  PciLib
+
+[Sources]
+  PciHostBridge.c
+  PciRootBridgeIo.c
+  PciHostBridge.h
+  IoFifo.h
+
+[Protocols]
+  gEfiPciHostBridgeResourceAllocationProtocolGuid       ## PRODUCES
+  gEfiPciRootBridgeIoProtocolGuid                       ## PRODUCES
+  gEfiMetronomeArchProtocolGuid                         ## CONSUMES
+  gEfiDevicePathProtocolGuid                            ## PRODUCES
+
+[depex]
+  gEfiMetronomeArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PciHostBridgeExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni
new file mode 100644
index 0000000000000000000000000000000000000000..819a077f54064dbbd5e260aaecdb4615149eee47
GIT binary patch
literal 826
zcmbu7+e-pb5XQgfp#R}uFBPd}Jw-(6E+k}$Yv7y6dTGHM>xJr%uYPmZRfBqpWzOuG
zIrGgom#@#V%5umlpVOU&N;K9$hdRJ&zPcuwd)oy2R7>@cL^J*!=a93h7|R2<1-`0M
zZheh-AL<QDN=!*BB9cAizoVQU!HS6*6Y&8~pDd9_N<bNr$KjoNd(CrMZrJ6_bM0jQ
zx!ygikzPS@I>vf}uIL=O;_n`;wa1J%`5NSoiJIXJu&w=lK<+avb+X4)Wsze(w})@+
zQX&>eN}Ta8>4wg<bi3Dq-<ic*W*55L=Cb-Mi^ZhWW9M!X|KYLgRKz3$byTGPR=dsH
zYA8}|-`{NVwj);8HEgO(CBR=nYVhkZ<t(D<*<~A(XUMhl`&RayFq_E{akeShd~Moo
zy48hIOV6Akx($yIPgf0WfnMMla(iM14gNA5V_`e8LfZ~H&%DU%$iFCnRs+dxH`eOd
T?W|3^1Da{G+Wb-#ez5%pMNWT>

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000000..b70e4745cc
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -0,0 +1,2421 @@
+/** @file
+  Implementation of PciRootBridgeIo.c
+  PCI Root Bridge Io Protocol implementation
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciHostBridge.h"
+#include "IoFifo.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 and io addresses are
+  // direct mapped to pci addresses, so no need translate, set bases to 0.
+  //
+  PrivateData->MemBase = ResAperture->MemBase;
+  PrivateData->IoBase  = ResAperture->IoBase;
+
+  //
+  // 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;
+  UINT64                                       MaxCount;
+  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
+  //
+  if ((Address & (UINT64)(mInStride[Width] - 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.
+  //
+  // The following form of the range check is equivalent but assumes that
+  // Limit is of the form (2^n - 1).
+  //
+  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 (Address < Base) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Count == 0) {
+    if (Address > Limit) {
+      return EFI_UNSUPPORTED;
+    }
+  } else {
+    MaxCount = RShiftU64 (Limit, Width);
+    if (MaxCount < (Count - 1)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+      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;
+  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;
+  }
+
+  InStride       = mInStride[Width];
+  OutStride      = mOutStride[Width];
+  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
+
+ #if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
+  if (InStride == 0) {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoWriteFifo8 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint16:
+          IoWriteFifo16 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint32:
+          IoWriteFifo32 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    } else {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoReadFifo8 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint16:
+          IoReadFifo16 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint32:
+          IoReadFifo32 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    }
+  }
+
+ #endif
+
+  for (Uint8Buffer = Buffer;
+       Count > 0;
+       Address += InStride, Uint8Buffer += OutStride, Count--)
+  {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoWrite8 ((UINTN)Address, *Uint8Buffer);
+          break;
+        case EfiPciWidthUint16:
+          IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+          break;
+        case EfiPciWidthUint32:
+          IoWrite32 ((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 = IoRead8 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint16:
+          *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint32:
+          *((UINT32 *)Uint8Buffer) = IoRead32 ((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) {
+      EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Desc;
+
+      Desc               = &Configuration.SpaceDesp[Index];
+      Desc->AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+      Desc->AddrRangeMax = PrivateData->ResAllocNode[Index].Base +
+                           PrivateData->ResAllocNode[Index].Length - 1;
+      Desc->AddrLen = PrivateData->ResAllocNode[Index].Length;
+    }
+  }
+
+  *Resources = &Configuration;
+  return EFI_SUCCESS;
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114595): https://edk2.groups.io/g/devel/message/114595
Mute This Topic: https://groups.io/mt/103975472/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-