]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Impl PI 1.2 PCI part. Major changes include:
authordavidhuang <davidhuang@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 20 Oct 2009 03:43:40 +0000 (03:43 +0000)
committerdavidhuang <davidhuang@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 20 Oct 2009 03:43:40 +0000 (03:43 +0000)
  a. Update PciBusDxe module, and move it from IntelFrameworkModulePkg to MdeModulePkg
  b. Move IncompatiblePciDeviceSupportDxe module from IntelFrameworkModulePkg to MdeModulePkg
  c. Update the related consumes in inf/dsc/fdf

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9347 6f19259b-4bc3-4df7-8a09-765794883524

33 files changed:
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c [new file with mode: 0644]
MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc

diff --git a/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c b/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.c
new file mode 100644 (file)
index 0000000..310817f
--- /dev/null
@@ -0,0 +1,387 @@
+/** @file\r
+  This module is one template module for Incompatible PCI Device Support protocol.\r
+  It includes one incompatile pci devices list template.\r
+  \r
+  Incompatible PCI Device Support protocol allows the PCI bus driver to support\r
+  resource allocation for some PCI devices that do not comply with the PCI Specification.\r
+\r
+Copyright (c) 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/IncompatiblePciDeviceSupport.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+typedef struct {\r
+  UINT64  VendorId;\r
+  UINT64  DeviceId;\r
+  UINT64  RevisionId;\r
+  UINT64  SubsystemVendorId;\r
+  UINT64  SubsystemDeviceId;\r
+} EFI_PCI_DEVICE_HEADER_INFO;\r
+\r
+typedef struct {\r
+  UINT64  ResType;\r
+  UINT64  GenFlag;\r
+  UINT64  SpecificFlag;\r
+  UINT64  AddrSpaceGranularity;\r
+  UINT64  AddrRangeMin;\r
+  UINT64  AddrRangeMax;\r
+  UINT64  AddrTranslationOffset;\r
+  UINT64  AddrLen;\r
+} EFI_PCI_RESOUCE_DESCRIPTOR;\r
+\r
+#define PCI_DEVICE_ID(VendorId, DeviceId, Revision, SubVendorId, SubDeviceId) \\r
+    VendorId, DeviceId, Revision, SubVendorId, SubDeviceId\r
+\r
+#define PCI_BAR_TYPE_IO   ACPI_ADDRESS_SPACE_TYPE_IO\r
+#define PCI_BAR_TYPE_MEM  ACPI_ADDRESS_SPACE_TYPE_MEM\r
+\r
+#define DEVICE_INF_TAG    0xFFF2\r
+#define DEVICE_RES_TAG    0xFFF1\r
+#define LIST_END_TAG      0x0000\r
+\r
+\r
+/**\r
+  Returns a list of ACPI resource descriptors that detail the special\r
+  resource configuration requirements for an incompatible PCI device.\r
+\r
+  @param  This                  Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
+  @param  VendorId              A unique ID to identify the manufacturer of the PCI device.\r
+  @param  DeviceId              A unique ID to identify the particular PCI device.\r
+  @param  RevisionId            A PCI device-specific revision identifier.\r
+  @param  SubsystemVendorId     Specifies the subsystem vendor ID.\r
+  @param  SubsystemDeviceId     Specifies the subsystem device ID.\r
+  @param  Configuration         A list of ACPI resource descriptors returned that detail\r
+                                the configuration requirement.\r
+\r
+  @retval EFI_SUCCESS           Successfully got ACPI resource for specified PCI device.\r
+  @retval EFI_INVALID_PARAMETER Configuration is NULL. \r
+  @retval EFI_OUT_OF_RESOURCES  No memory available.\r
+  @retval EFI_UNSUPPORTED       The specified PCI device wasn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PCheckDevice (\r
+  IN  EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *This,\r
+  IN  UINTN                                         VendorId,\r
+  IN  UINTN                                         DeviceId,\r
+  IN  UINTN                                         RevisionId,\r
+  IN  UINTN                                         SubsystemVendorId,\r
+  IN  UINTN                                         SubsystemDeviceId,\r
+  OUT VOID                                          **Configuration\r
+  );\r
+\r
+//\r
+// Handle onto which the Incompatible PCI Device List is installed\r
+//\r
+EFI_HANDLE                                    mIncompatiblePciDeviceSupportHandle = NULL;\r
+\r
+//\r
+// The Incompatible PCI Device Support Protocol instance produced by this driver\r
+//\r
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  mIncompatiblePciDeviceSupport = {\r
+  PCheckDevice\r
+};\r
+\r
+//\r
+// The incompatible PCI devices list template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mIncompatiblePciDeviceList[] = {\r
+  //\r
+  // DEVICE_INF_TAG,\r
+  // PCI_DEVICE_ID (VendorID, DeviceID, Revision, SubVendorId, SubDeviceId),\r
+  // DEVICE_RES_TAG,\r
+  // ResType,  GFlag , SFlag,   Granularity,  RangeMin,\r
+  // RangeMax, Offset, AddrLen\r
+  //\r
+  //\r
+  // Device Adaptec 9004\r
+  //\r
+  DEVICE_INF_TAG,\r
+  PCI_DEVICE_ID(0x9004, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+  DEVICE_RES_TAG,\r
+  PCI_BAR_TYPE_IO,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_BAR_EVEN_ALIGN,\r
+  PCI_BAR_ALL,\r
+  PCI_BAR_NOCHANGE,\r
+  //\r
+  // Device Adaptec 9005\r
+  //\r
+  DEVICE_INF_TAG,\r
+  PCI_DEVICE_ID(0x9005, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+  DEVICE_RES_TAG,\r
+  PCI_BAR_TYPE_IO,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_BAR_EVEN_ALIGN,\r
+  PCI_BAR_ALL,\r
+  PCI_BAR_NOCHANGE,\r
+  //\r
+  // Device QLogic  1007\r
+  //\r
+  DEVICE_INF_TAG,\r
+  PCI_DEVICE_ID(0x1077, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+  DEVICE_RES_TAG,\r
+  PCI_BAR_TYPE_IO,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_BAR_EVEN_ALIGN,\r
+  PCI_BAR_ALL,\r
+  PCI_BAR_NOCHANGE,\r
+  //\r
+  // Device Agilent 103C\r
+  //\r
+  DEVICE_INF_TAG,\r
+  PCI_DEVICE_ID(0x103C, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+  DEVICE_RES_TAG,\r
+  PCI_BAR_TYPE_IO,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_BAR_EVEN_ALIGN,\r
+  PCI_BAR_ALL,\r
+  PCI_BAR_NOCHANGE,\r
+  //\r
+  // Device Agilent 15BC\r
+  //\r
+  DEVICE_INF_TAG,\r
+  PCI_DEVICE_ID(0x15BC, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE, DEVICE_ID_NOCARE),\r
+  DEVICE_RES_TAG,\r
+  PCI_BAR_TYPE_IO,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_ACPI_UNUSED,\r
+  PCI_BAR_EVEN_ALIGN,\r
+  PCI_BAR_ALL,\r
+  PCI_BAR_NOCHANGE,\r
+  //\r
+  // The end of the list\r
+  //\r
+  LIST_END_TAG\r
+};\r
+\r
+\r
+/**\r
+  Entry point of the incompatible pci device support code. Setup an incompatible device list template\r
+  and install EFI Incompatible PCI Device Support protocol.\r
+\r
+  @param ImageHandle             A handle for the image that is initializing this driver.\r
+  @param SystemTable             A pointer to the EFI system table.\r
+\r
+  @retval EFI_SUCCESS            Installed EFI Incompatible PCI Device Support Protocol successfully.\r
+  @retval others                 Failed to install protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IncompatiblePciDeviceSupportEntryPoint (\r
+  IN EFI_HANDLE                   ImageHandle,\r
+  IN EFI_SYSTEM_TABLE             *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+\r
+  //\r
+  // Install EFI Incompatible PCI Device Support Protocol on a new handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mIncompatiblePciDeviceSupportHandle,\r
+                  &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mIncompatiblePciDeviceSupport\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Returns a list of ACPI resource descriptors that detail the special\r
+  resource configuration requirements for an incompatible PCI device.\r
+\r
+  @param  This                  Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance.\r
+  @param  VendorId              A unique ID to identify the manufacturer of the PCI device.\r
+  @param  DeviceId              A unique ID to identify the particular PCI device.\r
+  @param  RevisionId            A PCI device-specific revision identifier.\r
+  @param  SubsystemVendorId     Specifies the subsystem vendor ID.\r
+  @param  SubsystemDeviceId     Specifies the subsystem device ID.\r
+  @param  Configuration         A list of ACPI resource descriptors returned that detail\r
+                                the configuration requirement.\r
+\r
+  @retval EFI_SUCCESS           Successfully got ACPI resource for specified PCI device.\r
+  @retval EFI_INVALID_PARAMETER Configuration is NULL. \r
+  @retval EFI_OUT_OF_RESOURCES  No memory available.\r
+  @retval EFI_UNSUPPORTED       The specified PCI device wasn't supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PCheckDevice (\r
+  IN  EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *This,\r
+  IN  UINTN                                         VendorId,\r
+  IN  UINTN                                         DeviceId,\r
+  IN  UINTN                                         RevisionId,\r
+  IN  UINTN                                         SubsystemVendorId,\r
+  IN  UINTN                                         SubsystemDeviceId,\r
+  OUT VOID                                          **Configuration\r
+  )\r
+{\r
+  UINT64                            Tag;\r
+  UINT64                            *ListPtr;\r
+  UINT64                            *TempListPtr;\r
+  EFI_PCI_DEVICE_HEADER_INFO        *Header;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AcpiPtr;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *OldAcpiPtr;\r
+  EFI_PCI_RESOUCE_DESCRIPTOR        *Dsc;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
+  UINTN                             Index;\r
+\r
+  //\r
+  // Validate the parameters\r
+  //\r
+  if (Configuration == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Initialize the return value to NULL\r
+  //\r
+  * (VOID **) Configuration = NULL;\r
+\r
+  ListPtr                   = mIncompatiblePciDeviceList;\r
+  while (*ListPtr != LIST_END_TAG) {\r
+\r
+    Tag = *ListPtr;\r
+\r
+    switch (Tag) {\r
+    case DEVICE_INF_TAG:\r
+      Header  = (EFI_PCI_DEVICE_HEADER_INFO *) (ListPtr + 1);\r
+      ListPtr = ListPtr + 1 + sizeof (EFI_PCI_DEVICE_HEADER_INFO) / sizeof (UINT64);\r
+      //\r
+      // See if the Header matches the parameters passed in\r
+      //\r
+      if (Header->VendorId != DEVICE_ID_NOCARE) {\r
+        if (Header->VendorId != VendorId) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Header->DeviceId != DEVICE_ID_NOCARE) {\r
+        if (DeviceId != Header->DeviceId) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Header->RevisionId != DEVICE_ID_NOCARE) {\r
+        if (RevisionId != Header->RevisionId) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Header->SubsystemVendorId != DEVICE_ID_NOCARE) {\r
+        if (SubsystemVendorId != Header->SubsystemVendorId) {\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Header->SubsystemDeviceId != DEVICE_ID_NOCARE) {\r
+        if (SubsystemDeviceId != Header->SubsystemDeviceId) {\r
+          continue;\r
+        }\r
+      }\r
+      //\r
+      // Matched an item, so construct the ACPI descriptor for the resource.\r
+      //\r
+      //\r
+      // Count the resource items so that to allocate space\r
+      //\r
+      for (Index = 0, TempListPtr = ListPtr; *TempListPtr == DEVICE_RES_TAG; Index++) {\r
+        TempListPtr = TempListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+      }\r
+      //\r
+      // If there is at least one type of resource request,\r
+      // allocate an acpi resource node\r
+      //\r
+      if (Index == 0) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+      AcpiPtr = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Index + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+      if (AcpiPtr == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      OldAcpiPtr = AcpiPtr;\r
+      //\r
+      // Fill the EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR structure\r
+      // according to the EFI_PCI_RESOUCE_DESCRIPTOR structure\r
+      //\r
+      for (; *ListPtr == DEVICE_RES_TAG;) {\r
+\r
+        Dsc = (EFI_PCI_RESOUCE_DESCRIPTOR *) (ListPtr + 1);\r
+\r
+        AcpiPtr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+        AcpiPtr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+        AcpiPtr->ResType = (UINT8) Dsc->ResType;\r
+        AcpiPtr->GenFlag = (UINT8) Dsc->GenFlag;\r
+        AcpiPtr->SpecificFlag = (UINT8) Dsc->SpecificFlag;\r
+        AcpiPtr->AddrSpaceGranularity = Dsc->AddrSpaceGranularity;;\r
+        AcpiPtr->AddrRangeMin = Dsc->AddrRangeMin;\r
+        AcpiPtr->AddrRangeMax = Dsc->AddrRangeMax;\r
+        AcpiPtr->AddrTranslationOffset = Dsc->AddrTranslationOffset;\r
+        AcpiPtr->AddrLen = Dsc->AddrLen;\r
+\r
+        ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+        AcpiPtr++;\r
+      }\r
+      //\r
+      // Put the checksum\r
+      //\r
+      PtrEnd                    = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AcpiPtr);\r
+      PtrEnd->Desc              = ACPI_END_TAG_DESCRIPTOR;\r
+      PtrEnd->Checksum          = 0;\r
+\r
+      *(VOID **) Configuration  = OldAcpiPtr;\r
+\r
+      return EFI_SUCCESS;\r
+\r
+    case DEVICE_RES_TAG:\r
+      //\r
+      // Adjust the pointer to the next PCI resource descriptor item\r
+      //\r
+      ListPtr = ListPtr + 1 + ((sizeof (EFI_PCI_RESOUCE_DESCRIPTOR)) / sizeof (UINT64));\r
+      break;\r
+\r
+    default:\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf b/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
new file mode 100644 (file)
index 0000000..29bf4dc
--- /dev/null
@@ -0,0 +1,49 @@
+#/** @file\r
+#  PCI Incompatible device support module template.\r
+#\r
+#  Installs EFI PCI Incompatible Device Support protocol and includes one incompatile \r
+#  pci devices list template.\r
+#\r
+#  Copyright (c) 2009, Intel Corporation.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = IncompatiblePciDeviceSupport\r
+  FILE_GUID                      = AD70855E-0CC5-4abf-8979-BE762A949EA3\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = IncompatiblePciDeviceSupportEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  IncompatiblePciDeviceSupport.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  DebugLib\r
+\r
+[Protocols]\r
+  gEfiIncompatiblePciDeviceSupportProtocolGuid    ## PRODUCEDS\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c b/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..47eba5f
--- /dev/null
@@ -0,0 +1,176 @@
+/** @file\r
+  EFI Component Name functions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gPciBusComponentName = {\r
+  PciBusComponentNameGetDriverName,\r
+  PciBusComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {\r
+  { "eng;en", (CHAR16 *) L"PCI Bus Driver" },\r
+  { NULL , NULL }\r
+};\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mPciBusDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gPciBusComponentName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h b/MdeModulePkg/Bus/Pci/PciBusDxe/ComponentName.h
new file mode 100644 (file)
index 0000000..ee30e86
--- /dev/null
@@ -0,0 +1,152 @@
+/** @file\r
+  EFI Component Name functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H_\r
+#define _EFI_PCI_BUS_COMPONENT_NAME_H_\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL   gPciBusComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL  gPciBusComponentName2;\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  DriverName[out]       A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+\r
+  @param  ControllerHandle[in]  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+\r
+  @param  ChildHandle[in]       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+\r
+  @param  Language[in]          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+\r
+  @param  ControllerName[out]   A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
new file mode 100644 (file)
index 0000000..71bb539
--- /dev/null
@@ -0,0 +1,382 @@
+/** @file\r
+  Driver Binding functions for PCI Bus module.\r
+\r
+  Single PCI bus driver instance will manager all PCI Root Bridges in one EFI based firmware,\r
+  since all PCI Root Bridges' resources need to be managed together.\r
+  Supported() function will try to get PCI Root Bridge IO Protocol.\r
+  Start() function will get PCI Host Bridge Resource Allocation Protocol to manage all\r
+  PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each\r
+  PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// PCI Bus Driver Global Variables\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {\r
+  PciBusDriverBindingSupported,\r
+  PciBusDriverBindingStart,\r
+  PciBusDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+EFI_HANDLE                                    gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];\r
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL  *gEfiIncompatiblePciDeviceSupport = NULL;\r
+UINTN                                         gPciHostBridgeNumber = 0;\r
+BOOLEAN                                       gFullEnumeration     = TRUE;\r
+UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;\r
+UINT64                                        gAllZero             = 0;\r
+\r
+EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;\r
+EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {\r
+  PciHotPlugRequestNotify\r
+};\r
+\r
+/**\r
+  The Entry Point for PCI Bus module. The user code starts with this function.\r
+\r
+  Installs driver module protocols and. Creates virtual device handles for ConIn,\r
+  ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,\r
+  Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.\r
+  Installs Graphics Output protocol and/or UGA Draw protocol if needed.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurred when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  Handle;\r
+\r
+  //\r
+  // Initializes PCI devices pool\r
+  //\r
+  InitializePciDevicePool ();\r
+\r
+  //\r
+  // Install driver model protocol(s).\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gPciBusDriverBinding,\r
+             ImageHandle,\r
+             &gPciBusComponentName,\r
+             &gPciBusComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    //\r
+    // If Hot Plug is supported, install EFI PCI Hot Plug Request protocol.\r
+    //\r
+    Handle = NULL;\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &Handle,\r
+                    &gEfiPciHotPlugRequestProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    &mPciHotPlugRequest\r
+                    );\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+  than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.\r
+\r
+  @param  This                Protocol instance pointer.\r
+  @param  Controller          Handle of device to test.\r
+  @param  RemainingDevicePath Optional parameter use to pick a specific child.\r
+                              device to start.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device.\r
+  @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+  @retval other               This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  EFI_DEV_PATH_PTR                Node;\r
+\r
+  //\r
+  // Check RemainingDevicePath validation\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, go on checking other conditions\r
+    //\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node,\r
+      // check its validation\r
+      //\r
+      Node.DevPath = RemainingDevicePath;\r
+      if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
+          Node.DevPath->SubType != HW_PCI_DP         ||\r
+          DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check if Pci Root Bridge IO protocol is installed by platform\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Close the I/O Abstraction(s) used to perform the supported test\r
+  //\r
+  gBS->CloseProtocol (\r
+        Controller,\r
+        &gEfiPciRootBridgeIoProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        Controller\r
+        );\r
+\r
+  //\r
+  // Open the EFI Device Path protocol needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Close protocol, don't use device path protocol in the Support() function\r
+  //\r
+  gBS->CloseProtocol (\r
+        Controller,\r
+        &gEfiDevicePathProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        Controller\r
+        );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Start this driver on ControllerHandle and enumerate Pci bus and start\r
+  all device under PCI bus.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to bind driver to.\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child.\r
+                               device to start.\r
+\r
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle.\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Check RemainingDevicePath validation\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, return EFI_SUCCESS\r
+    //\r
+    if (IsDevicePathEnd (RemainingDevicePath)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+                  );\r
+\r
+  //\r
+  // If PCI Platform protocol is available, get it now.\r
+  // If the platform implements this, it must be installed before BDS phase\r
+  //\r
+  gPciPlatformProtocol = NULL;\r
+  gBS->LocateProtocol (\r
+        &gEfiPciPlatformProtocolGuid,\r
+        NULL,\r
+        (VOID **) &gPciPlatformProtocol\r
+        );\r
+\r
+  //\r
+  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.\r
+  //\r
+  if (gPciPlatformProtocol == NULL) { \r
+    gPciOverrideProtocol = NULL;\r
+    gBS->LocateProtocol (\r
+          &gEfiPciOverrideProtocolGuid,\r
+          NULL,\r
+          (VOID **) &gPciOverrideProtocol\r
+          );\r
+  }  \r
+\r
+  gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));\r
+\r
+  //\r
+  // Enumerate the entire host bridge\r
+  // After enumeration, a database that records all the device information will be created\r
+  //\r
+  //\r
+  Status = PciEnumerator (Controller);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Start all the devices under the entire host bridge.\r
+  //\r
+  StartPciDevices (Controller);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  Controller        Handle of device to stop driver on.\r
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                            children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle.\r
+  @retval other             This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    Controller,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  BOOLEAN     AllChildrenStopped;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close the bus driver\r
+    //\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiDevicePathProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+    gBS->CloseProtocol (\r
+          Controller,\r
+          &gEfiPciRootBridgeIoProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          Controller\r
+          );\r
+\r
+    DestroyRootBridgeByHandle (\r
+      Controller\r
+      );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Stop all the children\r
+  //\r
+\r
+  AllChildrenStopped = TRUE;\r
+\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+\r
+    //\r
+    // De register all the pci device\r
+    //\r
+    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
new file mode 100644 (file)
index 0000000..722f31d
--- /dev/null
@@ -0,0 +1,382 @@
+/** @file\r
+  Header files and data structures needed by PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_BUS_H_\r
+#define _EFI_PCI_BUS_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/LoadFile2.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/PciHotPlugRequest.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PciPlatform.h>\r
+#include <Protocol/PciHotPlugInit.h>\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/BusSpecificDriverOverride.h>\r
+#include <Protocol/IncompatiblePciDeviceSupport.h>\r
+#include <Protocol/PciOverride.h>\r
+#include <Protocol/PciEnumerationComplete.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeCoffLib.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+typedef struct _PCI_IO_DEVICE              PCI_IO_DEVICE;\r
+typedef struct _PCI_BAR                    PCI_BAR;\r
+\r
+#define EFI_PCI_RID(Bus, Device, Function)  (((UINT32)Bus << 8) + ((UINT32)Device << 3) + (UINT32)Function)\r
+#define EFI_PCI_BUS_OF_RID(RID)             ((UINT32)RID >> 8)\r
+\r
+#define     EFI_PCI_IOV_POLICY_ARI           0x0001\r
+#define     EFI_PCI_IOV_POLICY_SRIOV         0x0002\r
+#define     EFI_PCI_IOV_POLICY_MRIOV         0x0004\r
+\r
+typedef enum {\r
+  PciBarTypeUnknown = 0,\r
+  PciBarTypeIo16,\r
+  PciBarTypeIo32,\r
+  PciBarTypeMem32,\r
+  PciBarTypePMem32,\r
+  PciBarTypeMem64,\r
+  PciBarTypePMem64,\r
+  PciBarTypeIo,\r
+  PciBarTypeMem,\r
+  PciBarTypeMaxType\r
+} PCI_BAR_TYPE;\r
+\r
+#include "ComponentName.h"\r
+#include "PciIo.h"\r
+#include "PciCommand.h"\r
+#include "PciDeviceSupport.h"\r
+#include "PciEnumerator.h"\r
+#include "PciEnumeratorSupport.h"\r
+#include "PciDriverOverride.h"\r
+#include "PciRomTable.h"\r
+#include "PciOptionRomSupport.h"\r
+#include "PciPowerManagement.h"\r
+#include "PciHotPlugSupport.h"\r
+#include "PciLib.h"\r
+\r
+#define VGABASE1  0x3B0\r
+#define VGALIMIT1 0x3BB\r
+\r
+#define VGABASE2  0x3C0\r
+#define VGALIMIT2 0x3DF\r
+\r
+#define ISABASE   0x100\r
+#define ISALIMIT  0x3FF\r
+\r
+//\r
+// PCI BAR parameters\r
+//\r
+struct _PCI_BAR {\r
+  UINT64        BaseAddress;\r
+  UINT64        Length;\r
+  UINT64        Alignment;\r
+  PCI_BAR_TYPE  BarType;\r
+  BOOLEAN       Prefetchable;\r
+  UINT8         MemType;\r
+  UINT8         Offset;\r
+};\r
+\r
+//\r
+// defined in PCI Card Specification, 8.0\r
+//\r
+#define PCI_CARD_MEMORY_BASE_0                0x1C\r
+#define PCI_CARD_MEMORY_LIMIT_0               0x20\r
+#define PCI_CARD_MEMORY_BASE_1                0x24\r
+#define PCI_CARD_MEMORY_LIMIT_1               0x28\r
+#define PCI_CARD_IO_BASE_0_LOWER              0x2C\r
+#define PCI_CARD_IO_BASE_0_UPPER              0x2E\r
+#define PCI_CARD_IO_LIMIT_0_LOWER             0x30\r
+#define PCI_CARD_IO_LIMIT_0_UPPER             0x32\r
+#define PCI_CARD_IO_BASE_1_LOWER              0x34\r
+#define PCI_CARD_IO_BASE_1_UPPER              0x36\r
+#define PCI_CARD_IO_LIMIT_1_LOWER             0x38\r
+#define PCI_CARD_IO_LIMIT_1_UPPER             0x3A\r
+#define PCI_CARD_BRIDGE_CONTROL               0x3E\r
+\r
+#define PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE BIT8\r
+#define PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE BIT9\r
+\r
+#define PPB_BAR_0                             0\r
+#define PPB_BAR_1                             1\r
+#define PPB_IO_RANGE                          2\r
+#define PPB_MEM32_RANGE                       3\r
+#define PPB_PMEM32_RANGE                      4\r
+#define PPB_PMEM64_RANGE                      5\r
+#define PPB_MEM64_RANGE                       0xFF\r
+\r
+#define P2C_BAR_0                             0\r
+#define P2C_MEM_1                             1\r
+#define P2C_MEM_2                             2\r
+#define P2C_IO_1                              3\r
+#define P2C_IO_2                              4\r
+\r
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED      0x0001\r
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED    0x0002\r
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED    0x0004\r
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED      0x0008\r
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010\r
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED     0x0020\r
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED     0x0040\r
+\r
+#define PCI_MAX_HOST_BRIDGE_NUM               0x0010\r
+\r
+//\r
+// Define option for attribute\r
+//\r
+#define EFI_SET_SUPPORTS    0\r
+#define EFI_SET_ATTRIBUTES  1\r
+\r
+#define PCI_IO_DEVICE_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'o')\r
+\r
+struct _PCI_IO_DEVICE {\r
+  UINT32                                    Signature;\r
+  EFI_HANDLE                                Handle;\r
+  EFI_PCI_IO_PROTOCOL                       PciIo;\r
+  LIST_ENTRY                                Link;\r
+\r
+  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;\r
+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *PciRootBridgeIo;\r
+  EFI_LOAD_FILE2_PROTOCOL                   LoadFile2;\r
+\r
+  //\r
+  // PCI configuration space header type\r
+  //\r
+  PCI_TYPE00                                Pci;\r
+\r
+  //\r
+  // Bus number, Device number, Function number\r
+  //\r
+  UINT8                                     BusNumber;\r
+  UINT8                                     DeviceNumber;\r
+  UINT8                                     FunctionNumber;\r
+\r
+  //\r
+  // BAR for this PCI Device\r
+  //\r
+  PCI_BAR                                   PciBar[PCI_MAX_BAR];\r
+\r
+  //\r
+  // The bridge device this pci device is subject to\r
+  //\r
+  PCI_IO_DEVICE                             *Parent;\r
+\r
+  //\r
+  // A linked list for children Pci Device if it is bridge device\r
+  //\r
+  LIST_ENTRY                                ChildList;\r
+\r
+  //\r
+  // TURE if the PCI bus driver creates the handle for this PCI device\r
+  //\r
+  BOOLEAN                                   Registered;\r
+\r
+  //\r
+  // TRUE if the PCI bus driver successfully allocates the resource required by\r
+  // this PCI device\r
+  //\r
+  BOOLEAN                                   Allocated;\r
+\r
+  //\r
+  // The attribute this PCI device currently set\r
+  //\r
+  UINT64                                    Attributes;\r
+\r
+  //\r
+  // The attributes this PCI device actually supports\r
+  //\r
+  UINT64                                    Supports;\r
+\r
+  //\r
+  // The resource decode the bridge supports\r
+  //\r
+  UINT32                                    Decodes;\r
+\r
+  //\r
+  // The OptionRom Size\r
+  //\r
+  UINT64                                    RomSize;\r
+\r
+  //\r
+  // The OptionRom Size\r
+  //\r
+  UINT64                                    RomBase;\r
+\r
+  //\r
+  // TRUE if all OpROM (in device or in platform specific position) have been processed\r
+  //\r
+  BOOLEAN                                   AllOpRomProcessed;\r
+\r
+  //\r
+  // TRUE if there is any EFI driver in the OptionRom\r
+  //\r
+  BOOLEAN                                   BusOverride;\r
+\r
+  //\r
+  // A list tracking reserved resource on a bridge device\r
+  //\r
+  LIST_ENTRY                                ReservedResourceList;\r
+\r
+  //\r
+  // A list tracking image handle of platform specific overriding driver\r
+  //\r
+  LIST_ENTRY                                OptionRomDriverList;\r
+\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR         *ResourcePaddingDescriptors;\r
+  EFI_HPC_PADDING_ATTRIBUTES                PaddingAttributes;\r
+\r
+  BOOLEAN                                   IsPciExp;\r
+  //\r
+  // For SR-IOV\r
+  //\r
+  UINT8                                     PciExpressCapabilityOffset;\r
+  UINT32                                    AriCapabilityOffset;\r
+  UINT32                                    SrIovCapabilityOffset;\r
+  UINT32                                    MrIovCapabilityOffset;\r
+  PCI_BAR                                   VfPciBar[PCI_MAX_BAR];\r
+  UINT32                                    SystemPageSize;\r
+  UINT16                                    InitialVFs;\r
+  UINT16                                    ReservedBusNum;\r
+};\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \\r
+  CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \\r
+  CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_LINK(a) \\r
+  CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \\r
+  CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE)\r
+\r
+\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport;\r
+extern EFI_DRIVER_BINDING_PROTOCOL                  gPciBusDriverBinding;\r
+extern EFI_COMPONENT_NAME_PROTOCOL                  gPciBusComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL                 gPciBusComponentName2;\r
+extern BOOLEAN                                      gFullEnumeration;\r
+extern UINTN                                        gPciHostBridgeNumber;\r
+extern EFI_HANDLE                                   gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];\r
+extern UINT64                                       gAllOne;\r
+extern UINT64                                       gAllZero;\r
+extern EFI_PCI_PLATFORM_PROTOCOL                    *gPciPlatformProtocol;\r
+extern EFI_PCI_OVERRIDE_PROTOCOL                    *gPciOverrideProtocol;\r
+\r
+\r
+\r
+/**\r
+  Macro that checks whether device is a GFX device.\r
+\r
+  @param  _p      Specified device.\r
+\r
+  @retval TRUE    Device is a a GFX device.\r
+  @retval FALSE   Device is not a a GFX device.\r
+\r
+**/\r
+#define IS_PCI_GFX(_p)     IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+  than contains a gEfiPciRootBridgeIoProtocolGuid protocol can be supported.\r
+\r
+  @param  This                Protocol instance pointer.\r
+  @param  Controller          Handle of device to test.\r
+  @param  RemainingDevicePath Optional parameter use to pick a specific child.\r
+                              device to start.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device.\r
+  @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+  @retval other               This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Start this driver on ControllerHandle and enumerate Pci bus and start\r
+  all device under PCI bus.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  Controller           Handle of device to bind driver to.\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child.\r
+                               device to start.\r
+\r
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle.\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. Support stoping any child handles\r
+  created by this driver.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  Controller        Handle of device to stop driver on.\r
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                            children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle.\r
+  @retval other             This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN  EFI_HANDLE                    Controller,\r
+  IN  UINTN                         NumberOfChildren,\r
+  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
new file mode 100644 (file)
index 0000000..cd7865c
--- /dev/null
@@ -0,0 +1,116 @@
+#/** @file\r
+#  Component description file for PciBus module.\r
+#\r
+#  PCI bus driver. This module will probe all PCI devices and allocate MMIO and IO\r
+#  space for these devices. Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable\r
+#  hot plug supporting.\r
+#\r
+#  Copyright (c) 2006 - 2009, Intel Corporation\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PciBusDxe\r
+  FILE_GUID                      = 93B80004-9FB3-11d4-9A3A-0090273FC14D\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  ENTRY_POINT                    = PciBusEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+#  DRIVER_BINDING                =  gPciBusDriverBinding\r
+#  COMPONENT_NAME                =  gPciBusComponentName\r
+#  COMPONENT_NAME2               =  gPciBusComponentName2\r
+#\r
+\r
+[Sources.common]\r
+  PciLib.c\r
+  PciIo.c\r
+  PciBus.c\r
+  PciDeviceSupport.c\r
+  ComponentName.c\r
+  ComponentName.h\r
+  PciCommand.c\r
+  PciResourceSupport.c\r
+  PciEnumeratorSupport.c\r
+  PciEnumerator.c\r
+  PciOptionRomSupport.c\r
+  PciDriverOverride.c\r
+  PciPowerManagement.c\r
+  PciPowerManagement.h\r
+  PciDriverOverride.h\r
+  PciRomTable.c\r
+  PciHotPlugSupport.c\r
+  PciLib.h\r
+  PciHotPlugSupport.h\r
+  PciRomTable.h\r
+  PciOptionRomSupport.h\r
+  PciEnumeratorSupport.h\r
+  PciEnumerator.h\r
+  PciResourceSupport.h\r
+  PciDeviceSupport.h\r
+  PciCommand.h\r
+  PciIo.h\r
+  PciBus.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  PcdLib\r
+  DevicePathLib\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  ReportStatusCodeLib\r
+  BaseMemoryLib\r
+  UefiLib\r
+  BaseLib\r
+  UefiDriverEntryPoint\r
+  DebugLib\r
+  PeCoffLib\r
+\r
+[Protocols]\r
+  gEfiPciHotPlugRequestProtocolGuid               ## BY_START\r
+  gEfiPciIoProtocolGuid                           ## BY_START\r
+  gEfiDevicePathProtocolGuid                      ## BY_START\r
+  gEfiBusSpecificDriverOverrideProtocolGuid       ## BY_START\r
+  gEfiLoadedImageProtocolGuid                     ## CONSUMED\r
+  gEfiDecompressProtocolGuid                      ## CONSUMED\r
+  gEfiPciHotPlugInitProtocolGuid                  ## CONSUMED\r
+  gEfiPciHostBridgeResourceAllocationProtocolGuid ## CONSUMED\r
+  gEfiPciPlatformProtocolGuid                     ## CONSUMED\r
+  gEfiPciOverrideProtocolGuid                     ## CONSUMED \r
+  gEfiPciEnumerationCompleteProtocolGuid          ## CONSUMED \r
+  gEfiPciRootBridgeIoProtocolGuid                 ## CONSUMED\r
+  gEfiIncompatiblePciDeviceSupportProtocolGuid    ## CONSUMED\r
+  gEfiLoadFile2ProtocolGuid                       ## CONSUMED\r
+\r
+[FeaturePcd.common]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport\r
+\r
+[FixedPcd.common]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize\r
+# [Event]\r
+#   ##\r
+#   # Notify event set by CreateEventForHpc () for PCI Hot Plug controller.\r
+#   #\r
+#   EVT_NOTIFY_SIGNAL                   ## PRODUCES\r
+#\r
+#\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.c
new file mode 100644 (file)
index 0000000..601af30
--- /dev/null
@@ -0,0 +1,248 @@
+/** @file\r
+  PCI command register operations supporting functions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  Operate the PCI register via PciIo function interface.\r
+\r
+  @param PciIoDevice    Pointer to instance of PCI_IO_DEVICE.\r
+  @param Command        Operator command.\r
+  @param Offset         The address within the PCI configuration space for the PCI controller.\r
+  @param Operation      Type of Operation.\r
+  @param PtrCommand     Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.\r
+\r
+  @return Status of PciIo operation.\r
+\r
+**/\r
+EFI_STATUS\r
+PciOperateRegister (\r
+  IN  PCI_IO_DEVICE *PciIoDevice,\r
+  IN  UINT16        Command,\r
+  IN  UINT8         Offset,\r
+  IN  UINT8         Operation,\r
+  OUT UINT16        *PtrCommand\r
+  )\r
+{\r
+  UINT16              OldCommand;\r
+  EFI_STATUS          Status;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  OldCommand  = 0;\r
+  PciIo       = &PciIoDevice->PciIo;\r
+\r
+  if (Operation != EFI_SET_REGISTER) {\r
+    Status = PciIo->Pci.Read (\r
+                          PciIo,\r
+                          EfiPciIoWidthUint16,\r
+                          Offset,\r
+                          1,\r
+                          &OldCommand\r
+                          );\r
+\r
+    if (Operation == EFI_GET_REGISTER) {\r
+      *PtrCommand = OldCommand;\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if (Operation == EFI_ENABLE_REGISTER) {\r
+    OldCommand = (UINT16) (OldCommand | Command);\r
+  } else if (Operation == EFI_DISABLE_REGISTER) {\r
+    OldCommand = (UINT16) (OldCommand & ~(Command));\r
+  } else {\r
+    OldCommand = Command;\r
+  }\r
+\r
+  return PciIo->Pci.Write (\r
+                      PciIo,\r
+                      EfiPciIoWidthUint16,\r
+                      Offset,\r
+                      1,\r
+                      &OldCommand\r
+                      );\r
+}\r
+\r
+/**\r
+  Check the cpability supporting by given device.\r
+\r
+  @param PciIoDevice   Pointer to instance of PCI_IO_DEVICE.\r
+\r
+  @retval TRUE         Cpability supportted.\r
+  @retval FALSE        Cpability not supportted.\r
+\r
+**/\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+  IN PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+{\r
+  if ((PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Locate capability register block per capability ID.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param CapId             The capability ID.\r
+  @param Offset            A pointer to the offset returned.\r
+  @param NextRegBlock      A pointer to the next block returned.\r
+\r
+  @retval EFI_SUCCESS      Successfuly located capability register block.\r
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.\r
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINT8          CapId,\r
+  IN OUT UINT8      *Offset,\r
+  OUT UINT8         *NextRegBlock OPTIONAL\r
+  )\r
+{\r
+  UINT8   CapabilityPtr;\r
+  UINT16  CapabilityEntry;\r
+  UINT8   CapabilityID;\r
+\r
+  //\r
+  // To check the cpability of this device supports\r
+  //\r
+  if (!PciCapabilitySupport (PciIoDevice)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (*Offset != 0) {\r
+    CapabilityPtr = *Offset;\r
+  } else {\r
+\r
+    CapabilityPtr = 0;\r
+    if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+      PciIoDevice->PciIo.Pci.Read (\r
+                               &PciIoDevice->PciIo,\r
+                               EfiPciIoWidthUint8,\r
+                               EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,\r
+                               1,\r
+                               &CapabilityPtr\r
+                               );\r
+    } else {\r
+\r
+      PciIoDevice->PciIo.Pci.Read (\r
+                               &PciIoDevice->PciIo,\r
+                               EfiPciIoWidthUint8,\r
+                               PCI_CAPBILITY_POINTER_OFFSET,\r
+                               1,\r
+                               &CapabilityPtr\r
+                               );\r
+    }\r
+  }\r
+\r
+  while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &PciIoDevice->PciIo,\r
+                             EfiPciIoWidthUint16,\r
+                             CapabilityPtr,\r
+                             1,\r
+                             &CapabilityEntry\r
+                             );\r
+\r
+    CapabilityID = (UINT8) CapabilityEntry;\r
+\r
+    if (CapabilityID == CapId) {\r
+      *Offset = CapabilityPtr;\r
+      if (NextRegBlock != NULL) {\r
+        *NextRegBlock = (UINT8) (CapabilityEntry >> 8);\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CapabilityPtr = (UINT8) (CapabilityEntry >> 8);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Locate PciExpress capability register block per capability ID.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param CapId             The capability ID.\r
+  @param Offset            A pointer to the offset returned.\r
+  @param NextRegBlock      A pointer to the next block returned.\r
+\r
+  @retval EFI_SUCCESS      Successfuly located capability register block.\r
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.\r
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocatePciExpressCapabilityRegBlock (\r
+  IN     PCI_IO_DEVICE *PciIoDevice,\r
+  IN     UINT16        CapId,\r
+  IN OUT UINT32        *Offset,\r
+     OUT UINT32        *NextRegBlock OPTIONAL\r
+  )\r
+{\r
+  UINT32  CapabilityPtr;\r
+  UINT32  CapabilityEntry;\r
+  UINT16  CapabilityID;\r
+\r
+  //\r
+  // To check the capability of this device supports\r
+  //\r
+  if (!PciIoDevice->IsPciExp) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (*Offset != 0) {\r
+    CapabilityPtr = *Offset;\r
+  } else {\r
+    CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;\r
+  }\r
+\r
+  while (CapabilityPtr != 0) {\r
+    //\r
+    // Mask it to DWORD alignment per PCI spec\r
+    //\r
+    CapabilityPtr &= 0xFFC;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &PciIoDevice->PciIo,\r
+                             EfiPciIoWidthUint32,\r
+                             CapabilityPtr,\r
+                             1,\r
+                             &CapabilityEntry\r
+                             );\r
+\r
+    CapabilityID = (UINT16) CapabilityEntry;\r
+\r
+    if (CapabilityID == CapId) {\r
+      *Offset = CapabilityPtr;\r
+      if (NextRegBlock != NULL) {\r
+        *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciCommand.h
new file mode 100644 (file)
index 0000000..942bea9
--- /dev/null
@@ -0,0 +1,238 @@
+/** @file\r
+  PCI command register operations supporting functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_COMMAND_H_\r
+#define _EFI_PCI_COMMAND_H_\r
+\r
+//\r
+// The PCI Command register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_COMMAND_BITS_OWNED                          ( \\r
+                EFI_PCI_COMMAND_IO_SPACE                    | \\r
+                EFI_PCI_COMMAND_MEMORY_SPACE                | \\r
+                EFI_PCI_COMMAND_BUS_MASTER                  | \\r
+                EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \\r
+                EFI_PCI_COMMAND_VGA_PALETTE_SNOOP           | \\r
+                EFI_PCI_COMMAND_FAST_BACK_TO_BACK             \\r
+                )\r
+\r
+//\r
+// The PCI Bridge Control register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED                   ( \\r
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA_16               | \\r
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \\r
+                )\r
+\r
+//\r
+// The PCCard Bridge Control register bits owned by PCI Bus driver.\r
+//\r
+// They should be cleared at the beginning. The other registers\r
+// are owned by chipset, we should not touch them.\r
+//\r
+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED                ( \\r
+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \\r
+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \\r
+                )\r
+\r
+\r
+#define EFI_GET_REGISTER      1\r
+#define EFI_SET_REGISTER      2\r
+#define EFI_ENABLE_REGISTER   3\r
+#define EFI_DISABLE_REGISTER  4\r
+\r
+/**\r
+  Operate the PCI register via PciIo function interface.\r
+\r
+  @param PciIoDevice    Pointer to instance of PCI_IO_DEVICE.\r
+  @param Command        Operator command.\r
+  @param Offset         The address within the PCI configuration space for the PCI controller.\r
+  @param Operation      Type of Operation.\r
+  @param PtrCommand     Return buffer holding old PCI command, if operation is not EFI_SET_REGISTER.\r
+\r
+  @return Status of PciIo operation.\r
+\r
+**/\r
+EFI_STATUS\r
+PciOperateRegister (\r
+  IN  PCI_IO_DEVICE *PciIoDevice,\r
+  IN  UINT16        Command,\r
+  IN  UINT8         Offset,\r
+  IN  UINT8         Operation,\r
+  OUT UINT16        *PtrCommand\r
+  );\r
+\r
+/**\r
+  Check the cpability supporting by given device.\r
+\r
+  @param PciIoDevice   Pointer to instance of PCI_IO_DEVICE.\r
+\r
+  @retval TRUE         Cpability supportted.\r
+  @retval FALSE        Cpability not supportted.\r
+\r
+**/\r
+BOOLEAN\r
+PciCapabilitySupport (\r
+  IN PCI_IO_DEVICE  *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Locate capability register block per capability ID.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param CapId             The capability ID.\r
+  @param Offset            A pointer to the offset returned.\r
+  @param NextRegBlock      A pointer to the next block returned.\r
+\r
+  @retval EFI_SUCCESS      Successfuly located capability register block.\r
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.\r
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateCapabilityRegBlock (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINT8          CapId,\r
+  IN OUT UINT8      *Offset,\r
+  OUT UINT8         *NextRegBlock OPTIONAL\r
+  );\r
+\r
+/**\r
+  Locate PciExpress capability register block per capability ID.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param CapId             The capability ID.\r
+  @param Offset            A pointer to the offset returned.\r
+  @param NextRegBlock      A pointer to the next block returned.\r
+\r
+  @retval EFI_SUCCESS      Successfuly located capability register block.\r
+  @retval EFI_UNSUPPORTED  Pci device does not support capability.\r
+  @retval EFI_NOT_FOUND    Pci device support but can not find register block.\r
+\r
+**/\r
+EFI_STATUS\r
+LocatePciExpressCapabilityRegBlock (\r
+  IN     PCI_IO_DEVICE *PciIoDevice,\r
+  IN     UINT16        CapId,\r
+  IN OUT UINT32        *Offset,\r
+     OUT UINT32        *NextRegBlock OPTIONAL\r
+  );\r
+\r
+/**\r
+  Macro that reads command register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[out]           Pointer to the 16-bit value read from command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_READ_COMMAND_REGISTER(a,b) \\r
+        PciOperateRegister (a, 0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b)\r
+\r
+/**\r
+  Macro that writes command register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The 16-bit value written into command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_SET_COMMAND_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL)\r
+\r
+/**\r
+  Macro that enables command register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The enabled value written into command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_ENABLE_COMMAND_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL)\r
+\r
+/**\r
+  Macro that disalbes command register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The disabled value written into command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_DISABLE_COMMAND_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL)\r
+\r
+/**\r
+  Macro that reads PCI bridge control register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[out]           The 16-bit value read from control register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_READ_BRIDGE_CONTROL_REGISTER(a,b) \\r
+        PciOperateRegister (a, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b)\r
+\r
+/**\r
+  Macro that writes PCI bridge control register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The 16-bit value written into control register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_SET_BRIDGE_CONTROL_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL)\r
+\r
+/**\r
+  Macro that enables PCI bridge control register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The enabled value written into command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_ENABLE_BRIDGE_CONTROL_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL)\r
+\r
+/**\r
+ Macro that disalbes PCI bridge control register.\r
+\r
+  @param a[in]            Pointer to instance of PCI_IO_DEVICE.\r
+  @param b[in]            The disabled value written into command register.\r
+\r
+  @return status of PciIo operation\r
+\r
+**/\r
+#define PCI_DISABLE_BRIDGE_CONTROL_REGISTER(a,b) \\r
+        PciOperateRegister (a, b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL)\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
new file mode 100644 (file)
index 0000000..25387bd
--- /dev/null
@@ -0,0 +1,1185 @@
+/** @file\r
+  Supporting functions implementaion for PCI devices management.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// This device structure is serviced as a header.\r
+// Its next field points to the first root bridge device node.\r
+//\r
+LIST_ENTRY  mPciDevicePool;\r
+\r
+/**\r
+  Initialize the PCI devices pool.\r
+\r
+**/\r
+VOID\r
+InitializePciDevicePool (\r
+  VOID\r
+  )\r
+{\r
+  InitializeListHead (&mPciDevicePool);\r
+}\r
+\r
+/**\r
+  Insert a root bridge into PCI device pool.\r
+\r
+  @param RootBridge     A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+InsertRootBridge (\r
+  IN PCI_IO_DEVICE      *RootBridge\r
+  )\r
+{\r
+  InsertTailList (&mPciDevicePool, &(RootBridge->Link));\r
+}\r
+\r
+/**\r
+  This function is used to insert a PCI device node under\r
+  a bridge.\r
+\r
+  @param Bridge         The PCI bridge.\r
+  @param PciDeviceNode  The PCI device needs inserting.\r
+\r
+**/\r
+VOID\r
+InsertPciDevice (\r
+  IN PCI_IO_DEVICE      *Bridge,\r
+  IN PCI_IO_DEVICE      *PciDeviceNode\r
+  )\r
+{\r
+  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));\r
+  PciDeviceNode->Parent = Bridge;\r
+}\r
+\r
+/**\r
+  Destroy root bridge and remove it from deivce tree.\r
+\r
+  @param RootBridge     The bridge want to be removed.\r
+\r
+**/\r
+VOID\r
+DestroyRootBridge (\r
+  IN PCI_IO_DEVICE      *RootBridge\r
+  )\r
+{\r
+  DestroyPciDeviceTree (RootBridge);\r
+\r
+  FreePciDevice (RootBridge);\r
+}\r
+\r
+/**\r
+  Destroy a pci device node.\r
+\r
+  All direct or indirect allocated resource for this node will be freed.\r
+\r
+  @param PciIoDevice  A pointer to the PCI_IO_DEVICE to be destoried.\r
+\r
+**/\r
+VOID\r
+FreePciDevice (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  ASSERT (PciIoDevice != NULL);\r
+  //\r
+  // Assume all children have been removed underneath this device\r
+  //\r
+  if (PciIoDevice->ResourcePaddingDescriptors != NULL) {\r
+    FreePool (PciIoDevice->ResourcePaddingDescriptors);\r
+  }\r
+\r
+  if (PciIoDevice->DevicePath != NULL) {\r
+    FreePool (PciIoDevice->DevicePath);\r
+  }\r
+\r
+  FreePool (PciIoDevice);\r
+}\r
+\r
+/**\r
+  Destroy all the pci device node under the bridge.\r
+  Bridge itself is not included.\r
+\r
+  @param Bridge      A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+DestroyPciDeviceTree (\r
+  IN PCI_IO_DEVICE      *Bridge\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+    CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+    //\r
+    // Remove this node from the linked list\r
+    //\r
+    RemoveEntryList (CurrentLink);\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      DestroyPciDeviceTree (Temp);\r
+    }\r
+\r
+    FreePciDevice (Temp);\r
+  }\r
+}\r
+\r
+/**\r
+  Destroy all device nodes under the root bridge\r
+  specified by Controller.\r
+\r
+  The root bridge itself is also included.\r
+\r
+  @param  Controller    Root bridge handle.\r
+\r
+  @retval EFI_SUCCESS   Destory all devcie nodes successfully.\r
+  @retval EFI_NOT_FOUND Cannot find any PCI device under specified\r
+                        root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+  IN EFI_HANDLE        Controller\r
+  )\r
+{\r
+\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->Handle == Controller) {\r
+\r
+      RemoveEntryList (CurrentLink);\r
+\r
+      DestroyPciDeviceTree (Temp);\r
+\r
+      FreePciDevice (Temp);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  This function registers the PCI IO device.\r
+\r
+  It creates a handle for this PCI IO device (if the handle does not exist), attaches\r
+  appropriate protocols onto the handle, does necessary initialization, and sets up\r
+  parent/child relationship with its bus controller.\r
+\r
+  @param Controller     An EFI handle for the PCI bus controller.\r
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+  @param Handle         A pointer to hold the returned EFI handle for the PCI IO device.\r
+\r
+  @retval EFI_SUCCESS   The PCI device is successfully registered.\r
+  @retval other         An error occurred when registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+  IN  EFI_HANDLE          Controller,\r
+  IN  PCI_IO_DEVICE       *PciIoDevice,\r
+  OUT EFI_HANDLE          *Handle      OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  VOID                *PlatformOpRomBuffer;\r
+  UINTN               PlatformOpRomSize;\r
+  UINT8               PciExpressCapRegOffset;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT8               Data8;\r
+  BOOLEAN             HasEfiImage;\r
+  PCI_IO_DEVICE       *ParrentPciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL *ParrentPciIo;\r
+  UINT16              Data16;\r
+  UINT32              Data32;\r
+\r
+  //\r
+  // Install the pciio protocol, device path protocol\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &PciIoDevice->Handle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  PciIoDevice->DevicePath,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  &PciIoDevice->PciIo,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Detect if PCI Express Device\r
+  //\r
+  PciExpressCapRegOffset = 0;\r
+  Status = LocateCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+             &PciExpressCapRegOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice->IsPciExp = TRUE;\r
+  }\r
+\r
+  //\r
+  // Force Interrupt line to "Unknown" or "No Connection"\r
+  //\r
+  PciIo = &(PciIoDevice->PciIo);\r
+  Data8 = PCI_INT_LINE_UNKNOWN;\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);\r
+  \r
+  //\r
+  // PCI-IOV programming\r
+  //\r
+  if (((FeaturePcdGet(PcdAriSupport) & EFI_PCI_IOV_POLICY_ARI) != 0) && (PciIoDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport) & EFI_PCI_IOV_POLICY_SRIOV) != 0) &&\r
+      (PciIoDevice->SrIovCapabilityOffset != 0)) {\r
+    //\r
+    // Check its parrent ARI forwarding capability\r
+    //\r
+    ParrentPciIoDevice = PciIoDevice->Parent;\r
+    ParrentPciIo = &(ParrentPciIoDevice->PciIo);\r
+    ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, &Data32);\r
+    if (Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) {\r
+      //\r
+      // ARI forward support in bridge, so enable it.\r
+      //\r
+      ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
+      Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
+      ParrentPciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
+\r
+      //\r
+      // Set ARI Capable Hierarchy for device\r
+      //\r
+      PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+      Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Process OpRom\r
+  //\r
+  if (!PciIoDevice->AllOpRomProcessed) {\r
+\r
+    //\r
+    // Get the OpRom provided by platform\r
+    //\r
+    if (gPciPlatformProtocol != NULL) {\r
+      Status = gPciPlatformProtocol->GetPciRom (\r
+                                       gPciPlatformProtocol,\r
+                                       PciIoDevice->Handle,\r
+                                       &PlatformOpRomBuffer,\r
+                                       &PlatformOpRomSize\r
+                                       );\r
+      if (!EFI_ERROR (Status)) {\r
+        PciIoDevice->RomSize        = PlatformOpRomSize;\r
+        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;\r
+        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;\r
+        //\r
+        // For OpROM read from gPciPlatformProtocol:\r
+        // Add the Rom Image to internal database for later PCI light enumeration\r
+        //\r
+        PciRomAddImageMapping (\r
+          NULL,\r
+          PciIoDevice->PciRootBridgeIo->SegmentNumber,\r
+          PciIoDevice->BusNumber,\r
+          PciIoDevice->DeviceNumber,\r
+          PciIoDevice->FunctionNumber,\r
+          (UINT64) (UINTN) PciIoDevice->PciIo.RomImage,\r
+          PciIoDevice->PciIo.RomSize\r
+          );\r
+      }\r
+    } else if (gPciOverrideProtocol != NULL) {\r
+      Status = gPciOverrideProtocol->GetPciRom (\r
+                                       gPciOverrideProtocol,\r
+                                       PciIoDevice->Handle,\r
+                                       &PlatformOpRomBuffer,\r
+                                       &PlatformOpRomSize\r
+                                       );\r
+      if (!EFI_ERROR (Status)) {\r
+        PciIoDevice->RomSize        = PlatformOpRomSize;\r
+        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;\r
+        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;\r
+        //\r
+        // For OpROM read from gPciOverrideProtocol:\r
+        // Add the Rom Image to internal database for later PCI light enumeration\r
+        //\r
+        PciRomAddImageMapping (\r
+          NULL,\r
+          PciIoDevice->PciRootBridgeIo->SegmentNumber,\r
+          PciIoDevice->BusNumber,\r
+          PciIoDevice->DeviceNumber,\r
+          PciIoDevice->FunctionNumber,\r
+          (UINT64) (UINTN) PciIoDevice->PciIo.RomImage,\r
+          PciIoDevice->PciIo.RomSize\r
+          );\r
+      }   \r
+    }\r
+  }\r
+\r
+  //\r
+  // Determine if there are EFI images in the option rom\r
+  //\r
+  HasEfiImage = ContainEfiImage (PciIoDevice->PciIo.RomImage, PciIoDevice->PciIo.RomSize);\r
+\r
+  if (HasEfiImage) {\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &PciIoDevice->Handle,\r
+                    &gEfiLoadFile2ProtocolGuid,\r
+                    &PciIoDevice->LoadFile2,\r
+                    NULL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->UninstallMultipleProtocolInterfaces (\r
+             &PciIoDevice->Handle,\r
+             &gEfiDevicePathProtocolGuid,\r
+             PciIoDevice->DevicePath,\r
+             &gEfiPciIoProtocolGuid,\r
+             &PciIoDevice->PciIo,\r
+             NULL\r
+             );\r
+      return Status;\r
+    }\r
+  }\r
+\r
+\r
+  if (!PciIoDevice->AllOpRomProcessed) {\r
+\r
+    PciIoDevice->AllOpRomProcessed = TRUE;\r
+\r
+    //\r
+    // Dispatch the EFI OpRom for the PCI device.\r
+    // The OpRom is got from platform in the above code\r
+    // or loaded from device in the previous round of bus enumeration\r
+    //\r
+    if (HasEfiImage) {\r
+      ProcessOpRomImage (PciIoDevice);\r
+    }\r
+  }\r
+\r
+  if (PciIoDevice->BusOverride) {\r
+    //\r
+    // Install Bus Specific Driver Override Protocol\r
+    //\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &PciIoDevice->Handle,\r
+                    &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+                    &PciIoDevice->PciDriverOverride,\r
+                    NULL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->UninstallMultipleProtocolInterfaces (\r
+             &PciIoDevice->Handle,\r
+             &gEfiDevicePathProtocolGuid,\r
+             PciIoDevice->DevicePath,\r
+             &gEfiPciIoProtocolGuid,\r
+             &PciIoDevice->PciIo,\r
+             NULL\r
+             );\r
+      if (HasEfiImage) {\r
+        gBS->UninstallMultipleProtocolInterfaces (\r
+               &PciIoDevice->Handle,\r
+               &gEfiLoadFile2ProtocolGuid,\r
+               &PciIoDevice->LoadFile2,\r
+               NULL\r
+               );\r
+      }\r
+\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &(PciIoDevice->PciRootBridgeIo),\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  PciIoDevice->Handle,\r
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Handle != NULL) {\r
+    *Handle = PciIoDevice->Handle;\r
+  }\r
+\r
+  //\r
+  // Indicate the pci device is registered\r
+  //\r
+  PciIoDevice->Registered = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to remove the whole PCI devices on the specified bridge from\r
+  the root bridge.\r
+\r
+  @param RootBridgeHandle   The root bridge device handle.\r
+  @param Bridge             The bridge device to be removed.\r
+\r
+**/\r
+VOID\r
+RemoveAllPciDeviceOnBridge (\r
+  EFI_HANDLE               RootBridgeHandle,\r
+  PCI_IO_DEVICE            *Bridge\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+    CurrentLink = Bridge->ChildList.ForwardLink;\r
+    Temp        = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Check if the current node has been deregistered before\r
+    // If it is not, then deregister it\r
+    //\r
+    if (Temp->Registered) {\r
+      DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);\r
+    }\r
+\r
+    //\r
+    // Remove this node from the linked list\r
+    //\r
+    RemoveEntryList (CurrentLink);\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
+    }\r
+\r
+    FreePciDevice (Temp);\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to de-register the PCI IO device.\r
+\r
+  That includes un-installing PciIo protocol from the specified PCI\r
+  device handle.\r
+\r
+  @param Controller    An EFI handle for the PCI bus controller.\r
+  @param Handle        PCI device handle.\r
+\r
+  @retval EFI_SUCCESS  The PCI device is successfully de-registered.\r
+  @retval other        An error occurred when de-registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  EFI_HANDLE                     Handle\r
+  )\r
+\r
+{\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  EFI_STATUS                      Status;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  PCI_IO_DEVICE                   *Node;\r
+  LIST_ENTRY                      *CurrentLink;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Handle,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
+\r
+    //\r
+    // If it is already de-registered\r
+    //\r
+    if (!PciIoDevice->Registered) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // If it is PPB, first de-register its children\r
+    //\r
+\r
+    if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+\r
+      CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+\r
+      while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+        Status  = DeRegisterPciDevice (Controller, Node->Handle);\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        CurrentLink = CurrentLink->ForwardLink;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Close the child handle\r
+    //\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiPciRootBridgeIoProtocolGuid,\r
+                    gPciBusDriverBinding.DriverBindingHandle,\r
+                    Handle\r
+                    );\r
+\r
+    //\r
+    // Un-install the Device Path protocol and PCI I/O protocol\r
+    // and Bus Specific Driver Override protocol if needed.\r
+    //\r
+    if (PciIoDevice->BusOverride) {\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      PciIoDevice->DevicePath,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      &PciIoDevice->PciIo,\r
+                      &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+                      &PciIoDevice->PciDriverOverride,\r
+                      NULL\r
+                      );\r
+    } else {\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      PciIoDevice->DevicePath,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      &PciIoDevice->PciIo,\r
+                      NULL\r
+                      );\r
+    }\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Try to uninstall LoadFile2 protocol if exists\r
+      //\r
+      Status = gBS->OpenProtocol (\r
+                      Handle,\r
+                      &gEfiLoadFile2ProtocolGuid,\r
+                      NULL,\r
+                      gPciBusDriverBinding.DriverBindingHandle,\r
+                      Controller,\r
+                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                        Handle,\r
+                        &gEfiLoadFile2ProtocolGuid,\r
+                        &PciIoDevice->LoadFile2,\r
+                        NULL\r
+                        );\r
+      }\r
+      //\r
+      // Restore Status\r
+      //\r
+      Status = EFI_SUCCESS;\r
+    }\r
+\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->OpenProtocol (\r
+            Controller,\r
+            &gEfiPciRootBridgeIoProtocolGuid,\r
+            (VOID **) &PciRootBridgeIo,\r
+            gPciBusDriverBinding.DriverBindingHandle,\r
+            Handle,\r
+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+            );\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // The Device Driver should disable this device after disconnect\r
+    // so the Pci Bus driver will not touch this device any more.\r
+    // Restore the register field to the original value\r
+    //\r
+    PciIoDevice->Registered = FALSE;\r
+    PciIoDevice->Handle     = NULL;\r
+  } else {\r
+\r
+    //\r
+    // Handle may be closed before\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.\r
+\r
+  @param Controller          The root bridge handle.\r
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.\r
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+  @param NumberOfChildren    Children number.\r
+  @param ChildHandleBuffer   A pointer to the child handle buffer.\r
+\r
+  @retval EFI_NOT_READY   Device is not allocated.\r
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.\r
+  @retval EFI_NOT_FOUND   Can not find the specific device.\r
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevicesOnBridge (\r
+  IN EFI_HANDLE                          Controller,\r
+  IN PCI_IO_DEVICE                       *RootBridge,\r
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,\r
+  IN OUT UINT8                           *NumberOfChildren,\r
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer\r
+  )\r
+\r
+{\r
+  PCI_IO_DEVICE             *PciIoDevice;\r
+  EFI_DEV_PATH_PTR          Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;\r
+  EFI_STATUS                Status;\r
+  LIST_ENTRY                *CurrentLink;\r
+  UINT64                    Supports;\r
+\r
+  PciIoDevice = NULL;\r
+  CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+\r
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (RemainingDevicePath != NULL) {\r
+\r
+      Node.DevPath = RemainingDevicePath;\r
+\r
+      if (Node.Pci->Device != PciIoDevice->DeviceNumber ||\r
+          Node.Pci->Function != PciIoDevice->FunctionNumber) {\r
+        CurrentLink = CurrentLink->ForwardLink;\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Check if the device has been assigned with required resource\r
+      //\r
+      if (!PciIoDevice->Allocated) {\r
+        return EFI_NOT_READY;\r
+      }\r
+\r
+      //\r
+      // Check if the current node has been registered before\r
+      // If it is not, register it\r
+      //\r
+      if (!PciIoDevice->Registered) {\r
+        Status = RegisterPciDevice (\r
+                   Controller,\r
+                   PciIoDevice,\r
+                   NULL\r
+                   );\r
+\r
+      }\r
+\r
+      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
+        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
+        (*NumberOfChildren)++;\r
+      }\r
+\r
+      //\r
+      // Get the next device path\r
+      //\r
+      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);\r
+      if (IsDevicePathEnd (CurrentDevicePath)) {\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      //\r
+      // If it is a PPB\r
+      //\r
+      if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+        Status = StartPciDevicesOnBridge (\r
+                   Controller,\r
+                   PciIoDevice,\r
+                   CurrentDevicePath,\r
+                   NumberOfChildren,\r
+                   ChildHandleBuffer\r
+                   );\r
+\r
+        PciIoDevice->PciIo.Attributes (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoAttributeOperationSupported,\r
+                             0,\r
+                             &Supports\r
+                             );\r
+        Supports &= EFI_PCI_DEVICE_ENABLE;\r
+        PciIoDevice->PciIo.Attributes (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoAttributeOperationEnable,\r
+                             Supports,\r
+                             NULL\r
+                             );\r
+\r
+        return Status;\r
+      } else {\r
+\r
+        //\r
+        // Currently, the PCI bus driver only support PCI-PCI bridge\r
+        //\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+    } else {\r
+\r
+      //\r
+      // If remaining device path is NULL,\r
+      // try to enable all the pci devices under this bridge\r
+      //\r
+      if (!PciIoDevice->Registered && PciIoDevice->Allocated) {\r
+        Status = RegisterPciDevice (\r
+                   Controller,\r
+                   PciIoDevice,\r
+                   NULL\r
+                   );\r
+\r
+      }\r
+\r
+      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
+        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
+        (*NumberOfChildren)++;\r
+      }\r
+\r
+      if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+        Status = StartPciDevicesOnBridge (\r
+                   Controller,\r
+                   PciIoDevice,\r
+                   RemainingDevicePath,\r
+                   NumberOfChildren,\r
+                   ChildHandleBuffer\r
+                   );\r
+\r
+        PciIoDevice->PciIo.Attributes (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoAttributeOperationSupported,\r
+                             0,\r
+                             &Supports\r
+                             );\r
+        Supports &= EFI_PCI_DEVICE_ENABLE;\r
+        PciIoDevice->PciIo.Attributes (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoAttributeOperationEnable,\r
+                             Supports,\r
+                             NULL\r
+                             );\r
+\r
+      }\r
+\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+    }\r
+  }\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+/**\r
+  Start to manage all the PCI devices it found previously under\r
+  the entire host bridge.\r
+\r
+  @param Controller          The root bridge handle.\r
+\r
+  @retval EFI_NOT_READY   Device is not allocated.\r
+  @retval EFI_SUCCESS     Success to start Pci device on host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevices (\r
+  IN EFI_HANDLE                         Controller\r
+  )\r
+{\r
+  PCI_IO_DEVICE     *RootBridge;\r
+  EFI_HANDLE        ThisHostBridge;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  RootBridge = GetRootBridgeByHandle (Controller);\r
+  ASSERT (RootBridge != NULL);\r
+  ThisHostBridge = RootBridge->PciRootBridgeIo->ParentHandle;\r
+\r
+  CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    //\r
+    // Locate the right root bridge to start\r
+    //\r
+    if (RootBridge->PciRootBridgeIo->ParentHandle == ThisHostBridge) {\r
+      StartPciDevicesOnBridge (\r
+         RootBridge->Handle,\r
+         RootBridge,\r
+         NULL,\r
+         NULL,\r
+         NULL\r
+         );\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create root bridge device.\r
+\r
+  @param RootBridgeHandle    Specified root bridge hanle.\r
+\r
+  @return The crated root bridge device instance, NULL means no\r
+          root bridge device instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+  IN EFI_HANDLE                   RootBridgeHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  PCI_IO_DEVICE                   *Dev;\r
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  Dev = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
+  if (Dev == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;\r
+  Dev->Handle     = RootBridgeHandle;\r
+  InitializeListHead (&Dev->ChildList);\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  RootBridgeHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  RootBridgeHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Dev);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Record the root bridge parent device path\r
+  //\r
+  Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);\r
+\r
+  //\r
+  // Get the pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  RootBridgeHandle,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  RootBridgeHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    FreePciDevice (Dev);\r
+    return NULL;\r
+  }\r
+\r
+  Dev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+  //\r
+  // Initialize the PCI I/O instance structure\r
+  //\r
+  InitializePciIoInstance (Dev);\r
+  InitializePciDriverOverrideInstance (Dev);\r
+  InitializePciLoadFile2 (Dev);\r
+\r
+  //\r
+  // Initialize reserved resource list and\r
+  // option rom driver list\r
+  //\r
+  InitializeListHead (&Dev->ReservedResourceList);\r
+  InitializeListHead (&Dev->OptionRomDriverList);\r
+\r
+  return Dev;\r
+}\r
+\r
+/**\r
+  Get root bridge device instance by specific root bridge handle.\r
+\r
+  @param RootBridgeHandle    Given root bridge handle.\r
+\r
+  @return The root bridge device instance, NULL means no root bridge\r
+          device instance found.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+  EFI_HANDLE RootBridgeHandle\r
+  )\r
+{\r
+  PCI_IO_DEVICE   *RootBridgeDev;\r
+  LIST_ENTRY      *CurrentLink;\r
+\r
+  CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (RootBridgeDev->Handle == RootBridgeHandle) {\r
+      return RootBridgeDev;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Judege whether Pci device existed.\r
+\r
+  @param Bridge       Parent bridege instance.\r
+  @param PciIoDevice  Device instance.\r
+\r
+  @retval TRUE        Pci device existed.\r
+  @retval FALSE       Pci device did not exist.\r
+\r
+**/\r
+BOOLEAN\r
+PciDeviceExisted (\r
+  IN PCI_IO_DEVICE    *Bridge,\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp == PciIoDevice) {\r
+      return TRUE;\r
+    }\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      if (PciDeviceExisted (Temp, PciIoDevice)) {\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get the active VGA device on the same segment.\r
+\r
+  @param VgaDevice    PCI IO instance for the VGA device.\r
+\r
+  @return The active VGA device on the same segment.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+  IN PCI_IO_DEVICE        *VgaDevice\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = mPciDevicePool.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {\r
+\r
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+      if (Temp != NULL) {\r
+        return Temp;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get the active VGA device on the root bridge.\r
+\r
+  @param RootBridge  PCI IO instance for the root bridge.\r
+\r
+  @return The active VGA device.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+  IN PCI_IO_DEVICE        *RootBridge\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  CurrentLink = RootBridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (IS_PCI_VGA(&Temp->Pci) &&\r
+        (Temp->Attributes &\r
+         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |\r
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |\r
+          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+      return Temp;\r
+    }\r
+\r
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
+\r
+      if (Temp != NULL) {\r
+        return Temp;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Get HPC PCI address according to its device path.\r
+\r
+  @param RootBridge           Root bridege Io instance.\r
+  @param RemainingDevicePath  Given searching device path.\r
+  @param PciAddress           Buffer holding searched result.\r
+\r
+  @retval EFI_SUCCESS         PCI address was stored in PciAddress\r
+  @retval EFI_NOT_FOUND       Can not find the specific device path.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHpcPciAddressFromRootBridge (\r
+  IN  PCI_IO_DEVICE                    *RootBridge,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL         *RemainingDevicePath,\r
+  OUT UINT64                           *PciAddress\r
+  )\r
+{\r
+  EFI_DEV_PATH_PTR          Node;\r
+  PCI_IO_DEVICE             *Temp;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;\r
+  LIST_ENTRY                *CurrentLink;\r
+  BOOLEAN                   MisMatch;\r
+\r
+  MisMatch          = FALSE;\r
+\r
+  CurrentDevicePath = RemainingDevicePath;\r
+  Node.DevPath      = CurrentDevicePath;\r
+  Temp              = NULL;\r
+\r
+  while (!IsDevicePathEnd (CurrentDevicePath)) {\r
+\r
+    CurrentLink   = RootBridge->ChildList.ForwardLink;\r
+    Node.DevPath  = CurrentDevicePath;\r
+\r
+    while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
+      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+      if (Node.Pci->Device   == Temp->DeviceNumber &&\r
+          Node.Pci->Function == Temp->FunctionNumber) {\r
+        RootBridge = Temp;\r
+        break;\r
+      }\r
+\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+    }\r
+\r
+    //\r
+    // Check if we find the bridge\r
+    //\r
+    if (CurrentLink == &RootBridge->ChildList) {\r
+\r
+      MisMatch = TRUE;\r
+      break;\r
+\r
+    }\r
+\r
+    CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
+  }\r
+\r
+  if (MisMatch) {\r
+\r
+    CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
+\r
+    if (IsDevicePathEnd (CurrentDevicePath)) {\r
+      *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Temp != NULL) {\r
+    *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
+  } else {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.h
new file mode 100644 (file)
index 0000000..e97e90d
--- /dev/null
@@ -0,0 +1,289 @@
+/** @file\r
+  Supporting functions declaration for PCI devices management.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H_\r
+#define _EFI_PCI_DEVICE_SUPPORT_H_\r
+\r
+/**\r
+  Initialize the PCI devices pool.\r
+\r
+**/\r
+VOID\r
+InitializePciDevicePool (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Insert a root bridge into PCI device pool.\r
+\r
+  @param RootBridge     A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+InsertRootBridge (\r
+  IN PCI_IO_DEVICE      *RootBridge\r
+  );\r
+\r
+/**\r
+  This function is used to insert a PCI device node under\r
+  a bridge.\r
+\r
+  @param Bridge         The PCI bridge.\r
+  @param PciDeviceNode  The PCI device needs inserting.\r
+\r
+**/\r
+VOID\r
+InsertPciDevice (\r
+  IN PCI_IO_DEVICE      *Bridge,\r
+  IN PCI_IO_DEVICE      *PciDeviceNode\r
+  );\r
+\r
+/**\r
+  Destroy root bridge and remove it from deivce tree.\r
+\r
+  @param RootBridge     The bridge want to be removed.\r
+\r
+**/\r
+VOID\r
+DestroyRootBridge (\r
+  IN PCI_IO_DEVICE      *RootBridge\r
+  );\r
+\r
+/**\r
+  Destroy all the pci device node under the bridge.\r
+  Bridge itself is not included.\r
+\r
+  @param Bridge         A pointer to the PCI_IO_DEVICE.\r
+\r
+**/\r
+VOID\r
+DestroyPciDeviceTree (\r
+  IN PCI_IO_DEVICE      *Bridge\r
+  );\r
+\r
+/**\r
+  Destroy all device nodes under the root bridge\r
+  specified by Controller.\r
+\r
+  The root bridge itself is also included.\r
+\r
+  @param  Controller    Root bridge handle.\r
+\r
+  @retval EFI_SUCCESS   Destory all devcie nodes successfully.\r
+  @retval EFI_NOT_FOUND Cannot find any PCI device under specified\r
+                        root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+DestroyRootBridgeByHandle (\r
+  IN EFI_HANDLE        Controller\r
+  );\r
+\r
+/**\r
+  This function registers the PCI IO device.\r
+\r
+  It creates a handle for this PCI IO device (if the handle does not exist), attaches\r
+  appropriate protocols onto the handle, does necessary initialization, and sets up\r
+  parent/child relationship with its bus controller.\r
+\r
+  @param Controller     An EFI handle for the PCI bus controller.\r
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
+  @param Handle         A pointer to hold the returned EFI handle for the PCI IO device.\r
+\r
+  @retval EFI_SUCCESS   The PCI device is successfully registered.\r
+  @retval other         An error occurred when registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+  IN  EFI_HANDLE          Controller,\r
+  IN  PCI_IO_DEVICE       *PciIoDevice,\r
+  OUT EFI_HANDLE          *Handle      OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function is used to remove the whole PCI devices on the specified bridge from\r
+  the root bridge.\r
+\r
+  @param RootBridgeHandle   The root bridge device handle.\r
+  @param Bridge             The bridge device to be removed.\r
+\r
+**/\r
+VOID\r
+RemoveAllPciDeviceOnBridge (\r
+  EFI_HANDLE               RootBridgeHandle,\r
+  PCI_IO_DEVICE            *Bridge\r
+  );\r
+\r
+/**\r
+  This function is used to de-register the PCI IO device.\r
+\r
+  That includes un-installing PciIo protocol from the specified PCI\r
+  device handle.\r
+\r
+  @param Controller    An EFI handle for the PCI bus controller.\r
+  @param Handle        PCI device handle.\r
+\r
+  @retval EFI_SUCCESS  The PCI device is successfully de-registered.\r
+  @retval other        An error occurred when de-registering the PCI device.\r
+\r
+**/\r
+EFI_STATUS\r
+DeRegisterPciDevice (\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  EFI_HANDLE                     Handle\r
+  );\r
+\r
+/**\r
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.\r
+\r
+  @param Controller          The root bridge handle.\r
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.\r
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
+  @param NumberOfChildren    Children number.\r
+  @param ChildHandleBuffer   A pointer to the child handle buffer.\r
+\r
+  @retval EFI_NOT_READY   Device is not allocated.\r
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.\r
+  @retval EFI_NOT_FOUND   Can not find the specific device.\r
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevicesOnBridge (\r
+  IN EFI_HANDLE                          Controller,\r
+  IN PCI_IO_DEVICE                       *RootBridge,\r
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,\r
+  IN OUT UINT8                           *NumberOfChildren,\r
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer\r
+  );\r
+\r
+/**\r
+  Start to manage all the PCI devices it found previously under\r
+  the entire host bridge.\r
+\r
+  @param Controller          The root bridge handle.\r
+\r
+  @retval EFI_NOT_READY   Device is not allocated.\r
+  @retval EFI_SUCCESS     Success to start Pci device on host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+StartPciDevices (\r
+  IN EFI_HANDLE                         Controller\r
+  );\r
+\r
+/**\r
+  Create root bridge device.\r
+\r
+  @param RootBridgeHandle    Specified root bridge hanle.\r
+\r
+  @return The crated root bridge device instance, NULL means no\r
+          root bridge device instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreateRootBridge (\r
+  IN EFI_HANDLE                   RootBridgeHandle\r
+  );\r
+\r
+/**\r
+  Get root bridge device instance by specific root bridge handle.\r
+\r
+  @param RootBridgeHandle    Given root bridge handle.\r
+\r
+  @return The root bridge device instance, NULL means no root bridge\r
+          device instance found.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GetRootBridgeByHandle (\r
+  EFI_HANDLE RootBridgeHandle\r
+  );\r
+\r
+\r
+/**\r
+  Judege whether Pci device existed.\r
+\r
+  @param Bridge       Parent bridege instance.\r
+  @param PciIoDevice  Device instance.\r
+\r
+  @retval TRUE        Pci device existed.\r
+  @retval FALSE       Pci device did not exist.\r
+\r
+**/\r
+BOOLEAN\r
+PciDeviceExisted (\r
+  IN PCI_IO_DEVICE    *Bridge,\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Get the active VGA device on the same segment.\r
+\r
+  @param VgaDevice    PCI IO instance for the VGA device.\r
+\r
+  @return The active VGA device on the same segment.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheSameSegment (\r
+  IN PCI_IO_DEVICE        *VgaDevice\r
+  );\r
+\r
+/**\r
+  Get the active VGA device on the root bridge.\r
+\r
+  @param RootBridge  PCI IO instance for the root bridge.\r
+\r
+  @return The active VGA device.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+ActiveVGADeviceOnTheRootBridge (\r
+  IN PCI_IO_DEVICE        *RootBridge\r
+  );\r
+\r
+/**\r
+  Get HPC PCI address according to its device path.\r
+\r
+  @param RootBridge           Root bridege Io instance.\r
+  @param RemainingDevicePath  Given searching device path.\r
+  @param PciAddress           Buffer holding searched result.\r
+\r
+  @retval EFI_SUCCESS         PCI address was stored in PciAddress.\r
+  @retval EFI_NOT_FOUND       Can not find the specific device path.\r
+\r
+**/\r
+EFI_STATUS\r
+GetHpcPciAddressFromRootBridge (\r
+  IN  PCI_IO_DEVICE                    *RootBridge,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL         *RemainingDevicePath,\r
+  OUT UINT64                           *PciAddress\r
+  );\r
+\r
+/**\r
+  Destroy a pci device node.\r
+\r
+  All direct or indirect allocated resource for this node will be freed.\r
+\r
+  @param PciIoDevice  A pointer to the PCI_IO_DEVICE to be destoried.\r
+\r
+**/\r
+VOID\r
+FreePciDevice (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.c
new file mode 100644 (file)
index 0000000..119866b
--- /dev/null
@@ -0,0 +1,143 @@
+/** @file\r
+  Functions implementation for Bus Specific Driver Override protoocl.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  Initializes a PCI Driver Override Instance.\r
+\r
+  @param  PciIoDevice   PCI Device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciDriverOverrideInstance (\r
+  IN OUT PCI_IO_DEVICE          *PciIoDevice\r
+  )\r
+{\r
+  PciIoDevice->PciDriverOverride.GetDriver = GetDriver;\r
+}\r
+\r
+\r
+/**\r
+  Uses a bus specific algorithm to retrieve a driver image handle for a controller.\r
+\r
+  @param  This                  A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.\r
+  @param  DriverImageHandle     On input, a pointer to the previous driver image handle returned\r
+                                by GetDriver(). On output, a pointer to the next driver\r
+                                image handle. Passing in a NULL, will return the first driver\r
+                                image handle.\r
+\r
+  @retval EFI_SUCCESS           A bus specific override driver is returned in DriverImageHandle.\r
+  @retval EFI_NOT_FOUND         The end of the list of override drivers was reached.\r
+                                A bus specific override driver is not returned in DriverImageHandle.\r
+  @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a\r
+                                previous call to GetDriver().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,\r
+  IN OUT EFI_HANDLE                                         *DriverImageHandle\r
+  )\r
+{\r
+  PCI_IO_DEVICE             *PciIoDevice;\r
+  LIST_ENTRY                *CurrentLink;\r
+  PCI_DRIVER_OVERRIDE_LIST  *Node;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);\r
+\r
+  CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &PciIoDevice->OptionRomDriverList) {\r
+\r
+    Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);\r
+\r
+    if (*DriverImageHandle == NULL) {\r
+\r
+      *DriverImageHandle = Node->DriverImageHandle;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (*DriverImageHandle == Node->DriverImageHandle) {\r
+\r
+      if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||\r
+          CurrentLink->ForwardLink == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Get next node\r
+      //\r
+      Node                = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);\r
+      *DriverImageHandle  = Node->DriverImageHandle;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+  Add an overriding driver image.\r
+\r
+  @param PciIoDevice        Instance of PciIo device.\r
+  @param DriverImageHandle  new added driver image.\r
+\r
+  @retval EFI_SUCCESS          Successfully added driver.\r
+  @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.\r
+  @retval other                Some error occurred when locating gEfiLoadedImageProtocolGuid.\r
+\r
+**/\r
+EFI_STATUS\r
+AddDriver (\r
+  IN PCI_IO_DEVICE     *PciIoDevice,\r
+  IN EFI_HANDLE        DriverImageHandle\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;\r
+  PCI_DRIVER_OVERRIDE_LIST      *Node;\r
+\r
+  Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));\r
+  if (Node == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Node->Signature         = DRIVER_OVERRIDE_SIGNATURE;\r
+  Node->DriverImageHandle = DriverImageHandle;\r
+\r
+  InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));\r
+\r
+  PciIoDevice->BusOverride  = TRUE;\r
+\r
+  ImageContext.Handle    = LoadedImage->ImageBase;\r
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+  //\r
+  // Get information about the image\r
+  //\r
+  PeCoffLoaderGetImageInfo (&ImageContext);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDriverOverride.h
new file mode 100644 (file)
index 0000000..d28fb7f
--- /dev/null
@@ -0,0 +1,86 @@
+/** @file\r
+  Functions declaration for Bus Specific Driver Override protoocl.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H_\r
+#define _EFI_PCI_DRIVER_OVERRRIDE_H_\r
+\r
+#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')\r
+\r
+//\r
+// PCI driver override driver image list\r
+//\r
+typedef struct {\r
+  UINT32          Signature;\r
+  LIST_ENTRY      Link;\r
+  EFI_HANDLE      DriverImageHandle;\r
+} PCI_DRIVER_OVERRIDE_LIST;\r
+\r
+\r
+#define DRIVER_OVERRIDE_FROM_LINK(a) \\r
+  CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)\r
+\r
+/**\r
+  Initializes a PCI Driver Override Instance.\r
+\r
+  @param  PciIoDevice   PCI Device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciDriverOverrideInstance (\r
+  IN OUT PCI_IO_DEVICE          *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Add an overriding driver image.\r
+\r
+  @param PciIoDevice        Instance of PciIo device.\r
+  @param DriverImageHandle  new added driver image.\r
+\r
+  @retval EFI_SUCCESS          Successfully added driver.\r
+  @retval EFI_OUT_OF_RESOURCES No memory resource for new driver instance.\r
+  @retval other                Some error occurred when locating gEfiLoadedImageProtocolGuid.\r
+\r
+**/\r
+EFI_STATUS\r
+AddDriver (\r
+  IN PCI_IO_DEVICE     *PciIoDevice,\r
+  IN EFI_HANDLE        DriverImageHandle\r
+  );\r
+\r
+\r
+/**\r
+  Uses a bus specific algorithm to retrieve a driver image handle for a controller.\r
+\r
+  @param  This                  A pointer to the EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL instance.\r
+  @param  DriverImageHandle     On input, a pointer to the previous driver image handle returned\r
+                                by GetDriver(). On output, a pointer to the next driver\r
+                                image handle. Passing in a NULL, will return the first driver\r
+                                image handle.\r
+\r
+  @retval EFI_SUCCESS           A bus specific override driver is returned in DriverImageHandle.\r
+  @retval EFI_NOT_FOUND         The end of the list of override drivers was reached.\r
+                                A bus specific override driver is not returned in DriverImageHandle.\r
+  @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a\r
+                                previous call to GetDriver().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriver (\r
+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,\r
+  IN OUT EFI_HANDLE                                         *DriverImageHandle\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
new file mode 100644 (file)
index 0000000..6c1de3f
--- /dev/null
@@ -0,0 +1,2171 @@
+/** @file\r
+  PCI eunmeration implementation on entire PCI bus system for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  This routine is used to enumerate entire pci bus system\r
+  in a given platform.\r
+\r
+  @param Controller  Parent controller handle.\r
+\r
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.\r
+  @retval other          Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumerator (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+{\r
+  EFI_HANDLE                                        Handle;\r
+  EFI_HANDLE                                        HostBridgeHandle;\r
+  EFI_STATUS                                        Status;\r
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   *PciRootBridgeIo;\r
+\r
+  //\r
+  // If PCI bus has already done the full enumeration, never do it again\r
+  //\r
+  if (!gFullEnumeration) {\r
+    return PciEnumeratorLight (Controller);\r
+  }\r
+\r
+  //\r
+  // Get the rootbridge Io protocol to find the host bridge handle\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the host bridge handle\r
+  //\r
+  HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+\r
+  //\r
+  // Get the pci host bridge resource allocation protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  HostBridgeHandle,\r
+                  &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
+                  (VOID **) &PciResAlloc,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Notify the pci bus enumeration is about to begin\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);\r
+\r
+  //\r
+  // Start the bus allocation phase\r
+  //\r
+  Status = PciHostBridgeEnumerator (PciResAlloc);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Submit the resource request\r
+  //\r
+  Status = PciHostBridgeResourceAllocator (PciResAlloc);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Notify the pci bus enumeration is about to complete\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);\r
+\r
+  //\r
+  // Process P2C\r
+  //\r
+  Status = PciHostBridgeP2CProcess (PciResAlloc);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Process attributes for devices on this host bridge\r
+  //\r
+  Status = PciHostBridgeDeviceAttribute (PciResAlloc);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  gFullEnumeration = FALSE;\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiPciEnumerationCompleteProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enumerate PCI root bridge.\r
+\r
+  @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+  @param RootBridgeDev Instance of root bridge device.\r
+\r
+  @retval EFI_SUCCESS  Successfully enumerated root bridge.\r
+  @retval other        Failed to enumerate root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeEnumerator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,\r
+  IN PCI_IO_DEVICE                                     *RootBridgeDev\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+  UINT8                             SubBusNumber;\r
+  UINT8                             StartBusNumber;\r
+  UINT8                             PaddedBusRange;\r
+  EFI_HANDLE                        RootBridgeHandle;\r
+\r
+  SubBusNumber    = 0;\r
+  StartBusNumber  = 0;\r
+  PaddedBusRange  = 0;\r
+\r
+  //\r
+  // Get the root bridge handle\r
+  //\r
+  RootBridgeHandle = RootBridgeDev->Handle;\r
+\r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,\r
+    RootBridgeDev->DevicePath\r
+    );\r
+\r
+  //\r
+  // Get the Bus information\r
+  //\r
+  Status = PciResAlloc->StartBusEnumeration (\r
+                          PciResAlloc,\r
+                          RootBridgeHandle,\r
+                          (VOID **) &Configuration\r
+                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get the bus number to start with\r
+  //\r
+  StartBusNumber = (UINT8) (Configuration->AddrRangeMin);\r
+  PaddedBusRange  = (UINT8) (Configuration->AddrRangeMax);\r
+\r
+  //\r
+  // Initialize the subordinate bus number\r
+  //\r
+  SubBusNumber = StartBusNumber;\r
+\r
+  //\r
+  // Reset all assigned PCI bus number\r
+  //\r
+  ResetAllPpbBusNumber (\r
+    RootBridgeDev,\r
+    StartBusNumber\r
+  );\r
+\r
+  //\r
+  // Assign bus number\r
+  //\r
+  Status = PciScanBus (\r
+            RootBridgeDev,\r
+            (UINT8) (Configuration->AddrRangeMin),\r
+            &SubBusNumber,\r
+            &PaddedBusRange\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+\r
+  //\r
+  // Assign max bus number scanned\r
+  //\r
+  Configuration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;\r
+\r
+  //\r
+  // Set bus number\r
+  //\r
+  Status = PciResAlloc->SetBusNumbers (\r
+                          PciResAlloc,\r
+                          RootBridgeHandle,\r
+                          Configuration\r
+                          );\r
+\r
+  FreePool (Configuration);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This routine is used to process all PCI devices' Option Rom\r
+  on a certain root bridge.\r
+\r
+  @param Bridge     Given parent's root bridge.\r
+  @param RomBase    Base address of ROM driver loaded from.\r
+  @param MaxLength  Maximum rom size.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRom (\r
+  IN PCI_IO_DEVICE *Bridge,\r
+  IN UINT64        RomBase,\r
+  IN UINT64        MaxLength\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+\r
+  //\r
+  // Go through bridges to reach all devices\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+\r
+      //\r
+      // Go further to process the option rom under this bridge\r
+      //\r
+      ProcessOptionRom (Temp, RomBase, MaxLength);\r
+    }\r
+\r
+    if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {\r
+\r
+      //\r
+      // Load and process the option rom\r
+      //\r
+      LoadOpRomImage (Temp, RomBase);\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  This routine is used to assign bus number to the given PCI bus system\r
+\r
+  @param Bridge             Parent root bridge instance.\r
+  @param StartBusNumber     Number of beginning.\r
+  @param SubBusNumber       The number of sub bus.\r
+\r
+  @retval EFI_SUCCESS       Successfully assigned bus number.\r
+  @retval EFI_DEVICE_ERROR  Failed to assign bus number.\r
+\r
+**/\r
+EFI_STATUS\r
+PciAssignBusNumber (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber,\r
+  OUT UINT8                             *SubBusNumber\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  PCI_TYPE00                      Pci;\r
+  UINT8                           Device;\r
+  UINT8                           Func;\r
+  UINT64                          Address;\r
+  UINTN                           SecondBus;\r
+  UINT16                          Register;\r
+  UINT8                           Register8;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+\r
+  SecondBus       = 0;\r
+  Register        = 0;\r
+\r
+  *SubBusNumber = StartBusNumber;\r
+\r
+  //\r
+  // First check to see whether the parent is ppb\r
+  //\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether a pci device is present\r
+      //\r
+      Status = PciDevicePresent (\r
+                PciRootBridgeIo,\r
+                &Pci,\r
+                StartBusNumber,\r
+                Device,\r
+                Func\r
+                );\r
+\r
+      if (!EFI_ERROR (Status)   &&\r
+          (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
+\r
+        //\r
+        // Reserved one bus for cardbus bridge\r
+        //\r
+        SecondBus = ++(*SubBusNumber);\r
+\r
+        Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
+\r
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
+\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint16,\r
+                                        Address,\r
+                                        1,\r
+                                        &Register\r
+                                        );\r
+\r
+        //\r
+        // Initialize SubBusNumber to SecondBus\r
+        //\r
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint8,\r
+                                        Address,\r
+                                        1,\r
+                                        SubBusNumber\r
+                                        );\r
+        //\r
+        // If it is PPB, resursively search down this bridge\r
+        //\r
+        if (IS_PCI_BRIDGE (&Pci)) {\r
+\r
+          Register8 = 0xFF;\r
+          Status = PciRootBridgeIo->Pci.Write (\r
+                                          PciRootBridgeIo,\r
+                                          EfiPciWidthUint8,\r
+                                          Address,\r
+                                          1,\r
+                                          &Register8\r
+                                          );\r
+\r
+          Status = PciAssignBusNumber (\r
+                    Bridge,\r
+                    (UINT8) (SecondBus),\r
+                    SubBusNumber\r
+                    );\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return EFI_DEVICE_ERROR;\r
+          }\r
+        }\r
+\r
+        //\r
+        // Set the current maximum bus number under the PPB\r
+        //\r
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);\r
+\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint8,\r
+                                        Address,\r
+                                        1,\r
+                                        SubBusNumber\r
+                                        );\r
+\r
+      }\r
+\r
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+        //\r
+        // Skip sub functions, this is not a multi function device\r
+        //\r
+        Func = PCI_MAX_FUNC;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This routine is used to determine the root bridge attribute by interfacing\r
+  the host bridge resource allocation protocol.\r
+\r
+  @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+  @param RootBridgeDev  Root bridge instance\r
+\r
+  @retval EFI_SUCCESS  Successfully got root bridge's attribute.\r
+  @retval other        Failed to get attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineRootBridgeAttributes (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+  IN PCI_IO_DEVICE                                    *RootBridgeDev\r
+  )\r
+{\r
+  UINT64      Attributes;\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  RootBridgeHandle;\r
+\r
+  Attributes        = 0;\r
+  RootBridgeHandle  = RootBridgeDev->Handle;\r
+\r
+  //\r
+  // Get root bridge attribute by calling into pci host bridge resource allocation protocol\r
+  //\r
+  Status = PciResAlloc->GetAllocAttributes (\r
+                          PciResAlloc,\r
+                          RootBridgeHandle,\r
+                          &Attributes\r
+                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Here is the point where PCI bus driver calls HOST bridge allocation protocol\r
+  // Currently we hardcoded for ea815\r
+  //\r
+  if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {\r
+    RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;\r
+  }\r
+\r
+  if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {\r
+    RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+  }\r
+\r
+  RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+  RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+  RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get Max Option Rom size on specified bridge.\r
+\r
+  @param Bridge    Given bridge device instance.\r
+\r
+  @return Max size of option rom needed.\r
+\r
+**/\r
+UINT64\r
+GetMaxOptionRomSize (\r
+  IN PCI_IO_DEVICE   *Bridge\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+  UINT64          MaxOptionRomSize;\r
+  UINT64          TempOptionRomSize;\r
+\r
+  MaxOptionRomSize = 0;\r
+\r
+  //\r
+  // Go through bridges to reach all devices\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+\r
+      //\r
+      // Get max option rom size under this bridge\r
+      //\r
+      TempOptionRomSize = GetMaxOptionRomSize (Temp);\r
+\r
+      //\r
+      // Compare with the option rom size of the bridge\r
+      // Get the larger one\r
+      //\r
+      if (Temp->RomSize > TempOptionRomSize) {\r
+        TempOptionRomSize = Temp->RomSize;\r
+      }\r
+\r
+    } else {\r
+\r
+      //\r
+      // For devices get the rom size directly\r
+      //\r
+      TempOptionRomSize = Temp->RomSize;\r
+    }\r
+\r
+    //\r
+    // Get the largest rom size on this bridge\r
+    //\r
+    if (TempOptionRomSize > MaxOptionRomSize) {\r
+      MaxOptionRomSize = TempOptionRomSize;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return MaxOptionRomSize;\r
+}\r
+\r
+/**\r
+  Process attributes of devices on this host bridge\r
+\r
+  @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS   Successfully process attribute.\r
+  @retval EFI_NOT_FOUND Can not find the specific root bridge device.\r
+  @retval other         Failed to determine the root bridge device's attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeDeviceAttribute (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  )\r
+{\r
+  EFI_HANDLE    RootBridgeHandle;\r
+  PCI_IO_DEVICE *RootBridgeDev;\r
+  EFI_STATUS    Status;\r
+\r
+  RootBridgeHandle = NULL;\r
+\r
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // Get RootBridg Device by handle\r
+    //\r
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Set the attributes for devcies behind the Root Bridge\r
+    //\r
+    Status = DetermineDeviceAttribute (RootBridgeDev);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get resource allocation status from the ACPI resource descriptor.\r
+\r
+  @param AcpiConfig       Point to Acpi configuration table.\r
+  @param IoResStatus      Return the status of I/O resource.\r
+  @param Mem32ResStatus   Return the status of 32-bit Memory resource.\r
+  @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.\r
+  @param Mem64ResStatus   Return the status of 64-bit Memory resource.\r
+  @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.\r
+\r
+**/\r
+VOID\r
+GetResourceAllocationStatus (\r
+  VOID        *AcpiConfig,\r
+  OUT UINT64  *IoResStatus,\r
+  OUT UINT64  *Mem32ResStatus,\r
+  OUT UINT64  *PMem32ResStatus,\r
+  OUT UINT64  *Mem64ResStatus,\r
+  OUT UINT64  *PMem64ResStatus\r
+  )\r
+{\r
+  UINT8                             *Temp;\r
+  UINT64                            ResStatus;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;\r
+\r
+  Temp = (UINT8 *) AcpiConfig;\r
+\r
+  while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+\r
+    ACPIAddressDesc       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
+    ResStatus = ACPIAddressDesc->AddrTranslationOffset;\r
+\r
+    switch (ACPIAddressDesc->ResType) {\r
+    case 0:\r
+      if (ACPIAddressDesc->AddrSpaceGranularity == 32) {\r
+        if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
+          //\r
+          // Pmem32\r
+          //\r
+          *PMem32ResStatus = ResStatus;\r
+        } else {\r
+          //\r
+          // Mem32\r
+          //\r
+          *Mem32ResStatus = ResStatus;\r
+        }\r
+      }\r
+\r
+      if (ACPIAddressDesc->AddrSpaceGranularity == 64) {\r
+        if (ACPIAddressDesc->SpecificFlag == 0x06) {\r
+          //\r
+          // PMem64\r
+          //\r
+          *PMem64ResStatus = ResStatus;\r
+        } else {\r
+          //\r
+          // Mem64\r
+          //\r
+          *Mem64ResStatus = ResStatus;\r
+        }\r
+      }\r
+\r
+      break;\r
+\r
+    case 1:\r
+      //\r
+      // Io\r
+      //\r
+      *IoResStatus = ResStatus;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+  }\r
+}\r
+\r
+/**\r
+  Remove a PCI device from device pool and mark its bar.\r
+\r
+  @param PciDevice Instance of Pci device.\r
+\r
+  @retval EFI_SUCCESS Successfully remove the PCI device.\r
+  @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+RejectPciDevice (\r
+  IN PCI_IO_DEVICE       *PciDevice\r
+  )\r
+{\r
+  PCI_IO_DEVICE   *Bridge;\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+\r
+  //\r
+  // Remove the padding resource from a bridge\r
+  //\r
+  if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&\r
+       PciDevice->ResourcePaddingDescriptors != NULL ) {\r
+    FreePool (PciDevice->ResourcePaddingDescriptors);\r
+    PciDevice->ResourcePaddingDescriptors = NULL;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Skip RB and PPB\r
+  //\r
+  if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {\r
+    //\r
+    // Get the root bridge device\r
+    //\r
+    Bridge = PciDevice;\r
+    while (Bridge->Parent != NULL) {\r
+      Bridge = Bridge->Parent;\r
+    }\r
+\r
+    RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);\r
+\r
+    //\r
+    // Mark its bar\r
+    //\r
+    InitializeP2C (PciDevice);\r
+  }\r
+\r
+  //\r
+  // Remove the device\r
+  //\r
+  Bridge      = PciDevice->Parent;\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (Temp == PciDevice) {\r
+      InitializePciDevice (Temp);\r
+      RemoveEntryList (CurrentLink);\r
+      FreePciDevice (Temp);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_ABORTED;\r
+}\r
+\r
+/**\r
+  Determine whethter a PCI device can be rejected.\r
+\r
+  @param  PciResNode Pointer to Pci resource node instance.\r
+\r
+  @retval TRUE  The PCI device can be rejected.\r
+  @retval TRUE  The PCI device cannot be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsRejectiveDevice (\r
+  IN  PCI_RESOURCE_NODE   *PciResNode\r
+  )\r
+{\r
+  PCI_IO_DEVICE *Temp;\r
+\r
+  Temp = PciResNode->PciDev;\r
+\r
+  //\r
+  // Ensure the device is present\r
+  //\r
+  if (Temp == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // PPB and RB should go ahead\r
+  //\r
+  if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Skip device on Bus0\r
+  //\r
+  if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Skip VGA\r
+  //\r
+  if (IS_PCI_VGA (&Temp->Pci)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Compare two resource nodes and get the larger resource consumer.\r
+\r
+  @param PciResNode1  resource node 1 want to be compared\r
+  @param PciResNode2  resource node 2 want to be compared\r
+\r
+  @return Larger resource node.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetLargerConsumerDevice (\r
+  IN  PCI_RESOURCE_NODE   *PciResNode1,\r
+  IN  PCI_RESOURCE_NODE   *PciResNode2\r
+  )\r
+{\r
+  if (PciResNode2 == NULL) {\r
+    return PciResNode1;\r
+  }\r
+\r
+  if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \\r
+       && (PciResNode2->ResourceUsage != PciResUsagePadding) )\r
+  {\r
+    return PciResNode1;\r
+  }\r
+\r
+  if (PciResNode1 == NULL) {\r
+    return PciResNode2;\r
+  }\r
+\r
+  if ((PciResNode1->Length) > (PciResNode2->Length)) {\r
+    return PciResNode1;\r
+  }\r
+\r
+  return PciResNode2;\r
+}\r
+\r
+\r
+/**\r
+  Get the max resource consumer in the host resource pool.\r
+\r
+  @param ResPool  Pointer to resource pool node.\r
+\r
+  @return The max resource consumer in the host resource pool.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetMaxResourceConsumerDevice (\r
+  IN  PCI_RESOURCE_NODE   *ResPool\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Temp;\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *PciResNode;\r
+  PCI_RESOURCE_NODE *PPBResNode;\r
+\r
+  PciResNode  = NULL;\r
+\r
+  CurrentLink = ResPool->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IsRejectiveDevice (Temp)) {\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+      continue;\r
+    }\r
+\r
+    if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \\r
+          && (Temp->ResourceUsage != PciResUsagePadding))\r
+    {\r
+      PPBResNode  = GetMaxResourceConsumerDevice (Temp);\r
+      PciResNode  = GetLargerConsumerDevice (PciResNode, PPBResNode);\r
+    } else {\r
+      PciResNode = GetLargerConsumerDevice (PciResNode, Temp);\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return PciResNode;\r
+}\r
+\r
+/**\r
+  Adjust host bridge allocation so as to reduce resource requirement\r
+\r
+  @param IoPool           Pointer to instance of I/O resource Node.\r
+  @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.\r
+  @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.\r
+  @param Mem64Pool        Pointer to instance of 64-bit memory resource node.\r
+  @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.\r
+  @param IoResStatus      Status of I/O resource Node.\r
+  @param Mem32ResStatus   Status of 32-bit memory resource Node.\r
+  @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.\r
+  @param Mem64ResStatus   Status of 64-bit memory resource node.\r
+  @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.\r
+\r
+  @retval EFI_SUCCESS     Successfully adjusted resoruce on host bridge.\r
+  @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeAdjustAllocation (\r
+  IN  PCI_RESOURCE_NODE   *IoPool,\r
+  IN  PCI_RESOURCE_NODE   *Mem32Pool,\r
+  IN  PCI_RESOURCE_NODE   *PMem32Pool,\r
+  IN  PCI_RESOURCE_NODE   *Mem64Pool,\r
+  IN  PCI_RESOURCE_NODE   *PMem64Pool,\r
+  IN  UINT64              IoResStatus,\r
+  IN  UINT64              Mem32ResStatus,\r
+  IN  UINT64              PMem32ResStatus,\r
+  IN  UINT64              Mem64ResStatus,\r
+  IN  UINT64              PMem64ResStatus\r
+  )\r
+{\r
+  BOOLEAN                               AllocationAjusted;\r
+  PCI_RESOURCE_NODE                     *PciResNode;\r
+  PCI_RESOURCE_NODE                     *ResPool[5];\r
+  PCI_IO_DEVICE                         *RemovedPciDev[5];\r
+  UINT64                                ResStatus[5];\r
+  UINTN                                 RemovedPciDevNum;\r
+  UINTN                                 DevIndex;\r
+  UINTN                                 ResType;\r
+  EFI_STATUS                            Status;\r
+  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
+\r
+  PciResNode = NULL;\r
+  ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));\r
+  RemovedPciDevNum  = 0;\r
+\r
+  ResPool[0]        = IoPool;\r
+  ResPool[1]        = Mem32Pool;\r
+  ResPool[2]        = PMem32Pool;\r
+  ResPool[3]        = Mem64Pool;\r
+  ResPool[4]        = PMem64Pool;\r
+\r
+  ResStatus[0]      = IoResStatus;\r
+  ResStatus[1]      = Mem32ResStatus;\r
+  ResStatus[2]      = PMem32ResStatus;\r
+  ResStatus[3]      = Mem64ResStatus;\r
+  ResStatus[4]      = PMem64ResStatus;\r
+\r
+  AllocationAjusted = FALSE;\r
+\r
+  for (ResType = 0; ResType < 5; ResType++) {\r
+\r
+    if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {\r
+      continue;\r
+    }\r
+\r
+    if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {\r
+      //\r
+      // Host bridge hasn't this resource type\r
+      //\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    //\r
+    // Hostbridge hasn't enough resource\r
+    //\r
+    PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);\r
+    if (PciResNode == NULL) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check if the device has been removed before\r
+    //\r
+    for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {\r
+      if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (DevIndex != RemovedPciDevNum) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Remove the device if it isn't in the array\r
+    //\r
+    Status = RejectPciDevice (PciResNode->PciDev);\r
+    if (Status == EFI_SUCCESS) {\r
+\r
+      //\r
+      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
+      //\r
+      //\r
+      // Have no way to get ReqRes, AllocRes & Bar here\r
+      //\r
+      ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
+      AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+      AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;\r
+      AllocFailExtendedData.Bar            = PciResNode->Bar;\r
+\r
+      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+            EFI_PROGRESS_CODE,\r
+            EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
+            (VOID *) &AllocFailExtendedData,\r
+            sizeof (AllocFailExtendedData)\r
+            );\r
+\r
+      //\r
+      // Add it to the array and indicate at least a device has been rejected\r
+      //\r
+      RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;\r
+      AllocationAjusted                 = TRUE;\r
+    }\r
+  }\r
+  //\r
+  // End for\r
+  //\r
+\r
+  if (AllocationAjusted) {\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_ABORTED;\r
+  }\r
+}\r
+\r
+/**\r
+  Summary requests for all resource type, and contruct ACPI resource\r
+  requestor instance.\r
+\r
+  @param Bridge           detecting bridge\r
+  @param IoNode           Pointer to instance of I/O resource Node\r
+  @param Mem32Node        Pointer to instance of 32-bit memory resource Node\r
+  @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node\r
+  @param Mem64Node        Pointer to instance of 64-bit memory resource node\r
+  @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node\r
+  @param Config           Output buffer holding new constructed APCI resource requestor\r
+\r
+  @retval EFI_SUCCESS           Successfully constructed ACPI resource.\r
+  @retval EFI_OUT_OF_RESOURCES  No memory availabe.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructAcpiResourceRequestor (\r
+  IN PCI_IO_DEVICE      *Bridge,\r
+  IN PCI_RESOURCE_NODE  *IoNode,\r
+  IN PCI_RESOURCE_NODE  *Mem32Node,\r
+  IN PCI_RESOURCE_NODE  *PMem32Node,\r
+  IN PCI_RESOURCE_NODE  *Mem64Node,\r
+  IN PCI_RESOURCE_NODE  *PMem64Node,\r
+  OUT VOID              **Config\r
+  )\r
+{\r
+  UINT8                             NumConfig;\r
+  UINT8                             Aperture;\r
+  UINT8                             *Configuration;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
+\r
+  NumConfig = 0;\r
+  Aperture  = 0;\r
+\r
+  *Config  = NULL;\r
+\r
+  //\r
+  // if there is io request, add to the io aperture\r
+  //\r
+  if (ResourceRequestExisted (IoNode)) {\r
+    NumConfig++;\r
+    Aperture |= 0x01;\r
+  }\r
+\r
+  //\r
+  // if there is mem32 request, add to the mem32 aperture\r
+  //\r
+  if (ResourceRequestExisted (Mem32Node)) {\r
+    NumConfig++;\r
+    Aperture |= 0x02;\r
+  }\r
+\r
+  //\r
+  // if there is pmem32 request, add to the pmem32 aperture\r
+  //\r
+  if (ResourceRequestExisted (PMem32Node)) {\r
+    NumConfig++;\r
+    Aperture |= 0x04;\r
+  }\r
+\r
+  //\r
+  // if there is mem64 request, add to the mem64 aperture\r
+  //\r
+  if (ResourceRequestExisted (Mem64Node)) {\r
+    NumConfig++;\r
+    Aperture |= 0x08;\r
+  }\r
+\r
+  //\r
+  // if there is pmem64 request, add to the pmem64 aperture\r
+  //\r
+  if (ResourceRequestExisted (PMem64Node)) {\r
+    NumConfig++;\r
+    Aperture |= 0x10;\r
+  }\r
+\r
+  if (NumConfig != 0) {\r
+\r
+    //\r
+    // If there is at least one type of resource request,\r
+    // allocate a acpi resource node\r
+    //\r
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    if (Configuration == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+    //\r
+    // Deal with io aperture\r
+    //\r
+    if ((Aperture & 0x01) != 0) {\r
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      //\r
+      // Io\r
+      //\r
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+      //\r
+      // non ISA range\r
+      //\r
+      Ptr->SpecificFlag = 1;\r
+      Ptr->AddrLen      = IoNode->Length;\r
+      Ptr->AddrRangeMax = IoNode->Alignment;\r
+\r
+      Ptr++;\r
+    }\r
+    //\r
+    // Deal with mem32 aperture\r
+    //\r
+    if ((Aperture & 0x02) != 0) {\r
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      //\r
+      // Mem\r
+      //\r
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+      //\r
+      // Nonprefechable\r
+      //\r
+      Ptr->SpecificFlag = 0;\r
+      //\r
+      // 32 bit\r
+      //\r
+      Ptr->AddrSpaceGranularity = 32;\r
+      Ptr->AddrLen      = Mem32Node->Length;\r
+      Ptr->AddrRangeMax = Mem32Node->Alignment;\r
+\r
+      Ptr++;\r
+    }\r
+\r
+    //\r
+    // Deal with Pmem32 aperture\r
+    //\r
+    if ((Aperture & 0x04) != 0) {\r
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      //\r
+      // Mem\r
+      //\r
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+      //\r
+      // prefechable\r
+      //\r
+      Ptr->SpecificFlag = 0x6;\r
+      //\r
+      // 32 bit\r
+      //\r
+      Ptr->AddrSpaceGranularity = 32;\r
+      Ptr->AddrLen      = PMem32Node->Length;\r
+      Ptr->AddrRangeMax = PMem32Node->Alignment;\r
+\r
+      Ptr++;\r
+    }\r
+    //\r
+    // Deal with mem64 aperture\r
+    //\r
+    if ((Aperture & 0x08) != 0) {\r
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      //\r
+      // Mem\r
+      //\r
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+      //\r
+      // nonprefechable\r
+      //\r
+      Ptr->SpecificFlag = 0;\r
+      //\r
+      // 64 bit\r
+      //\r
+      Ptr->AddrSpaceGranularity = 64;\r
+      Ptr->AddrLen      = Mem64Node->Length;\r
+      Ptr->AddrRangeMax = Mem64Node->Alignment;\r
+\r
+      Ptr++;\r
+    }\r
+    //\r
+    // Deal with Pmem64 aperture\r
+    //\r
+    if ((Aperture & 0x10) != 0) {\r
+      Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len      = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+      //\r
+      // Mem\r
+      //\r
+      Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+      //\r
+      // prefechable\r
+      //\r
+      Ptr->SpecificFlag = 0x06;\r
+      //\r
+      // 64 bit\r
+      //\r
+      Ptr->AddrSpaceGranularity = 64;\r
+      Ptr->AddrLen      = PMem64Node->Length;\r
+      Ptr->AddrRangeMax = PMem64Node->Alignment;\r
+\r
+      Ptr++;\r
+    }\r
+\r
+    //\r
+    // put the checksum\r
+    //\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;\r
+\r
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+    PtrEnd->Checksum  = 0;\r
+\r
+  } else {\r
+\r
+    //\r
+    // If there is no resource request\r
+    //\r
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    if (Configuration == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);\r
+    Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);\r
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+    PtrEnd->Checksum  = 0;\r
+  }\r
+\r
+  *Config = Configuration;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get resource base from an acpi configuration descriptor.\r
+\r
+  @param Config       An acpi configuration descriptor.\r
+  @param IoBase       Output of I/O resource base address.\r
+  @param Mem32Base    Output of 32-bit memory base address.\r
+  @param PMem32Base   Output of 32-bit prefetchable memory base address.\r
+  @param Mem64Base    Output of 64-bit memory base address.\r
+  @param PMem64Base   Output of 64-bit prefetchable memory base address.\r
+\r
+**/\r
+VOID\r
+GetResourceBase (\r
+  IN VOID     *Config,\r
+  OUT UINT64  *IoBase,\r
+  OUT UINT64  *Mem32Base,\r
+  OUT UINT64  *PMem32Base,\r
+  OUT UINT64  *Mem64Base,\r
+  OUT UINT64  *PMem64Base\r
+  )\r
+{\r
+  UINT8                             *Temp;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  UINT64                            ResStatus;\r
+\r
+  ASSERT (Config != NULL);\r
+\r
+  *IoBase     = 0xFFFFFFFFFFFFFFFFULL;\r
+  *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;\r
+  *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;\r
+  *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;\r
+  *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+  Temp        = (UINT8 *) Config;\r
+\r
+  while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+\r
+    Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;\r
+    ResStatus = Ptr->AddrTranslationOffset;\r
+\r
+    if (ResStatus == EFI_RESOURCE_SATISFIED) {\r
+\r
+      switch (Ptr->ResType) {\r
+\r
+      //\r
+      // Memory type aperture\r
+      //\r
+      case 0:\r
+\r
+        //\r
+        // Check to see the granularity\r
+        //\r
+        if (Ptr->AddrSpaceGranularity == 32) {\r
+          if ((Ptr->SpecificFlag & 0x06) != 0) {\r
+            *PMem32Base = Ptr->AddrRangeMin;\r
+          } else {\r
+            *Mem32Base = Ptr->AddrRangeMin;\r
+          }\r
+        }\r
+\r
+        if (Ptr->AddrSpaceGranularity == 64) {\r
+          if ((Ptr->SpecificFlag & 0x06) != 0) {\r
+            *PMem64Base = Ptr->AddrRangeMin;\r
+          } else {\r
+            *Mem64Base = Ptr->AddrRangeMin;\r
+          }\r
+        }\r
+        break;\r
+\r
+      case 1:\r
+\r
+        //\r
+        // Io type aperture\r
+        //\r
+        *IoBase = Ptr->AddrRangeMin;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+\r
+      }\r
+      //\r
+      // End switch\r
+      //\r
+    }\r
+    //\r
+    // End for\r
+    //\r
+    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+  }\r
+}\r
+\r
+/**\r
+  Enumerate pci bridge, allocate resource and determine attribute\r
+  for devices on this bridge.\r
+\r
+  @param BridgeDev    Pointer to instance of bridge device.\r
+\r
+  @retval EFI_SUCCESS Successfully enumerated PCI bridge.\r
+  @retval other       Failed to enumerate.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeEnumerator (\r
+  IN PCI_IO_DEVICE                                     *BridgeDev\r
+  )\r
+{\r
+  UINT8               SubBusNumber;\r
+  UINT8               StartBusNumber;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  EFI_STATUS          Status;\r
+\r
+  SubBusNumber    = 0;\r
+  StartBusNumber  = 0;\r
+  PciIo           = &(BridgeDev->PciIo);\r
+  Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciAssignBusNumber (\r
+            BridgeDev,\r
+            StartBusNumber,\r
+            &SubBusNumber\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciBridgeResourceAllocator (BridgeDev);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = DetermineDeviceAttribute (BridgeDev);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Allocate all kinds of resource for PCI bridge.\r
+\r
+  @param  Bridge      Pointer to bridge instance.\r
+\r
+  @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.\r
+  @retval other       Failed to allocate resource for bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeResourceAllocator (\r
+  IN PCI_IO_DEVICE  *Bridge\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *IoBridge;\r
+  PCI_RESOURCE_NODE *Mem32Bridge;\r
+  PCI_RESOURCE_NODE *PMem32Bridge;\r
+  PCI_RESOURCE_NODE *Mem64Bridge;\r
+  PCI_RESOURCE_NODE *PMem64Bridge;\r
+  UINT64            IoBase;\r
+  UINT64            Mem32Base;\r
+  UINT64            PMem32Base;\r
+  UINT64            Mem64Base;\r
+  UINT64            PMem64Base;\r
+  EFI_STATUS        Status;\r
+\r
+  IoBridge = CreateResourceNode (\r
+               Bridge,\r
+               0,\r
+               0xFFF,\r
+               0,\r
+               PciBarTypeIo16,\r
+               PciResUsageTypical\r
+               );\r
+\r
+  Mem32Bridge = CreateResourceNode (\r
+                  Bridge,\r
+                  0,\r
+                  0xFFFFF,\r
+                  0,\r
+                  PciBarTypeMem32,\r
+                  PciResUsageTypical\r
+                  );\r
+\r
+  PMem32Bridge = CreateResourceNode (\r
+                   Bridge,\r
+                   0,\r
+                   0xFFFFF,\r
+                   0,\r
+                   PciBarTypePMem32,\r
+                   PciResUsageTypical\r
+                   );\r
+\r
+  Mem64Bridge = CreateResourceNode (\r
+                  Bridge,\r
+                  0,\r
+                  0xFFFFF,\r
+                  0,\r
+                  PciBarTypeMem64,\r
+                  PciResUsageTypical\r
+                  );\r
+\r
+  PMem64Bridge = CreateResourceNode (\r
+                   Bridge,\r
+                   0,\r
+                   0xFFFFF,\r
+                   0,\r
+                   PciBarTypePMem64,\r
+                   PciResUsageTypical\r
+                   );\r
+\r
+  //\r
+  // Create resourcemap by going through all the devices subject to this root bridge\r
+  //\r
+  CreateResourceMap (\r
+    Bridge,\r
+    IoBridge,\r
+    Mem32Bridge,\r
+    PMem32Bridge,\r
+    Mem64Bridge,\r
+    PMem64Bridge\r
+    );\r
+\r
+  Status = GetResourceBaseFromBridge (\r
+             Bridge,\r
+             &IoBase,\r
+             &Mem32Base,\r
+             &PMem32Base,\r
+             &Mem64Base,\r
+             &PMem64Base\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Program IO resources\r
+  //\r
+  ProgramResource (\r
+    IoBase,\r
+    IoBridge\r
+    );\r
+\r
+  //\r
+  // Program Mem32 resources\r
+  //\r
+  ProgramResource (\r
+    Mem32Base,\r
+    Mem32Bridge\r
+    );\r
+\r
+  //\r
+  // Program PMem32 resources\r
+  //\r
+  ProgramResource (\r
+    PMem32Base,\r
+    PMem32Bridge\r
+    );\r
+\r
+  //\r
+  // Program Mem64 resources\r
+  //\r
+  ProgramResource (\r
+    Mem64Base,\r
+    Mem64Bridge\r
+    );\r
+\r
+  //\r
+  // Program PMem64 resources\r
+  //\r
+  ProgramResource (\r
+    PMem64Base,\r
+    PMem64Bridge\r
+    );\r
+\r
+  DestroyResourceTree (IoBridge);\r
+  DestroyResourceTree (Mem32Bridge);\r
+  DestroyResourceTree (PMem32Bridge);\r
+  DestroyResourceTree (PMem64Bridge);\r
+  DestroyResourceTree (Mem64Bridge);\r
+\r
+  gBS->FreePool (IoBridge);\r
+  gBS->FreePool (Mem32Bridge);\r
+  gBS->FreePool (PMem32Bridge);\r
+  gBS->FreePool (PMem64Bridge);\r
+  gBS->FreePool (Mem64Bridge);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get resource base address for a pci bridge device.\r
+\r
+  @param Bridge     Given Pci driver instance.\r
+  @param IoBase     Output for base address of I/O type resource.\r
+  @param Mem32Base  Output for base address of 32-bit memory type resource.\r
+  @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.\r
+  @param Mem64Base  Output for base address of 64-bit memory type resource.\r
+  @param PMem64Base Output for base address of 64-bit Pmemory type resource.\r
+\r
+  @retval EFI_SUCCESS           Successfully got resource base address.\r
+  @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+GetResourceBaseFromBridge (\r
+  IN  PCI_IO_DEVICE *Bridge,\r
+  OUT UINT64        *IoBase,\r
+  OUT UINT64        *Mem32Base,\r
+  OUT UINT64        *PMem32Base,\r
+  OUT UINT64        *Mem64Base,\r
+  OUT UINT64        *PMem64Base\r
+  )\r
+{\r
+  if (!Bridge->Allocated) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  *IoBase     = gAllOne;\r
+  *Mem32Base  = gAllOne;\r
+  *PMem32Base = gAllOne;\r
+  *Mem64Base  = gAllOne;\r
+  *PMem64Base = gAllOne;\r
+\r
+  if (IS_PCI_BRIDGE (&Bridge->Pci)) {\r
+\r
+    if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {\r
+      *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;\r
+    }\r
+\r
+    if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {\r
+      *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;\r
+    }\r
+\r
+    if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {\r
+      *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;\r
+    }\r
+\r
+    if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {\r
+      *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;\r
+    } else {\r
+      *PMem64Base = gAllOne;\r
+    }\r
+\r
+  }\r
+\r
+  if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {\r
+    if (Bridge->PciBar[P2C_IO_1].Length > 0) {\r
+      *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;\r
+    } else {\r
+      if (Bridge->PciBar[P2C_IO_2].Length > 0) {\r
+        *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;\r
+      }\r
+    }\r
+\r
+    if (Bridge->PciBar[P2C_MEM_1].Length > 0) {\r
+      if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {\r
+        *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
+      }\r
+\r
+      if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {\r
+        *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;\r
+      }\r
+    }\r
+\r
+    if (Bridge->PciBar[P2C_MEM_2].Length > 0) {\r
+      if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {\r
+        *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
+      }\r
+\r
+      if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {\r
+        *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+   These are the notifications from the PCI bus driver that it is about to enter a certain\r
+   phase of the PCI enumeration process.\r
+\r
+   This member function can be used to notify the host bridge driver to perform specific actions,\r
+   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
+   Eight notification points are defined at this time. See belows:\r
+   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data\r
+                                          structures. The PCI enumerator should issue this notification\r
+                                          before starting a fresh enumeration process. Enumeration cannot\r
+                                          be restarted after sending any other notification such as\r
+                                          EfiPciHostBridgeBeginBusAllocation.\r
+   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is\r
+                                          required here. This notification can be used to perform any\r
+                                          chipset-specific programming.\r
+   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No\r
+                                          specific action is required here. This notification can be used to\r
+                                          perform any chipset-specific programming.\r
+   EfiPciHostBridgeBeginResourceAllocation\r
+                                          The resource allocation phase is about to begin. No specific\r
+                                          action is required here. This notification can be used to perform\r
+                                          any chipset-specific programming.\r
+   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI\r
+                                          root bridges. These resource settings are returned on the next call to\r
+                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
+                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
+                                          for gathering I/O and memory requests for\r
+                                          all the PCI root bridges and submitting these requests using\r
+                                          SubmitResources(). This function pads the resource amount\r
+                                          to suit the root bridge hardware, takes care of dependencies between\r
+                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
+                                          with the allocation request. In the case of padding, the allocated range\r
+                                          could be bigger than what was requested.\r
+   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated\r
+                                          resources (proposed resources) for all the PCI root bridges. After the\r
+                                          hardware is programmed, reassigning resources will not be supported.\r
+                                          The bus settings are not affected.\r
+   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI\r
+                                          root bridges and resets the I/O and memory apertures to their initial\r
+                                          state. The bus settings are not affected. If the request to allocate\r
+                                          resources fails, the PCI enumerator can use this notification to\r
+                                          deallocate previous resources, adjust the requests, and retry\r
+                                          allocation.\r
+   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is\r
+                                          required here. This notification can be used to perform any chipsetspecific\r
+                                          programming.\r
+\r
+   @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+   @param[in] Phase               The phase during enumeration\r
+\r
+   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error\r
+                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
+                                  SubmitResources() has not been called for one or more\r
+                                  PCI root bridges before this call\r
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid\r
+                                  for a Phase of EfiPciHostBridgeSetResources.\r
+   @retval EFI_INVALID_PARAMETER  Invalid phase parameter\r
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.\r
+                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
+                                  previously submitted resource requests cannot be fulfilled or\r
+                                  were only partially fulfilled.\r
+   @retval EFI_SUCCESS            The notification was accepted without any errors.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyPhase (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase\r
+  )\r
+{\r
+  EFI_HANDLE                      HostBridgeHandle;\r
+  EFI_HANDLE                      RootBridgeHandle;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  EFI_STATUS                      Status;\r
+\r
+  HostBridgeHandle  = NULL;\r
+  RootBridgeHandle  = NULL;\r
+  if (gPciPlatformProtocol != NULL) {\r
+    //\r
+    // Get Host Bridge Handle.\r
+    //\r
+    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
+\r
+    //\r
+    // Get the rootbridge Io protocol to find the host bridge handle\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    RootBridgeHandle,\r
+                    &gEfiPciRootBridgeIoProtocolGuid,\r
+                    (VOID **) &PciRootBridgeIo\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+\r
+    //\r
+    // Call PlatformPci::PlatformNotify() if the protocol is present.\r
+    //\r
+    gPciPlatformProtocol->PlatformNotify (\r
+                            gPciPlatformProtocol,\r
+                            HostBridgeHandle,\r
+                            Phase,\r
+                            ChipsetEntry\r
+                            );\r
+  } else if (gPciOverrideProtocol != NULL){\r
+    //\r
+    // Get Host Bridge Handle.\r
+    //\r
+    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);\r
+\r
+    //\r
+    // Get the rootbridge Io protocol to find the host bridge handle\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    RootBridgeHandle,\r
+                    &gEfiPciRootBridgeIoProtocolGuid,\r
+                    (VOID **) &PciRootBridgeIo\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+\r
+    //\r
+    // Call PlatformPci::PhaseNotify() if the protocol is present.\r
+    //\r
+    gPciOverrideProtocol->PlatformNotify (\r
+                            gPciOverrideProtocol,\r
+                            HostBridgeHandle,\r
+                            Phase,\r
+                            ChipsetEntry\r
+                            );\r
+  }  \r
+\r
+  Status = PciResAlloc->NotifyPhase (\r
+                          PciResAlloc,\r
+                          Phase\r
+                          );\r
+\r
+  if (gPciPlatformProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PlatformNotify() if the protocol is present.\r
+    //\r
+    gPciPlatformProtocol->PlatformNotify (\r
+                            gPciPlatformProtocol,\r
+                            HostBridgeHandle,\r
+                            Phase,\r
+                            ChipsetExit\r
+                            );\r
+\r
+  } else if (gPciOverrideProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PhaseNotify() if the protocol is present.\r
+    //\r
+    gPciOverrideProtocol->PlatformNotify (\r
+                            gPciOverrideProtocol,\r
+                            HostBridgeHandle,\r
+                            Phase,\r
+                            ChipsetExit\r
+                            );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
+  PCI controllers before enumeration.\r
+\r
+  This function is called during the PCI enumeration process. No specific action is expected from this\r
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
+  enumeration.\r
+\r
+  @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+  @param Bus               The bus number of the pci device.\r
+  @param Device            The device number of the pci device.\r
+  @param Func              The function number of the pci device.\r
+  @param Phase             The phase of the PCI device enumeration.\r
+\r
+  @retval EFI_SUCCESS              The requested parameters were returned.\r
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.\r
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in\r
+                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should\r
+                                   not enumerate this device, including its child devices if it is a PCI-to-PCI\r
+                                   bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PreprocessController (\r
+  IN PCI_IO_DEVICE                                    *Bridge,\r
+  IN UINT8                                            Bus,\r
+  IN UINT8                                            Device,\r
+  IN UINT8                                            Func,\r
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase\r
+  )\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;\r
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;\r
+  EFI_HANDLE                                        RootBridgeHandle;\r
+  EFI_HANDLE                                        HostBridgeHandle;\r
+  EFI_STATUS                                        Status;\r
+\r
+  //\r
+  // Get the host bridge handle\r
+  //\r
+  HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;\r
+\r
+  //\r
+  // Get the pci host bridge resource allocation protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  HostBridgeHandle,\r
+                  &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
+                  (VOID **) &PciResAlloc,\r
+                  NULL,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get Root Brige Handle\r
+  //\r
+  while (Bridge->Parent != NULL) {\r
+    Bridge = Bridge->Parent;\r
+  }\r
+\r
+  RootBridgeHandle                      = Bridge->Handle;\r
+\r
+  RootBridgePciAddress.Register         = 0;\r
+  RootBridgePciAddress.Function         = Func;\r
+  RootBridgePciAddress.Device           = Device;\r
+  RootBridgePciAddress.Bus              = Bus;\r
+  RootBridgePciAddress.ExtendedRegister = 0;\r
+\r
+  if (gPciPlatformProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PrepController() if the protocol is present.\r
+    //\r
+    gPciPlatformProtocol->PlatformPrepController (\r
+                            gPciPlatformProtocol,\r
+                            HostBridgeHandle,\r
+                            RootBridgeHandle,\r
+                            RootBridgePciAddress,\r
+                            Phase,\r
+                            ChipsetEntry\r
+                            );\r
+  } else if (gPciOverrideProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PrepController() if the protocol is present.\r
+    //\r
+    gPciOverrideProtocol->PlatformPrepController (\r
+                            gPciOverrideProtocol,\r
+                            HostBridgeHandle,\r
+                            RootBridgeHandle,\r
+                            RootBridgePciAddress,\r
+                            Phase,\r
+                            ChipsetEntry\r
+                            );\r
+  }\r
+\r
+  Status = PciResAlloc->PreprocessController (\r
+                          PciResAlloc,\r
+                          RootBridgeHandle,\r
+                          RootBridgePciAddress,\r
+                          Phase\r
+                          );\r
+\r
+  if (gPciPlatformProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PrepController() if the protocol is present.\r
+    //\r
+    gPciPlatformProtocol->PlatformPrepController (\r
+                            gPciPlatformProtocol,\r
+                            HostBridgeHandle,\r
+                            RootBridgeHandle,\r
+                            RootBridgePciAddress,\r
+                            Phase,\r
+                            ChipsetExit\r
+                            );\r
+  } else if (gPciOverrideProtocol != NULL) {\r
+    //\r
+    // Call PlatformPci::PrepController() if the protocol is present.\r
+    //\r
+    gPciOverrideProtocol->PlatformPrepController (\r
+                            gPciOverrideProtocol,\r
+                            HostBridgeHandle,\r
+                            RootBridgeHandle,\r
+                            RootBridgePciAddress,\r
+                            Phase,\r
+                            ChipsetExit\r
+                            );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has\r
+  happened on the hot-plug controller. Currently, the operations include add operation and remove operation..\r
+\r
+  @param This                 A pointer to the hot plug request protocol.\r
+  @param Operation            The operation the PCI bus driver is requested to make.\r
+  @param Controller           The handle of the hot-plug controller.\r
+  @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.\r
+  @param NumberOfChildren     The number of child handles.\r
+                              For a add operation, it is an output parameter.\r
+                              For a remove operation, it's an input parameter.\r
+  @param ChildHandleBuffer    The buffer which contains the child handles.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Operation is not a legal value.\r
+                                 Controller is NULL or not a valid handle.\r
+                                 NumberOfChildren is NULL.\r
+                                 ChildHandleBuffer is NULL while Operation is add.\r
+  @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.\r
+  @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.\r
+  @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed\r
+                                 as requested, and for an add operation, the new handles are\r
+                                 returned in ChildHandleBuffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciHotPlugRequestNotify (\r
+  IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
+  IN EFI_PCI_HOTPLUG_OPERATION        Operation,\r
+  IN EFI_HANDLE                       Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,\r
+  IN OUT UINT8                        *NumberOfChildren,\r
+  IN OUT EFI_HANDLE                   * ChildHandleBuffer\r
+  )\r
+{\r
+  PCI_IO_DEVICE       *Bridge;\r
+  PCI_IO_DEVICE       *Temp;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINTN               Index;\r
+  EFI_HANDLE          RootBridgeHandle;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Check input parameter validity\r
+  //\r
+  if ((Controller == NULL) || (NumberOfChildren == NULL)){\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Operation == EfiPciHotPlugRequestAdd){\r
+    if (ChildHandleBuffer == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {\r
+    if (ChildHandleBuffer == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
+\r
+  //\r
+  // Get root bridge handle\r
+  //\r
+  Temp = Bridge;\r
+  while (Temp->Parent != NULL) {\r
+    Temp = Temp->Parent;\r
+  }\r
+\r
+  RootBridgeHandle = Temp->Handle;\r
+\r
+  if (Operation == EfiPciHotPlugRequestAdd) {\r
+\r
+    if (NumberOfChildren != NULL) {\r
+      *NumberOfChildren = 0;\r
+    }\r
+\r
+    if (IsListEmpty (&Bridge->ChildList)) {\r
+\r
+      Status = PciBridgeEnumerator (Bridge);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    Status = StartPciDevicesOnBridge (\r
+              RootBridgeHandle,\r
+              Bridge,\r
+              RemainingDevicePath,\r
+              NumberOfChildren,\r
+              ChildHandleBuffer\r
+              );\r
+\r
+    return Status;\r
+  }\r
+\r
+  if (Operation == EfiPciHotplugRequestRemove) {\r
+\r
+    if (*NumberOfChildren == 0) {\r
+      //\r
+      // Remove all devices on the bridge\r
+      //\r
+      RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);\r
+      return EFI_SUCCESS;\r
+\r
+    }\r
+\r
+    for (Index = 0; Index < *NumberOfChildren; Index++) {\r
+      //\r
+      // De register all the pci device\r
+      //\r
+      Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+    }\r
+    //\r
+    // End for\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Search hostbridge according to given handle\r
+\r
+  @param RootBridgeHandle  Host bridge handle.\r
+\r
+  @retval TRUE             Found host bridge handle.\r
+  @retval FALSE            Not found hot bridge handle.\r
+\r
+**/\r
+BOOLEAN\r
+SearchHostBridgeHandle (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  )\r
+{\r
+  EFI_HANDLE                      HostBridgeHandle;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+\r
+  //\r
+  // Get the rootbridge Io protocol to find the host bridge handle\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  RootBridgeHandle,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  RootBridgeHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  HostBridgeHandle = PciRootBridgeIo->ParentHandle;\r
+  for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
+    if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Add host bridge handle to global variable for enumerating.\r
+\r
+  @param HostBridgeHandle   Host bridge handle.\r
+\r
+  @retval EFI_SUCCESS       Successfully added host bridge.\r
+  @retval EFI_ABORTED       Host bridge is NULL, or given host bridge\r
+                            has been in host bridge list.\r
+\r
+**/\r
+EFI_STATUS\r
+AddHostBridgeEnumerator (\r
+  IN EFI_HANDLE HostBridgeHandle\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  if (HostBridgeHandle == NULL) {\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  for (Index = 0; Index < gPciHostBridgeNumber; Index++) {\r
+    if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+\r
+  if (Index < PCI_MAX_HOST_BRIDGE_NUM) {\r
+    gPciHostBrigeHandles[Index] = HostBridgeHandle;\r
+    gPciHostBridgeNumber++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.h
new file mode 100644 (file)
index 0000000..3c0ca2f
--- /dev/null
@@ -0,0 +1,519 @@
+/** @file\r
+  PCI bus enumeration logic function declaration for PCI bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_H_\r
+#define _EFI_PCI_ENUMERATOR_H_\r
+\r
+#include "PciResourceSupport.h"\r
+\r
+/**\r
+  This routine is used to enumerate entire pci bus system\r
+  in a given platform.\r
+\r
+  @param Controller  Parent controller handle.\r
+\r
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.\r
+  @retval other          Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumerator (\r
+  IN EFI_HANDLE                    Controller\r
+  );\r
+\r
+/**\r
+  Enumerate PCI root bridge.\r
+\r
+  @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+  @param RootBridgeDev Instance of root bridge device.\r
+\r
+  @retval EFI_SUCCESS  Successfully enumerated root bridge.\r
+  @retval other        Failed to enumerate root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeEnumerator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,\r
+  IN PCI_IO_DEVICE                                     *RootBridgeDev\r
+  );\r
+\r
+/**\r
+  This routine is used to process all PCI devices' Option Rom\r
+  on a certain root bridge.\r
+\r
+  @param Bridge     Given parent's root bridge.\r
+  @param RomBase    Base address of ROM driver loaded from.\r
+  @param MaxLength  Maximum rom size.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRom (\r
+  IN PCI_IO_DEVICE *Bridge,\r
+  IN UINT64        RomBase,\r
+  IN UINT64        MaxLength\r
+  );\r
+\r
+/**\r
+  This routine is used to assign bus number to the given PCI bus system\r
+\r
+  @param Bridge             Parent root bridge instance.\r
+  @param StartBusNumber     Number of beginning.\r
+  @param SubBusNumber       The number of sub bus.\r
+\r
+  @retval EFI_SUCCESS       Successfully assigned bus number.\r
+  @retval EFI_DEVICE_ERROR  Failed to assign bus number.\r
+\r
+**/\r
+EFI_STATUS\r
+PciAssignBusNumber (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber,\r
+  OUT UINT8                             *SubBusNumber\r
+  );\r
+\r
+/**\r
+  This routine is used to determine the root bridge attribute by interfacing\r
+  the host bridge resource allocation protocol.\r
+\r
+  @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+  @param RootBridgeDev  Root bridge instance\r
+\r
+  @retval EFI_SUCCESS  Successfully got root bridge's attribute.\r
+  @retval other        Failed to get attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineRootBridgeAttributes (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+  IN PCI_IO_DEVICE                                    *RootBridgeDev\r
+  );\r
+\r
+/**\r
+  Get Max Option Rom size on specified bridge.\r
+\r
+  @param Bridge    Given bridge device instance.\r
+\r
+  @return Max size of option rom needed.\r
+\r
+**/\r
+UINT64\r
+GetMaxOptionRomSize (\r
+  IN PCI_IO_DEVICE   *Bridge\r
+  );\r
+\r
+/**\r
+  Process attributes of devices on this host bridge\r
+\r
+  @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS   Successfully process attribute.\r
+  @retval EFI_NOT_FOUND Can not find the specific root bridge device.\r
+  @retval other         Failed to determine the root bridge device's attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeDeviceAttribute (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  );\r
+\r
+/**\r
+  Get resource allocation status from the ACPI resource descriptor.\r
+\r
+  @param AcpiConfig       Point to Acpi configuration table.\r
+  @param IoResStatus      Return the status of I/O resource.\r
+  @param Mem32ResStatus   Return the status of 32-bit Memory resource.\r
+  @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.\r
+  @param Mem64ResStatus   Return the status of 64-bit Memory resource.\r
+  @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.\r
+\r
+**/\r
+VOID\r
+GetResourceAllocationStatus (\r
+  VOID        *AcpiConfig,\r
+  OUT UINT64  *IoResStatus,\r
+  OUT UINT64  *Mem32ResStatus,\r
+  OUT UINT64  *PMem32ResStatus,\r
+  OUT UINT64  *Mem64ResStatus,\r
+  OUT UINT64  *PMem64ResStatus\r
+  );\r
+\r
+/**\r
+  Remove a PCI device from device pool and mark its bar.\r
+\r
+  @param PciDevice Instance of Pci device.\r
+\r
+  @retval EFI_SUCCESS Successfully remove the PCI device.\r
+  @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+RejectPciDevice (\r
+  IN PCI_IO_DEVICE       *PciDevice\r
+  );\r
+\r
+/**\r
+  Determine whethter a PCI device can be rejected.\r
+\r
+  @param  PciResNode Pointer to Pci resource node instance.\r
+\r
+  @retval TRUE  The PCI device can be rejected.\r
+  @retval TRUE  The PCI device cannot be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsRejectiveDevice (\r
+  IN  PCI_RESOURCE_NODE   *PciResNode\r
+  );\r
+\r
+/**\r
+  Compare two resource nodes and get the larger resource consumer.\r
+\r
+  @param PciResNode1  resource node 1 want to be compared\r
+  @param PciResNode2  resource node 2 want to be compared\r
+\r
+  @return Larger resource node.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetLargerConsumerDevice (\r
+  IN  PCI_RESOURCE_NODE   *PciResNode1,\r
+  IN  PCI_RESOURCE_NODE   *PciResNode2\r
+  );\r
+\r
+/**\r
+  Get the max resource consumer in the host resource pool.\r
+\r
+  @param ResPool  Pointer to resource pool node.\r
+\r
+  @return The max resource consumer in the host resource pool.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+GetMaxResourceConsumerDevice (\r
+  IN  PCI_RESOURCE_NODE   *ResPool\r
+  );\r
+\r
+/**\r
+  Adjust host bridge allocation so as to reduce resource requirement\r
+\r
+  @param IoPool           Pointer to instance of I/O resource Node.\r
+  @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.\r
+  @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.\r
+  @param Mem64Pool        Pointer to instance of 64-bit memory resource node.\r
+  @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.\r
+  @param IoResStatus      Status of I/O resource Node.\r
+  @param Mem32ResStatus   Status of 32-bit memory resource Node.\r
+  @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.\r
+  @param Mem64ResStatus   Status of 64-bit memory resource node.\r
+  @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.\r
+\r
+  @retval EFI_SUCCESS     Successfully adjusted resoruce on host bridge.\r
+  @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeAdjustAllocation (\r
+  IN  PCI_RESOURCE_NODE   *IoPool,\r
+  IN  PCI_RESOURCE_NODE   *Mem32Pool,\r
+  IN  PCI_RESOURCE_NODE   *PMem32Pool,\r
+  IN  PCI_RESOURCE_NODE   *Mem64Pool,\r
+  IN  PCI_RESOURCE_NODE   *PMem64Pool,\r
+  IN  UINT64              IoResStatus,\r
+  IN  UINT64              Mem32ResStatus,\r
+  IN  UINT64              PMem32ResStatus,\r
+  IN  UINT64              Mem64ResStatus,\r
+  IN  UINT64              PMem64ResStatus\r
+  );\r
+\r
+/**\r
+  Summary requests for all resource type, and contruct ACPI resource\r
+  requestor instance.\r
+\r
+  @param Bridge           detecting bridge\r
+  @param IoNode           Pointer to instance of I/O resource Node\r
+  @param Mem32Node        Pointer to instance of 32-bit memory resource Node\r
+  @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node\r
+  @param Mem64Node        Pointer to instance of 64-bit memory resource node\r
+  @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node\r
+  @param Config           Output buffer holding new constructed APCI resource requestor\r
+\r
+  @retval EFI_SUCCESS           Successfully constructed ACPI resource.\r
+  @retval EFI_OUT_OF_RESOURCES  No memory availabe.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructAcpiResourceRequestor (\r
+  IN PCI_IO_DEVICE      *Bridge,\r
+  IN PCI_RESOURCE_NODE  *IoNode,\r
+  IN PCI_RESOURCE_NODE  *Mem32Node,\r
+  IN PCI_RESOURCE_NODE  *PMem32Node,\r
+  IN PCI_RESOURCE_NODE  *Mem64Node,\r
+  IN PCI_RESOURCE_NODE  *PMem64Node,\r
+  OUT VOID              **Config\r
+  );\r
+\r
+/**\r
+  Get resource base from an acpi configuration descriptor.\r
+\r
+  @param Config       An acpi configuration descriptor.\r
+  @param IoBase       Output of I/O resource base address.\r
+  @param Mem32Base    Output of 32-bit memory base address.\r
+  @param PMem32Base   Output of 32-bit prefetchable memory base address.\r
+  @param Mem64Base    Output of 64-bit memory base address.\r
+  @param PMem64Base   Output of 64-bit prefetchable memory base address.\r
+\r
+**/\r
+VOID\r
+GetResourceBase (\r
+  IN VOID     *Config,\r
+  OUT UINT64  *IoBase,\r
+  OUT UINT64  *Mem32Base,\r
+  OUT UINT64  *PMem32Base,\r
+  OUT UINT64  *Mem64Base,\r
+  OUT UINT64  *PMem64Base\r
+  );\r
+\r
+/**\r
+  Enumerate pci bridge, allocate resource and determine attribute\r
+  for devices on this bridge.\r
+\r
+  @param BridgeDev    Pointer to instance of bridge device.\r
+\r
+  @retval EFI_SUCCESS Successfully enumerated PCI bridge.\r
+  @retval other       Failed to enumerate.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeEnumerator (\r
+  IN PCI_IO_DEVICE                                     *BridgeDev\r
+  );\r
+\r
+/**\r
+  Allocate all kinds of resource for PCI bridge.\r
+\r
+  @param  Bridge      Pointer to bridge instance.\r
+\r
+  @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.\r
+  @retval other       Failed to allocate resource for bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciBridgeResourceAllocator (\r
+  IN PCI_IO_DEVICE  *Bridge\r
+  );\r
+\r
+/**\r
+  Get resource base address for a pci bridge device.\r
+\r
+  @param Bridge     Given Pci driver instance.\r
+  @param IoBase     Output for base address of I/O type resource.\r
+  @param Mem32Base  Output for base address of 32-bit memory type resource.\r
+  @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.\r
+  @param Mem64Base  Output for base address of 64-bit memory type resource.\r
+  @param PMem64Base Output for base address of 64-bit Pmemory type resource.\r
+\r
+  @retval EFI_SUCCESS           Successfully got resource base address.\r
+  @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+GetResourceBaseFromBridge (\r
+  IN  PCI_IO_DEVICE *Bridge,\r
+  OUT UINT64        *IoBase,\r
+  OUT UINT64        *Mem32Base,\r
+  OUT UINT64        *PMem32Base,\r
+  OUT UINT64        *Mem64Base,\r
+  OUT UINT64        *PMem64Base\r
+  );\r
+\r
+/**\r
+  Process Option Rom on this host bridge\r
+\r
+  @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+  @retval EFI_SUCCESS   Success process.\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  );\r
+\r
+/**\r
+   These are the notifications from the PCI bus driver that it is about to enter a certain\r
+   phase of the PCI enumeration process.\r
+\r
+   This member function can be used to notify the host bridge driver to perform specific actions,\r
+   including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
+   Eight notification points are defined at this time. See belows:\r
+   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data\r
+                                          structures. The PCI enumerator should issue this notification\r
+                                          before starting a fresh enumeration process. Enumeration cannot\r
+                                          be restarted after sending any other notification such as\r
+                                          EfiPciHostBridgeBeginBusAllocation.\r
+   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is\r
+                                          required here. This notification can be used to perform any\r
+                                          chipset-specific programming.\r
+   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No\r
+                                          specific action is required here. This notification can be used to\r
+                                          perform any chipset-specific programming.\r
+   EfiPciHostBridgeBeginResourceAllocation\r
+                                          The resource allocation phase is about to begin. No specific\r
+                                          action is required here. This notification can be used to perform\r
+                                          any chipset-specific programming.\r
+   EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI\r
+                                          root bridges. These resource settings are returned on the next call to\r
+                                          GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
+                                          EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
+                                          for gathering I/O and memory requests for\r
+                                          all the PCI root bridges and submitting these requests using\r
+                                          SubmitResources(). This function pads the resource amount\r
+                                          to suit the root bridge hardware, takes care of dependencies between\r
+                                          the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
+                                          with the allocation request. In the case of padding, the allocated range\r
+                                          could be bigger than what was requested.\r
+   EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated\r
+                                          resources (proposed resources) for all the PCI root bridges. After the\r
+                                          hardware is programmed, reassigning resources will not be supported.\r
+                                          The bus settings are not affected.\r
+   EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI\r
+                                          root bridges and resets the I/O and memory apertures to their initial\r
+                                          state. The bus settings are not affected. If the request to allocate\r
+                                          resources fails, the PCI enumerator can use this notification to\r
+                                          deallocate previous resources, adjust the requests, and retry\r
+                                          allocation.\r
+   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is\r
+                                          required here. This notification can be used to perform any chipsetspecific\r
+                                          programming.\r
+\r
+   @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+   @param[in] Phase               The phase during enumeration\r
+\r
+   @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error\r
+                                  is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
+                                  SubmitResources() has not been called for one or more\r
+                                  PCI root bridges before this call\r
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid\r
+                                  for a Phase of EfiPciHostBridgeSetResources.\r
+   @retval EFI_INVALID_PARAMETER  Invalid phase parameter\r
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.\r
+                                  This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
+                                  previously submitted resource requests cannot be fulfilled or\r
+                                  were only partially fulfilled.\r
+   @retval EFI_SUCCESS            The notification was accepted without any errors.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyPhase (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,\r
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase\r
+  );\r
+\r
+/**\r
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
+  PCI controllers before enumeration.\r
+\r
+  This function is called during the PCI enumeration process. No specific action is expected from this\r
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
+  enumeration.\r
+\r
+  @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
+  @param Bus               The bus number of the pci device.\r
+  @param Device            The device number of the pci device.\r
+  @param Func              The function number of the pci device.\r
+  @param Phase             The phase of the PCI device enumeration.\r
+\r
+  @retval EFI_SUCCESS              The requested parameters were returned.\r
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.\r
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in\r
+                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should\r
+                                    not enumerate this device, including its child devices if it is a PCI-to-PCI\r
+                                    bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PreprocessController (\r
+  IN PCI_IO_DEVICE                                  *Bridge,\r
+  IN UINT8                                          Bus,\r
+  IN UINT8                                          Device,\r
+  IN UINT8                                          Func,\r
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE   Phase\r
+  );\r
+\r
+/**\r
+  This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has\r
+  happened on the hot-plug controller. Currently, the operations include add operation and remove operation..\r
+\r
+  @param This                 A pointer to the hot plug request protocol.\r
+  @param Operation            The operation the PCI bus driver is requested to make.\r
+  @param Controller           The handle of the hot-plug controller.\r
+  @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.\r
+  @param NumberOfChildren     The number of child handles.\r
+                              For a add operation, it is an output parameter.\r
+                              For a remove operation, it's an input parameter.\r
+  @param ChildHandleBuffer    The buffer which contains the child handles.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Operation is not a legal value.\r
+                                 Controller is NULL or not a valid handle.\r
+                                 NumberOfChildren is NULL.\r
+                                 ChildHandleBuffer is NULL while Operation is add.\r
+  @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.\r
+  @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.\r
+  @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed\r
+                                 as requested, and for an add operation, the new handles are\r
+                                 returned in ChildHandleBuffer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciHotPlugRequestNotify (\r
+  IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,\r
+  IN EFI_PCI_HOTPLUG_OPERATION        Operation,\r
+  IN EFI_HANDLE                       Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,\r
+  IN OUT UINT8                        *NumberOfChildren,\r
+  IN OUT EFI_HANDLE                   * ChildHandleBuffer\r
+  );\r
+\r
+/**\r
+  Search hostbridge according to given handle\r
+\r
+  @param RootBridgeHandle  Host bridge handle.\r
+\r
+  @retval TRUE             Found host bridge handle.\r
+  @retval FALSE            Not found hot bridge handle.\r
+\r
+**/\r
+BOOLEAN\r
+SearchHostBridgeHandle (\r
+  IN EFI_HANDLE RootBridgeHandle\r
+  );\r
+\r
+/**\r
+  Add host bridge handle to global variable for enumerating.\r
+\r
+  @param HostBridgeHandle   Host bridge handle.\r
+\r
+  @retval EFI_SUCCESS       Successfully added host bridge.\r
+  @retval EFI_ABORTED       Host bridge is NULL, or given host bridge\r
+                            has been in host bridge list.\r
+\r
+**/\r
+EFI_STATUS\r
+AddHostBridgeEnumerator (\r
+  IN EFI_HANDLE HostBridgeHandle\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
new file mode 100644 (file)
index 0000000..8f3ed5e
--- /dev/null
@@ -0,0 +1,2494 @@
+/** @file\r
+  PCI emumeration support functions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  This routine is used to check whether the pci device is present.\r
+\r
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+  @param Pci               Output buffer for PCI device configuration space.\r
+  @param Bus               PCI bus NO.\r
+  @param Device            PCI device NO.\r
+  @param Func              PCI Func NO.\r
+\r
+  @retval EFI_NOT_FOUND    PCI device not present.\r
+  @retval EFI_SUCCESS      PCI device is found.\r
+\r
+**/\r
+EFI_STATUS\r
+PciDevicePresent (\r
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,\r
+  OUT PCI_TYPE00                          *Pci,\r
+  IN  UINT8                               Bus,\r
+  IN  UINT8                               Device,\r
+  IN  UINT8                               Func\r
+  )\r
+{\r
+  UINT64      Address;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Create PCI address map in terms of Bus, Device and Func\r
+  //\r
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+  //\r
+  // Read the Vendor ID register\r
+  //\r
+  Status = PciRootBridgeIo->Pci.Read (\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  Pci\r
+                                  );\r
+\r
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
+    //\r
+    // Read the entire config header for the device\r
+    //\r
+    Status = PciRootBridgeIo->Pci.Read (\r
+                                    PciRootBridgeIo,\r
+                                    EfiPciWidthUint32,\r
+                                    Address,\r
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),\r
+                                    Pci\r
+                                    );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Collect all the resource information under this root bridge.\r
+\r
+  A database that records all the information about pci device subject to this\r
+  root bridge will then be created.\r
+\r
+  @param Bridge         Parent bridge instance.\r
+  @param StartBusNumber Bus number of begining.\r
+\r
+  @retval EFI_SUCCESS   PCI device is found.\r
+  @retval other         Some error occurred when reading PCI bridge information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  PCI_TYPE00          Pci;\r
+  UINT8               Device;\r
+  UINT8               Func;\r
+  UINT8               SecBus;\r
+  PCI_IO_DEVICE       *PciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  SecBus  = 0;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether PCI device is present\r
+      //\r
+      Status = PciDevicePresent (\r
+                 Bridge->PciRootBridgeIo,\r
+                 &Pci,\r
+                 (UINT8) StartBusNumber,\r
+                 (UINT8) Device,\r
+                 (UINT8) Func\r
+                 );\r
+      if (!EFI_ERROR (Status)) {\r
+\r
+        //\r
+        // Call back to host bridge function\r
+        //\r
+        PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);\r
+\r
+        //\r
+        // Collect all the information about the PCI device discovered\r
+        //\r
+        Status = PciSearchDevice (\r
+                   Bridge,\r
+                   &Pci,\r
+                   (UINT8) StartBusNumber,\r
+                   Device,\r
+                   Func,\r
+                   &PciIoDevice\r
+                   );\r
+\r
+        //\r
+        // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
+        //\r
+        //\r
+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
+\r
+          //\r
+          // If it is PPB, we need to get the secondary bus to continue the enumeration\r
+          //\r
+          PciIo   = &(PciIoDevice->PciIo);\r
+\r
+          Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          //\r
+          // Get resource padding for PPB\r
+          //\r
+          GetResourcePaddingPpb (PciIoDevice);\r
+\r
+          //\r
+          // Deep enumerate the next level bus\r
+          //\r
+          Status = PciPciDeviceInfoCollector (\r
+                     PciIoDevice,\r
+                     (UINT8) (SecBus)\r
+                     );\r
+\r
+        }\r
+\r
+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+          //\r
+          // Skip sub functions, this is not a multi function device\r
+          //\r
+          Func = PCI_MAX_FUNC;\r
+        }\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Seach required device and create PCI device instance.\r
+\r
+  @param Bridge     Parent bridge instance.\r
+  @param Pci        Input PCI device information block.\r
+  @param Bus        PCI bus NO.\r
+  @param Device     PCI device NO.\r
+  @param Func       PCI func  NO.\r
+  @param PciDevice  Output of searched PCI device instance.\r
+\r
+  @retval EFI_SUCCESS           Successfully created PCI device instance.\r
+  @retval EFI_OUT_OF_RESOURCES  Cannot get PCI device information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciSearchDevice (\r
+  IN  PCI_IO_DEVICE                         *Bridge,\r
+  IN  PCI_TYPE00                            *Pci,\r
+  IN  UINT8                                 Bus,\r
+  IN  UINT8                                 Device,\r
+  IN  UINT8                                 Func,\r
+  OUT PCI_IO_DEVICE                         **PciDevice\r
+  )\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = NULL;\r
+\r
+  if (!IS_PCI_BRIDGE (Pci)) {\r
+\r
+    if (IS_CARDBUS_BRIDGE (Pci)) {\r
+      PciIoDevice = GatherP2CInfo (\r
+                      Bridge,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+      if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+        InitializeP2C (PciIoDevice);\r
+      }\r
+    } else {\r
+\r
+      //\r
+      // Create private data for Pci Device\r
+      //\r
+      PciIoDevice = GatherDeviceInfo (\r
+                      Bridge,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+\r
+    }\r
+\r
+  } else {\r
+\r
+    //\r
+    // Create private data for PPB\r
+    //\r
+    PciIoDevice = GatherPpbInfo (\r
+                    Bridge,\r
+                    Pci,\r
+                    Bus,\r
+                    Device,\r
+                    Func\r
+                    );\r
+\r
+    //\r
+    // Special initialization for PPB including making the PPB quiet\r
+    //\r
+    if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+      InitializePpb (PciIoDevice);\r
+    }\r
+  }\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Update the bar information for this PCI device so as to support some specific device\r
+  //\r
+  UpdatePciInfo (PciIoDevice);\r
+\r
+  if (PciIoDevice->DevicePath == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Detect this function has option rom\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    if (!IS_CARDBUS_BRIDGE (Pci)) {\r
+\r
+      GetOpRomInfo (PciIoDevice);\r
+\r
+    }\r
+\r
+    ResetPowerManagementFeature (PciIoDevice);\r
+\r
+  }\r
+\r
+  //\r
+  // Insert it into a global tree for future reference\r
+  //\r
+  InsertPciDevice (Bridge, PciIoDevice);\r
+\r
+  //\r
+  // Determine PCI device attributes\r
+  //\r
+\r
+  if (PciDevice != NULL) {\r
+    *PciDevice = PciIoDevice;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create PCI device instance for PCI device.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  )\r
+{\r
+  UINTN                           Offset;\r
+  UINTN                           BarIndex;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  //\r
+  // If it is a full enumeration, disconnect the device in advance\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+  }\r
+\r
+  //\r
+  // Start to parse the bars\r
+  //\r
+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
+  }\r
+\r
+  //\r
+  // Parse the SR-IOV VF bars\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+    for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;\r
+         Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;\r
+         BarIndex++) {\r
+\r
+      ASSERT (BarIndex < PCI_MAX_BAR);\r
+      Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
+    }\r
+  }\r
+  return PciIoDevice;\r
+}\r
+\r
+/**\r
+  Create PCI device instance for PCI-PCI bridge.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherPpbInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  )\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           Value;\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  UINT8                           Temp;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  if (gFullEnumeration) {\r
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
+\r
+  }\r
+\r
+  //\r
+  // PPB can have two BARs\r
+  //\r
+  if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {\r
+    //\r
+    // Not 64-bit bar\r
+    //\r
+    PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);\r
+  }\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Test whether it support 32 decode or not\r
+  //\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+\r
+  if (Value != 0) {\r
+    if ((Value & 0x01) != 0) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  Status = BarExisted (\r
+            PciIoDevice,\r
+            0x24,\r
+            NULL,\r
+            NULL\r
+            );\r
+\r
+  //\r
+  // Test if it supports 64 memory or not\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    Status = BarExisted (\r
+              PciIoDevice,\r
+              0x28,\r
+              NULL,\r
+              NULL\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Memory 32 code is required for ppb\r
+  //\r
+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+\r
+  GetResourcePaddingPpb (PciIoDevice);\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+\r
+/**\r
+  Create PCI device instance for PCI Card bridge device.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  )\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  if (gFullEnumeration) {\r
+    PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
+  }\r
+\r
+  //\r
+  // P2C only has one bar that is in 0x10\r
+  //\r
+  PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);\r
+\r
+  //\r
+  // Read PciBar information from the bar register\r
+  //\r
+  GetBackPcCardBar (PciIoDevice);\r
+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |\r
+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+/**\r
+  Create device path for pci deivce.\r
+\r
+  @param ParentDevicePath  Parent bridge's path.\r
+  @param PciIoDevice       Pci device instance.\r
+\r
+  @return Device path protocol instance for specific pci device.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+  IN  PCI_IO_DEVICE            *PciIoDevice\r
+  )\r
+{\r
+\r
+  PCI_DEVICE_PATH PciNode;\r
+\r
+  //\r
+  // Create PCI device path\r
+  //\r
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
+  PciNode.Header.SubType  = HW_PCI_DP;\r
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+\r
+  PciNode.Device          = PciIoDevice->DeviceNumber;\r
+  PciNode.Function        = PciIoDevice->FunctionNumber;\r
+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
+\r
+  return PciIoDevice->DevicePath;\r
+}\r
+\r
+/**\r
+  Check whether the PCI IOV VF bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT32              OriginalValue;\r
+  UINT32              Value;\r
+  EFI_TPL             OldTpl;\r
+\r
+  //\r
+  // Ensure it is called properly\r
+  //\r
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (BarLengthValue != NULL) {\r
+    *BarLengthValue = Value;\r
+  }\r
+\r
+  if (OriginalBarValue != NULL) {\r
+    *OriginalBarValue = OriginalValue;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+/**\r
+  Check whether the bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+BarExisted (\r
+  IN  PCI_IO_DEVICE *PciIoDevice,\r
+  IN  UINTN         Offset,\r
+  OUT UINT32        *BarLengthValue,\r
+  OUT UINT32        *OriginalBarValue\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT32              OriginalValue;\r
+  UINT32              Value;\r
+  EFI_TPL             OldTpl;\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (BarLengthValue != NULL) {\r
+    *BarLengthValue = Value;\r
+  }\r
+\r
+  if (OriginalBarValue != NULL) {\r
+    *OriginalBarValue = OriginalValue;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+/**\r
+  Test whether the device can support given attributes.\r
+\r
+  @param PciIoDevice      Pci device instance.\r
+  @param Command          Input command register value, and\r
+                          returned supported register value.\r
+  @param BridgeControl    Inout bridge control value for PPB or P2C, and\r
+                          returned supported bridge control value.\r
+  @param OldCommand       Returned and stored old command register offset.\r
+  @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.\r
+\r
+**/\r
+VOID\r
+PciTestSupportedAttribute (\r
+  IN     PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN OUT UINT16                             *Command,\r
+  IN OUT UINT16                             *BridgeControl,\r
+     OUT UINT16                             *OldCommand,\r
+     OUT UINT16                             *OldBridgeControl\r
+  )\r
+{\r
+  EFI_TPL OldTpl;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+  PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);\r
+  PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+    //\r
+    // Preserve the original value\r
+    //\r
+    PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);\r
+\r
+    //\r
+    // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+    //\r
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+    PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);\r
+    PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+\r
+    //\r
+    // Write back the original value\r
+    //\r
+    PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);\r
+\r
+    //\r
+    // Restore TPL to its original level\r
+    //\r
+    gBS->RestoreTPL (OldTpl);\r
+\r
+  } else {\r
+    *OldBridgeControl = 0;\r
+    *BridgeControl    = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Set the supported or current attributes of a PCI device.\r
+\r
+  @param PciIoDevice    Structure pointer for PCI device.\r
+  @param Command        Command register value.\r
+  @param BridgeControl  Bridge control value for PPB or P2C.\r
+  @param Option         Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
+\r
+**/\r
+VOID\r
+PciSetDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT16                             Command,\r
+  IN UINT16                             BridgeControl,\r
+  IN UINTN                              Option\r
+  )\r
+{\r
+  UINT64  Attributes;\r
+\r
+  Attributes = 0;\r
+\r
+  if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
+  }\r
+\r
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
+  }\r
+\r
+  if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
+  }\r
+\r
+  if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+  }\r
+\r
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+  }\r
+\r
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+  }\r
+\r
+  if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;\r
+  }\r
+\r
+  if (Option == EFI_SET_SUPPORTS) {\r
+\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        |\r
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       |\r
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      |\r
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         |\r
+                  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+\r
+    if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+    }\r
+\r
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+      //\r
+      // For bridge, it should support IDE attributes\r
+      //\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+    } else {\r
+\r
+      if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+      }\r
+\r
+      if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+      }\r
+    }\r
+\r
+    PciIoDevice->Supports = Attributes;\r
+    PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \\r
+                               EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+                               EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
+\r
+  } else {\r
+    PciIoDevice->Attributes = Attributes;\r
+  }\r
+}\r
+\r
+/**\r
+  Determine if the device can support Fast Back to Back attribute.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param StatusIndex  Status register value.\r
+\r
+  @retval EFI_SUCCESS       This device support Fast Back to Back attribute.\r
+  @retval EFI_UNSUPPORTED   This device doesn't support Fast Back to Back attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFastBackToBackSupport (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT8                              StatusIndex\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  EFI_STATUS          Status;\r
+  UINT32              StatusRegister;\r
+\r
+  //\r
+  // Read the status register\r
+  //\r
+  PciIo   = &PciIoDevice->PciIo;\r
+  Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Check the Fast B2B bit\r
+  //\r
+  if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+}\r
+\r
+/**\r
+  Process the option ROM for all the children of the specified parent PCI device.\r
+  It can only be used after the first full Option ROM process.\r
+\r
+  @param PciIoDevice Pci device instance.\r
+\r
+**/\r
+VOID\r
+ProcessOptionRomLight (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+{\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+\r
+  //\r
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+  //\r
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      ProcessOptionRomLight (Temp);\r
+    }\r
+\r
+    PciRomGetImageMapping (Temp);\r
+\r
+    //\r
+    // The OpRom has already been processed in the first round\r
+    //\r
+    Temp->AllOpRomProcessed = TRUE;\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  Determine the related attributes of all devices under a Root Bridge.\r
+\r
+  @param PciIoDevice   PCI device instance.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+{\r
+  UINT16          Command;\r
+  UINT16          BridgeControl;\r
+  UINT16          OldCommand;\r
+  UINT16          OldBridgeControl;\r
+  BOOLEAN         FastB2BSupport;\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+  EFI_STATUS      Status;\r
+\r
+  //\r
+  // For Root Bridge, just copy it by RootBridgeIo proctocol\r
+  // so as to keep consistent with the actual attribute\r
+  //\r
+  if (PciIoDevice->Parent == NULL) {\r
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+                                            PciIoDevice->PciRootBridgeIo,\r
+                                            &PciIoDevice->Supports,\r
+                                            &PciIoDevice->Attributes\r
+                                            );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+\r
+    //\r
+    // Set the attributes to be checked for common PCI devices and PPB or P2C\r
+    // Since some devices only support part of them, it is better to set the\r
+    // attribute according to its command or bridge control register\r
+    //\r
+    Command = EFI_PCI_COMMAND_IO_SPACE     |\r
+              EFI_PCI_COMMAND_MEMORY_SPACE |\r
+              EFI_PCI_COMMAND_BUS_MASTER   |\r
+              EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+\r
+    BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
+\r
+    //\r
+    // Test whether the device can support attributes above\r
+    //\r
+    PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
+\r
+    //\r
+    // Set the supported attributes for specified PCI device\r
+    //\r
+    PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
+\r
+    //\r
+    // Set the current attributes for specified PCI device\r
+    //\r
+    PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
+\r
+    //\r
+    // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
+    //\r
+    PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+  }\r
+\r
+  FastB2BSupport = TRUE;\r
+\r
+  //\r
+  // P2C can not support FB2B on the secondary side\r
+  //\r
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+    FastB2BSupport = FALSE;\r
+  }\r
+\r
+  //\r
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+  //\r
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+    Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    Status  = DetermineDeviceAttribute (Temp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Detect Fast Bact to Bact support for the device under the bridge\r
+    //\r
+    Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
+    if (FastB2BSupport && EFI_ERROR (Status)) {\r
+      FastB2BSupport = FALSE;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+  //\r
+  // Set or clear Fast Back to Back bit for the whole bridge\r
+  //\r
+  if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+\r
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+      Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
+\r
+      if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
+        FastB2BSupport = FALSE;\r
+        PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+      } else {\r
+        PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+      }\r
+    }\r
+\r
+    CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+    while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
+      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+      if (FastB2BSupport) {\r
+        PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+      } else {\r
+        PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+      }\r
+\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+    }\r
+  }\r
+  //\r
+  // End for IsListEmpty\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This routine is used to update the bar information for those incompatible PCI device.\r
+\r
+  @param PciIoDevice      Input Pci device instance. Output Pci device instance with updated\r
+                          Bar information.\r
+\r
+  @retval EFI_SUCCESS     Successfully updated bar information.\r
+  @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePciInfo (\r
+  IN OUT PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             BarIndex;\r
+  UINTN                             BarEndIndex;\r
+  BOOLEAN                           SetFlag;\r
+  VOID                              *Configuration;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+\r
+  Configuration = NULL;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
+    //\r
+    // It can only be supported after the Incompatible PCI Device\r
+    // Support Protocol has been installed\r
+    //\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+                    );\r
+  }\r
+  if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Check whether the device belongs to incompatible devices from protocol or not\r
+      // If it is , then get its special requirement in the ACPI table\r
+      //\r
+      Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
+                                                   gEfiIncompatiblePciDeviceSupport,\r
+                                                   PciIoDevice->Pci.Hdr.VendorId,\r
+                                                   PciIoDevice->Pci.Hdr.DeviceId,\r
+                                                   PciIoDevice->Pci.Hdr.RevisionID,\r
+                                                   PciIoDevice->Pci.Device.SubsystemVendorID,\r
+                                                   PciIoDevice->Pci.Device.SubsystemID,\r
+                                                   &Configuration\r
+                                                   );\r
+\r
+  }\r
+\r
+  if (EFI_ERROR (Status) || Configuration == NULL ) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Update PCI device information from the ACPI table\r
+  //\r
+  Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+  while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+    if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+      //\r
+      // The format is not support\r
+      //\r
+      break;\r
+    }\r
+\r
+    BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
+    BarEndIndex = BarIndex;\r
+\r
+    //\r
+    // Update all the bars in the device\r
+    //\r
+    if (BarIndex == PCI_BAR_ALL) {\r
+      BarIndex    = 0;\r
+      BarEndIndex = PCI_MAX_BAR - 1;\r
+    }\r
+\r
+    if (BarIndex > PCI_MAX_BAR) {\r
+      Ptr++;\r
+      continue;\r
+    }\r
+\r
+    for (; BarIndex <= BarEndIndex; BarIndex++) {\r
+      SetFlag = FALSE;\r
+      switch (Ptr->ResType) {\r
+      case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+\r
+        //\r
+        // Make sure the bar is memory type\r
+        //\r
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
+          SetFlag = TRUE;\r
+        }\r
+        break;\r
+\r
+      case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+\r
+        //\r
+        // Make sure the bar is IO type\r
+        //\r
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
+          SetFlag = TRUE;\r
+        }\r
+        break;\r
+      }\r
+\r
+      if (SetFlag) {\r
+\r
+        //\r
+        // Update the new alignment for the device\r
+        //\r
+        SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
+\r
+        //\r
+        // Update the new length for the device\r
+        //\r
+        if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+          PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
+        }\r
+      }\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  FreePool (Configuration);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This routine will update the alignment with the new alignment.\r
+\r
+  @param Alignment    Input Old alignment. Output updated alignment.\r
+  @param NewAlignment New alignment.\r
+\r
+**/\r
+VOID\r
+SetNewAlign (\r
+  IN OUT UINT64     *Alignment,\r
+  IN     UINT64     NewAlignment\r
+  )\r
+{\r
+  UINT64  OldAlignment;\r
+  UINTN   ShiftBit;\r
+\r
+  //\r
+  // The new alignment is the same as the original,\r
+  // so skip it\r
+  //\r
+  if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+    return ;\r
+  }\r
+  //\r
+  // Check the validity of the parameter\r
+  //\r
+   if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&\r
+       NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
+       NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
+    *Alignment = NewAlignment;\r
+    return ;\r
+  }\r
+\r
+  OldAlignment  = (*Alignment) + 1;\r
+  ShiftBit      = 0;\r
+\r
+  //\r
+  // Get the first non-zero hex value of the length\r
+  //\r
+  while ((OldAlignment & 0x0F) == 0x00) {\r
+    OldAlignment = RShiftU64 (OldAlignment, 4);\r
+    ShiftBit += 4;\r
+  }\r
+\r
+  //\r
+  // Adjust the alignment to even, quad or double quad boundary\r
+  //\r
+  if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+    if ((OldAlignment & 0x01) != 0) {\r
+      OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
+    }\r
+  } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+    if ((OldAlignment & 0x03) != 0) {\r
+      OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
+    }\r
+  } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+    if ((OldAlignment & 0x07) != 0) {\r
+      OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Update the old value\r
+  //\r
+  NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
+  *Alignment    = NewAlignment;\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  )\r
+{\r
+  UINT32      Value;\r
+  UINT32      OriginalValue;\r
+  UINT32      Mask;\r
+  UINT32      Data;\r
+  UINT8       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Ensure it is called properly\r
+  //\r
+  ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);\r
+  if (PciIoDevice->SrIovCapabilityOffset == 0) {\r
+    return 0;\r
+  }\r
+\r
+  OriginalValue = 0;\r
+  Value         = 0;\r
+\r
+  Status = VfBarExisted (\r
+            PciIoDevice,\r
+            Offset,\r
+            &Value,\r
+            &OriginalValue\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Length      = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;\r
+\r
+    //\r
+    // Scan all the BARs anyway\r
+    //\r
+    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+    return Offset + 4;\r
+  }\r
+\r
+  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+  if (Value & 0x01) {\r
+    //\r
+    // Device I/Os. Impossible\r
+    //\r
+    ASSERT (FALSE);\r
+    return Offset + 4;\r
+\r
+  } else {\r
+\r
+    Mask  = 0xfffffff0;\r
+\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+    switch (Value & 0x07) {\r
+\r
+    //\r
+    //memory space; anywhere in 32 bit address space\r
+    //\r
+    case 0x00:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;\r
+      } else {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;\r
+      }\r
+\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Adjust Length\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+      //\r
+      // Adjust Alignment\r
+      //\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // memory space; anywhere in 64 bit address space\r
+    //\r
+    case 0x04:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;\r
+      } else {\r
+        PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;\r
+      }\r
+\r
+      //\r
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+      // is regarded as an extension for the first bar. As a result\r
+      // the sizing will be conducted on combined 64 bit value\r
+      // Here just store the masked first 32bit value for future size\r
+      // calculation\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = Value & Mask;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      //\r
+      // Increment the offset to point to next DWORD\r
+      //\r
+      Offset += 4;\r
+\r
+      Status = VfBarExisted (\r
+                PciIoDevice,\r
+                Offset,\r
+                &Value,\r
+                &OriginalValue\r
+                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Offset + 4;\r
+      }\r
+\r
+      //\r
+      // Fix the length to support some spefic 64 bit BAR\r
+      //\r
+      Data  = Value;\r
+      Index = 0;\r
+      for (Data = Value; Data != 0; Data >>= 1) {\r
+       Index ++;\r
+      }\r
+      Value |= ((UINT32)(-1) << Index); \r
+\r
+      //\r
+      // Calculate the size of 64bit bar\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Adjust Length\r
+      //\r
+      PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);\r
+      //\r
+      // Adjust Alignment\r
+      //\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // reserved\r
+    //\r
+    default:\r
+      PciIoDevice->VfPciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
+      PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;\r
+\r
+      if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {\r
+        PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;\r
+      }\r
+\r
+      break;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Check the length again so as to keep compatible with some special bars\r
+  //\r
+  if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {\r
+    PciIoDevice->VfPciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
+    PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;\r
+  }\r
+  \r
+  //\r
+  // Increment number of bar\r
+  //\r
+  return Offset + 4;\r
+}\r
+\r
+/**\r
+  Parse PCI bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciParseBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  )\r
+{\r
+  UINT32      Value;\r
+  UINT32      OriginalValue;\r
+  UINT32      Mask;\r
+  UINT32      Data;\r
+  UINT8       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  OriginalValue = 0;\r
+  Value         = 0;\r
+\r
+  Status = BarExisted (\r
+             PciIoDevice,\r
+             Offset,\r
+             &Value,\r
+             &OriginalValue\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Length      = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+\r
+    //\r
+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
+    //\r
+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+    return Offset + 4;\r
+  }\r
+\r
+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+  if ((Value & 0x01) != 0) {\r
+    //\r
+    // Device I/Os\r
+    //\r
+    Mask = 0xfffffffc;\r
+\r
+    if ((Value & 0xFFFF0000) != 0) {\r
+      //\r
+      // It is a IO32 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;\r
+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    } else {\r
+      //\r
+      // It is a IO16 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;\r
+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    }\r
+    //\r
+    // Workaround. Some platforms inplement IO bar with 0 length\r
+    // Need to treat it as no-bar\r
+    //\r
+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+      PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
+    }\r
+\r
+    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
+\r
+  } else {\r
+\r
+    Mask  = 0xfffffff0;\r
+\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+    switch (Value & 0x07) {\r
+\r
+    //\r
+    //memory space; anywhere in 32 bit address space\r
+    //\r
+    case 0x00:\r
+      if ((Value & 0x08) != 0) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+      }\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
+      break;\r
+\r
+    //\r
+    // memory space; anywhere in 64 bit address space\r
+    //\r
+    case 0x04:\r
+      if ((Value & 0x08) != 0) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
+      }\r
+\r
+      //\r
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+      // is regarded as an extension for the first bar. As a result\r
+      // the sizing will be conducted on combined 64 bit value\r
+      // Here just store the masked first 32bit value for future size\r
+      // calculation\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Increment the offset to point to next DWORD\r
+      //\r
+      Offset += 4;\r
+\r
+      Status = BarExisted (\r
+                 PciIoDevice,\r
+                 Offset,\r
+                 &Value,\r
+                 &OriginalValue\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again\r
+        //\r
+        if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+          //\r
+          // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
+          //\r
+          PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+        }\r
+        return Offset + 4;\r
+      }\r
+\r
+      //\r
+      // Fix the length to support some spefic 64 bit BAR\r
+      //\r
+      Data  = Value;\r
+      Index = 0;\r
+      for (Data = Value; Data != 0; Data >>= 1) {\r
+        Index ++;\r
+      }\r
+      Value |= ((UINT32)(-1) << Index);\r
+\r
+      //\r
+      // Calculate the size of 64bit bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
+\r
+      break;\r
+\r
+    //\r
+    // reserved\r
+    //\r
+    default:\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {\r
+        //\r
+        // Force minimum 4KByte alignment for Virtualization technology for Directed I/O\r
+        //\r
+        PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+      }\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check the length again so as to keep compatible with some special bars\r
+  //\r
+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+  }\r
+\r
+  //\r
+  // Increment number of bar\r
+  //\r
+  return Offset + 4;\r
+}\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI device.\r
+\r
+  @param PciIoDevice Pci device instance.\r
+\r
+  @note It can be called typically when a device is going to be rejected.\r
+\r
+**/\r
+VOID\r
+InitializePciDevice (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT8               Offset;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures\r
+  // Resource base is set to all ones so as to indicate its resource\r
+  // has not been alloacted\r
+  //\r
+  for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
+    PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
+  }\r
+}\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI-PCI Bridge device.\r
+\r
+  @param  PciIoDevice PCI-PCI bridge device instance.\r
+\r
+**/\r
+VOID\r
+InitializePpb (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
+\r
+  //\r
+  // Don't support use io32 as for now\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
+\r
+  //\r
+  // Force Interrupt line to zero for cards that come up randomly\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+}\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI Card Bridge device.\r
+\r
+  @param PciIoDevice  PCI Card bridge device.\r
+\r
+**/\r
+VOID\r
+InitializeP2C (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state(\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
+\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
+\r
+  //\r
+  // Force Interrupt line to zero for cards that come up randomly\r
+  //\r
+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+}\r
+\r
+/**\r
+  Create and initiliaze general PCI I/O device instance for\r
+  PCI device/bridge device/hotplug bridge device.\r
+\r
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+  @param Pci               Input Pci information block.\r
+  @param Bus               Device Bus NO.\r
+  @param Device            Device device NO.\r
+  @param Func              Device func NO.\r
+\r
+  @return Instance of PCI device. NULL means no instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  )\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL  *PciIo;\r
+  EFI_STATUS           Status;\r
+\r
+  PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
+  if (PciIoDevice == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
+  PciIoDevice->Handle           = NULL;\r
+  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
+  PciIoDevice->DevicePath       = NULL;\r
+  PciIoDevice->BusNumber        = Bus;\r
+  PciIoDevice->DeviceNumber     = Device;\r
+  PciIoDevice->FunctionNumber   = Func;\r
+  PciIoDevice->Decodes          = 0;\r
+\r
+  if (gFullEnumeration) {\r
+    PciIoDevice->Allocated = FALSE;\r
+  } else {\r
+    PciIoDevice->Allocated = TRUE;\r
+  }\r
+\r
+  PciIoDevice->Registered         = FALSE;\r
+  PciIoDevice->Attributes         = 0;\r
+  PciIoDevice->Supports           = 0;\r
+  PciIoDevice->BusOverride        = FALSE;\r
+  PciIoDevice->AllOpRomProcessed  = FALSE;\r
+\r
+  PciIoDevice->IsPciExp           = FALSE;\r
+\r
+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
+\r
+  //\r
+  // Initialize the PCI I/O instance structure\r
+  //\r
+  InitializePciIoInstance (PciIoDevice);\r
+  InitializePciDriverOverrideInstance (PciIoDevice);\r
+  InitializePciLoadFile2 (PciIoDevice);\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Detect if PCI Express Device\r
+  //\r
+  PciIoDevice->PciExpressCapabilityOffset = 0;\r
+  Status = LocateCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCI_CAPABILITY_ID_PCIEXP,\r
+             &PciIoDevice->PciExpressCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    PciIoDevice->IsPciExp = TRUE;\r
+  }\r
+\r
+  //\r
+  // Initialize for PCI IOV\r
+  //\r
+\r
+  //\r
+  // Check ARI for function 0 only\r
+  //\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_ARI,\r
+             &PciIoDevice->AriCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->AriCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_SRIOV,\r
+             &PciIoDevice->SrIovCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->SrIovCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  Status = LocatePciExpressCapabilityRegBlock (\r
+             PciIoDevice,\r
+             EFI_PCIE_CAPABILITY_ID_MRIOV,\r
+             &PciIoDevice->MrIovCapabilityOffset,\r
+             NULL\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",\r
+      (UINTN)Bus,\r
+      (UINTN)Device,\r
+      (UINTN)Func,\r
+      (UINTN)PciIoDevice->MrIovCapabilityOffset\r
+      ));\r
+  }\r
+\r
+  //\r
+  // Calculate SystemPageSize\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
+                 1,\r
+                 &PciIoDevice->SystemPageSize\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+\r
+    PciIoDevice->SystemPageSize = (PcdGet32(PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
+    ASSERT (PciIoDevice->SystemPageSize != 0);\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
+                 1,\r
+                 &PciIoDevice->SystemPageSize\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+    //\r
+    // Adjust SystemPageSize for Alignment usage later\r
+    //\r
+    PciIoDevice->SystemPageSize <<= 12;\r
+  }\r
+\r
+  // Calculate BusReservation for PCI IOV\r
+  //\r
+  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+    UINT16    VFStride;\r
+    UINT16    FirstVFOffset;\r
+    UINT32    PFRID;\r
+    UINT32    LastVF;\r
+\r
+    //\r
+    // Read First FirstVFOffset, InitialVFs, and VFStride\r
+    //\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
+                 1,\r
+                 &FirstVFOffset\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
+                 1,\r
+                 &PciIoDevice->InitialVFs\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));\r
+\r
+    PciIo->Pci.Read (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
+                 1,\r
+                 &VFStride\r
+                 );\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));\r
+\r
+    //\r
+    // Calculate LastVF\r
+    //\r
+    PFRID = EFI_PCI_RID(Bus, Device, Func);\r
+    LastVF = PFRID + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
+\r
+    //\r
+    // Calculate ReservedBusNum for this PF\r
+    //\r
+    PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
+    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));\r
+  }\r
+\r
+\r
+  //\r
+  // Initialize the reserved resource list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ReservedResourceList);\r
+\r
+  //\r
+  // Initialize the driver list\r
+  //\r
+  InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
+\r
+  //\r
+  // Initialize the child list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ChildList);\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+/**\r
+  This routine is used to enumerate entire pci bus system\r
+  in a given platform.\r
+\r
+  It is only called on the second start on the same Root Bridge.\r
+\r
+  @param  Controller     Parent bridge handler.\r
+\r
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.\r
+  @retval other          Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+{\r
+\r
+  EFI_STATUS                        Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                     *RootBridgeDev;\r
+  UINT16                            MinBus;\r
+  UINT16                            MaxBus;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+  MinBus      = 0;\r
+  MaxBus      = PCI_MAX_BUS;\r
+  Descriptors = NULL;\r
+\r
+  //\r
+  // If this root bridge has been already enumerated, then return successfully\r
+  //\r
+  if (GetRootBridgeByHandle (Controller) != NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Open pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // Create a device node for root bridge device with a NULL host bridge controller handle\r
+    //\r
+    RootBridgeDev = CreateRootBridge (Controller);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      Descriptors++;\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Record the root bridgeio protocol\r
+    //\r
+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+    Status = PciPciDeviceInfoCollector (\r
+               RootBridgeDev,\r
+               (UINT8) MinBus\r
+               );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+\r
+      //\r
+      // Remove those PCI devices which are rejected when full enumeration\r
+      //\r
+      RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
+\r
+      //\r
+      // Process option rom light\r
+      //\r
+      ProcessOptionRomLight (RootBridgeDev);\r
+\r
+      //\r
+      // Determine attributes for all devices under this root bridge\r
+      //\r
+      DetermineDeviceAttribute (RootBridgeDev);\r
+\r
+      //\r
+      // If successfully, insert the node into device pool\r
+      //\r
+      InsertRootBridge (RootBridgeDev);\r
+    } else {\r
+\r
+      //\r
+      // If unsuccessly, destroy the entire node\r
+      //\r
+      DestroyRootBridge (RootBridgeDev);\r
+    }\r
+\r
+    Descriptors++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get bus range from PCI resource descriptor list.\r
+\r
+  @param Descriptors  A pointer to the address space descriptor.\r
+  @param MinBus       The min bus returned.\r
+  @param MaxBus       The max bus returned.\r
+  @param BusRange     The bus range returned.\r
+\r
+  @retval EFI_SUCCESS    Successfully got bus range.\r
+  @retval EFI_NOT_FOUND  Can not find the specific bus.\r
+\r
+**/\r
+EFI_STATUS\r
+PciGetBusRange (\r
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,\r
+  OUT    UINT16                             *MinBus,\r
+  OUT    UINT16                             *MaxBus,\r
+  OUT    UINT16                             *BusRange\r
+  )\r
+{\r
+  while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+    if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+      if (MinBus != NULL) {\r
+        *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
+      }\r
+\r
+      if (MaxBus != NULL) {\r
+        *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
+      }\r
+\r
+      if (BusRange != NULL) {\r
+        *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    (*Descriptors)++;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  This routine can be used to start the root bridge.\r
+\r
+  @param RootBridgeDev     Pci device instance.\r
+\r
+  @retval EFI_SUCCESS      This device started.\r
+  @retval other            Failed to get PCI Root Bridge I/O protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+StartManagingRootBridge (\r
+  IN PCI_IO_DEVICE *RootBridgeDev\r
+  )\r
+{\r
+  EFI_HANDLE                      RootBridgeHandle;\r
+  EFI_STATUS                      Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  //\r
+  // Get the root bridge handle\r
+  //\r
+  RootBridgeHandle = RootBridgeDev->Handle;\r
+  PciRootBridgeIo  = NULL;\r
+\r
+  //\r
+  // Get the pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  RootBridgeHandle,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  RootBridgeHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Store the PciRootBridgeIo protocol into root bridge private data\r
+  //\r
+  RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  This routine can be used to check whether a PCI device should be rejected when light enumeration.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+\r
+  @retval TRUE      This device should be rejected.\r
+  @retval FALSE     This device shouldn't be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciDeviceRejected (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      TestValue;\r
+  UINT32      OldValue;\r
+  UINT32      Mask;\r
+  UINT8       BarOffset;\r
+\r
+  //\r
+  // PPB should be skip!\r
+  //\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+    //\r
+    // Only test base registers for P2C\r
+    //\r
+    for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
+\r
+      Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
+      Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      TestValue = TestValue & Mask;\r
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+        //\r
+        // The bar isn't programed, so it should be rejected\r
+        //\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+    return FALSE;\r
+  }\r
+\r
+  for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
+    //\r
+    // Test PCI devices\r
+    //\r
+    Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    if ((TestValue & 0x01) != 0) {\r
+\r
+      //\r
+      // IO Bar\r
+      //\r
+      Mask      = 0xFFFFFFFC;\r
+      TestValue = TestValue & Mask;\r
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+        return TRUE;\r
+      }\r
+\r
+    } else {\r
+\r
+      //\r
+      // Mem Bar\r
+      //\r
+      Mask      = 0xFFFFFFF0;\r
+      TestValue = TestValue & Mask;\r
+\r
+      if ((TestValue & 0x07) == 0x04) {\r
+\r
+        //\r
+        // Mem64 or PMem64\r
+        //\r
+        BarOffset += sizeof (UINT32);\r
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+\r
+          //\r
+          // Test its high 32-Bit BAR\r
+          //\r
+          Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+          if (TestValue == OldValue) {\r
+            return TRUE;\r
+          }\r
+        }\r
+\r
+      } else {\r
+\r
+        //\r
+        // Mem32 or PMem32\r
+        //\r
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+          return TRUE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Reset all bus number from specific bridge.\r
+\r
+  @param Bridge           Parent specific bridge.\r
+  @param StartBusNumber   Start bus number.\r
+\r
+**/\r
+VOID\r
+ResetAllPpbBusNumber (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  PCI_TYPE00                      Pci;\r
+  UINT8                           Device;\r
+  UINT32                          Register;\r
+  UINT8                           Func;\r
+  UINT64                          Address;\r
+  UINT8                           SecondaryBus;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether a pci device is present\r
+      //\r
+      Status = PciDevicePresent (\r
+                 PciRootBridgeIo,\r
+                 &Pci,\r
+                 StartBusNumber,\r
+                 Device,\r
+                 Func\r
+                 );\r
+\r
+      if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
+\r
+        Register  = 0;\r
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
+        Status    = PciRootBridgeIo->Pci.Read (\r
+                                           PciRootBridgeIo,\r
+                                           EfiPciWidthUint32,\r
+                                           Address,\r
+                                           1,\r
+                                           &Register\r
+                                           );\r
+        SecondaryBus = (UINT8)(Register >> 8);\r
+\r
+        if (SecondaryBus != 0) {\r
+          ResetAllPpbBusNumber (Bridge, SecondaryBus);\r
+        }\r
+\r
+        //\r
+        // Reset register 18h, 19h, 1Ah on PCI Bridge\r
+        //\r
+        Register &= 0xFF000000;\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint32,\r
+                                        Address,\r
+                                        1,\r
+                                        &Register\r
+                                        );\r
+      }\r
+\r
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+        //\r
+        // Skip sub functions, this is not a multi function device\r
+        //\r
+        Func = PCI_MAX_FUNC;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
new file mode 100644 (file)
index 0000000..31238b4
--- /dev/null
@@ -0,0 +1,463 @@
+/** @file\r
+  PCI emumeration support functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H_\r
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H_\r
+\r
+/**\r
+  This routine is used to check whether the pci device is present.\r
+\r
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+  @param Pci               Output buffer for PCI device configuration space.\r
+  @param Bus               PCI bus NO.\r
+  @param Device            PCI device NO.\r
+  @param Func              PCI Func NO.\r
+\r
+  @retval EFI_NOT_FOUND    PCI device not present.\r
+  @retval EFI_SUCCESS      PCI device is found.\r
+\r
+**/\r
+EFI_STATUS\r
+PciDevicePresent (\r
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,\r
+  OUT PCI_TYPE00                          *Pci,\r
+  IN  UINT8                               Bus,\r
+  IN  UINT8                               Device,\r
+  IN  UINT8                               Func\r
+  );\r
+\r
+/**\r
+  Collect all the resource information under this root bridge.\r
+\r
+  A database that records all the information about pci device subject to this\r
+  root bridge will then be created.\r
+\r
+  @param Bridge         Parent bridge instance.\r
+  @param StartBusNumber Bus number of begining.\r
+\r
+  @retval EFI_SUCCESS   PCI device is found.\r
+  @retval other         Some error occurred when reading PCI bridge information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber\r
+  );\r
+\r
+/**\r
+  Seach required device and create PCI device instance.\r
+\r
+  @param Bridge     Parent bridge instance.\r
+  @param Pci        Input PCI device information block.\r
+  @param Bus        PCI bus NO.\r
+  @param Device     PCI device NO.\r
+  @param Func       PCI func  NO.\r
+  @param PciDevice  Output of searched PCI device instance.\r
+\r
+  @retval EFI_SUCCESS           Successfully created PCI device instance.\r
+  @retval EFI_OUT_OF_RESOURCES  Cannot get PCI device information.\r
+\r
+**/\r
+EFI_STATUS\r
+PciSearchDevice (\r
+  IN  PCI_IO_DEVICE                         *Bridge,\r
+  IN  PCI_TYPE00                            *Pci,\r
+  IN  UINT8                                 Bus,\r
+  IN  UINT8                                 Device,\r
+  IN  UINT8                                 Func,\r
+  OUT PCI_IO_DEVICE                         **PciDevice\r
+  );\r
+\r
+/**\r
+  Create PCI device instance for PCI device.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  );\r
+\r
+/**\r
+  Create PCI device instance for PCI-PCI bridge.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherPpbInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  );\r
+\r
+/**\r
+  Create PCI device instance for PCI Card bridge device.\r
+\r
+  @param Bridge   Parent bridge instance.\r
+  @param Pci      Input PCI device information block.\r
+  @param Bus      PCI device Bus NO.\r
+  @param Device   PCI device Device NO.\r
+  @param Func     PCI device's func NO.\r
+\r
+  @return  Created PCI device instance.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  );\r
+\r
+/**\r
+  Create device path for pci deivce.\r
+\r
+  @param ParentDevicePath  Parent bridge's path.\r
+  @param PciIoDevice       Pci device instance.\r
+\r
+  @return device path protocol instance for specific pci device.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+  IN  PCI_IO_DEVICE            *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Check whether the PCI IOV VF bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+VfBarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  );\r
+\r
+/**\r
+  Check whether the bar is existed or not.\r
+\r
+  @param PciIoDevice       A pointer to the PCI_IO_DEVICE.\r
+  @param Offset            The offset.\r
+  @param BarLengthValue    The bar length value returned.\r
+  @param OriginalBarValue  The original bar value returned.\r
+\r
+  @retval EFI_NOT_FOUND    The bar doesn't exist.\r
+  @retval EFI_SUCCESS      The bar exist.\r
+\r
+**/\r
+EFI_STATUS\r
+BarExisted (\r
+  IN  PCI_IO_DEVICE *PciIoDevice,\r
+  IN  UINTN         Offset,\r
+  OUT UINT32        *BarLengthValue,\r
+  OUT UINT32        *OriginalBarValue\r
+  );\r
+\r
+/**\r
+  Test whether the device can support given attributes.\r
+\r
+  @param PciIoDevice      Pci device instance.\r
+  @param Command          Input command register value, and\r
+                          returned supported register value.\r
+  @param BridgeControl    Inout bridge control value for PPB or P2C, and\r
+                          returned supported bridge control value.\r
+  @param OldCommand       Returned and stored old command register offset.\r
+  @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.\r
+\r
+**/\r
+VOID\r
+PciTestSupportedAttribute (\r
+  IN     PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN OUT UINT16                             *Command,\r
+  IN OUT UINT16                             *BridgeControl,\r
+     OUT UINT16                             *OldCommand,\r
+     OUT UINT16                             *OldBridgeControl\r
+  );\r
+\r
+/**\r
+  Set the supported or current attributes of a PCI device.\r
+\r
+  @param PciIoDevice    Structure pointer for PCI device.\r
+  @param Command        Command register value.\r
+  @param BridgeControl  Bridge control value for PPB or P2C.\r
+  @param Option         Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
+\r
+**/\r
+VOID\r
+PciSetDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT16                             Command,\r
+  IN UINT16                             BridgeControl,\r
+  IN UINTN                              Option\r
+  );\r
+\r
+/**\r
+  Determine if the device can support Fast Back to Back attribute.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param StatusIndex  Status register value.\r
+\r
+  @retval EFI_SUCCESS       This device support Fast Back to Back attribute.\r
+  @retval EFI_UNSUPPORTED   This device doesn't support Fast Back to Back attribute.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFastBackToBackSupport (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT8                              StatusIndex\r
+  );\r
+\r
+/**\r
+  Determine the related attributes of all devices under a Root Bridge.\r
+\r
+  @param PciIoDevice   PCI device instance.\r
+\r
+**/\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  );\r
+\r
+/**\r
+  This routine is used to update the bar information for those incompatible PCI device.\r
+\r
+  @param PciIoDevice      Input Pci device instance. Output Pci device instance with updated\r
+                          Bar information.\r
+\r
+  @retval EFI_SUCCESS     Successfully updated bar information.\r
+  @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePciInfo (\r
+  IN OUT PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  This routine will update the alignment with the new alignment.\r
+\r
+  @param Alignment    Input Old alignment. Output updated alignment.\r
+  @param NewAlignment New alignment.\r
+\r
+**/\r
+VOID\r
+SetNewAlign (\r
+  IN OUT UINT64     *Alignment,\r
+  IN     UINT64     NewAlignment\r
+  );\r
+\r
+/**\r
+  Parse PCI bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciParseBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  );\r
+\r
+/**\r
+  Parse PCI IOV VF bar information and fill them into PCI device instance.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Offset       Bar offset.\r
+  @param BarIndex     Bar index.\r
+\r
+  @return Next bar offset.\r
+\r
+**/\r
+UINTN\r
+PciIovParseVfBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  );\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI device.\r
+\r
+  @param PciIoDevice Pci device instance.\r
+\r
+  @note It can be called typically when a device is going to be rejected.\r
+\r
+**/\r
+VOID\r
+InitializePciDevice (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI-PCI Bridge device.\r
+\r
+  @param  PciIoDevice PCI-PCI bridge device instance.\r
+\r
+**/\r
+VOID\r
+InitializePpb (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  This routine is used to initialize the bar of a PCI Card Bridge device.\r
+\r
+  @param PciIoDevice  PCI Card bridge device.\r
+\r
+**/\r
+VOID\r
+InitializeP2C (\r
+  IN PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Create and initiliaze general PCI I/O device instance for\r
+  PCI device/bridge device/hotplug bridge device.\r
+\r
+  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r
+  @param Pci               Input Pci information block.\r
+  @param Bus               Device Bus NO.\r
+  @param Device            Device device NO.\r
+  @param Func              Device func NO.\r
+\r
+  @return Instance of PCI device. NULL means no instance created.\r
+\r
+**/\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  IN UINT8                            Bus,\r
+  IN UINT8                            Device,\r
+  IN UINT8                            Func\r
+  );\r
+\r
+/**\r
+  This routine is used to enumerate entire pci bus system\r
+  in a given platform.\r
+\r
+  It is only called on the second start on the same Root Bridge.\r
+\r
+  @param  Controller     Parent bridge handler.\r
+\r
+  @retval EFI_SUCCESS    PCI enumeration finished successfully.\r
+  @retval other          Some error occurred when enumerating the pci bus system.\r
+\r
+**/\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+  IN EFI_HANDLE                    Controller\r
+  );\r
+\r
+/**\r
+  Get bus range from PCI resource descriptor list.\r
+\r
+  @param Descriptors  A pointer to the address space descriptor.\r
+  @param MinBus       The min bus returned.\r
+  @param MaxBus       The max bus returned.\r
+  @param BusRange     The bus range returned.\r
+\r
+  @retval EFI_SUCCESS    Successfully got bus range.\r
+  @retval EFI_NOT_FOUND  Can not find the specific bus.\r
+\r
+**/\r
+EFI_STATUS\r
+PciGetBusRange (\r
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,\r
+  OUT    UINT16                             *MinBus,\r
+  OUT    UINT16                             *MaxBus,\r
+  OUT    UINT16                             *BusRange\r
+  );\r
+\r
+/**\r
+  This routine can be used to start the root bridge.\r
+\r
+  @param RootBridgeDev     Pci device instance.\r
+\r
+  @retval EFI_SUCCESS      This device started.\r
+  @retval other            Failed to get PCI Root Bridge I/O protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+StartManagingRootBridge (\r
+  IN PCI_IO_DEVICE *RootBridgeDev\r
+  );\r
+\r
+/**\r
+  This routine can be used to check whether a PCI device should be rejected when light enumeration.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+\r
+  @retval TRUE      This device should be rejected.\r
+  @retval FALSE     This device shouldn't be rejected.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciDeviceRejected (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Reset all bus number from specific bridge.\r
+\r
+  @param Bridge           Parent specific bridge.\r
+  @param StartBusNumber   Start bus number.\r
+\r
+**/\r
+VOID\r
+ResetAllPpbBusNumber (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
new file mode 100644 (file)
index 0000000..20c2c2f
--- /dev/null
@@ -0,0 +1,394 @@
+/** @file\r
+  PCI Hot Plug support functions implementation for PCI Bus module..\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+EFI_PCI_HOT_PLUG_INIT_PROTOCOL  *gPciHotPlugInit = NULL;\r
+EFI_HPC_LOCATION                *gPciRootHpcPool = NULL;\r
+UINTN                           gPciRootHpcCount = 0;\r
+ROOT_HPC_DATA                   *gPciRootHpcData = NULL;\r
+\r
+\r
+/**\r
+  Event notification function to set Hot Plug controller status.\r
+\r
+  @param  Event                    The event that invoke this function.\r
+  @param  Context                  The calling context, pointer to ROOT_HPC_DATA.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHPCInitialized (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  ROOT_HPC_DATA   *HpcData;\r
+\r
+  HpcData               = (ROOT_HPC_DATA *) Context;\r
+  HpcData->Initialized  = TRUE;\r
+}\r
+\r
+/**\r
+  Compare two device pathes to check if they are exactly same.\r
+\r
+  @param DevicePath1    A pointer to the first device path data structure.\r
+  @param DevicePath2    A pointer to the second device path data structure.\r
+\r
+  @retval TRUE    They are same.\r
+  @retval FALSE   They are not same.\r
+\r
+**/\r
+BOOLEAN\r
+EfiCompareDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
+  )\r
+{\r
+  UINTN Size1;\r
+  UINTN Size2;\r
+\r
+  Size1 = GetDevicePathSize (DevicePath1);\r
+  Size2 = GetDevicePathSize (DevicePath2);\r
+\r
+  if (Size1 != Size2) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Check hot plug support and initialize root hot plug private data.\r
+\r
+  If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol\r
+  to get PCI Hot Plug controller's information and constructor the root hot plug\r
+  private data structure.\r
+\r
+  @retval EFI_SUCCESS           They are same.\r
+  @retval EFI_UNSUPPORTED       No PCI Hot Plug controler on the platform.\r
+  @retval EFI_OUT_OF_RESOURCES  No memory to constructor root hot plug private\r
+                                data structure.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotPlugSupport (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_HPC_LOCATION  *HpcList;\r
+  UINTN             HpcCount;\r
+\r
+  //\r
+  // Locate the PciHotPlugInit Protocol\r
+  // If it doesn't exist, that means there is no\r
+  // hot plug controller supported on the platform\r
+  // the PCI Bus driver is running on. HotPlug Support\r
+  // is an optional feature, so absence of the protocol\r
+  // won't incur the penalty.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiPciHotPlugInitProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &gPciHotPlugInit\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = gPciHotPlugInit->GetRootHpcList (\r
+                              gPciHotPlugInit,\r
+                              &HpcCount,\r
+                              &HpcList\r
+                              );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    gPciRootHpcPool   = HpcList;\r
+    gPciRootHpcCount  = HpcCount;\r
+    gPciRootHpcData   = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);\r
+    if (gPciRootHpcData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Test whether device path is for root pci hot plug bus.\r
+\r
+  @param HpbDevicePath  A pointer to device path data structure to be tested.\r
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
+                        plug in global array when TRUE is retuned.\r
+\r
+  @retval TRUE          The device path is for root pci hot plug bus.\r
+  @retval FALSE         The device path is not for root pci hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugBus (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *HpbDevicePath,\r
+  OUT UINTN                           *HpIndex    OPTIONAL\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+    if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {\r
+\r
+      if (HpIndex != NULL) {\r
+        *HpIndex = Index;\r
+      }\r
+\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Test whether device path is for root pci hot plug controller.\r
+\r
+  @param HpcDevicePath  A pointer to device path data structure to be tested.\r
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
+                        plug in global array when TRUE is retuned.\r
+\r
+  @retval TRUE          The device path is for root pci hot plug controller.\r
+  @retval FALSE         The device path is not for root pci hot plug controller.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugController (\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,\r
+  OUT UINTN                           *HpIndex\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+    if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {\r
+\r
+      if (HpIndex != NULL) {\r
+        *HpIndex = Index;\r
+      }\r
+\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Creating event object for PCI Hot Plug controller.\r
+\r
+  @param  HpIndex   Index of hot plug device in global array.\r
+  @param  Event     The retuned event that invoke this function.\r
+\r
+  @return Status of create event invoken.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateEventForHpc (\r
+  IN  UINTN      HpIndex,\r
+  OUT EFI_EVENT  *Event\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  PciHPCInitialized,\r
+                  gPciRootHpcData + HpIndex,\r
+                  &((gPciRootHpcData + HpIndex)->Event)\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    *Event = (gPciRootHpcData + HpIndex)->Event;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Wait for all root PCI Hot Plug controller finished initializing.\r
+\r
+  @param TimeoutInMicroSeconds  Microseconds to wait for all root HPCs' initialization.\r
+\r
+  @retval EFI_SUCCESS           All HPCs initialization finished.\r
+  @retval EFI_TIMEOUT           Not ALL HPCs initialization finished in Microseconds.\r
+\r
+**/\r
+EFI_STATUS\r
+AllRootHPCInitialized (\r
+  IN  UINTN           TimeoutInMicroSeconds\r
+  )\r
+{\r
+  UINT32  Delay;\r
+  UINTN   Index;\r
+\r
+  Delay = (UINT32) ((TimeoutInMicroSeconds / 30) + 1);\r
+\r
+  do {\r
+    for (Index = 0; Index < gPciRootHpcCount; Index++) {\r
+\r
+      if (!gPciRootHpcData[Index].Initialized) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index == gPciRootHpcCount) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    //\r
+    // Stall for 30 microseconds..\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+\r
+  } while (Delay > 0);\r
+\r
+  return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+  Check whether PCI-PCI bridge has PCI Hot Plug capability register block.\r
+\r
+  @param PciIoDevice    A Pointer to the PCI-PCI bridge.\r
+\r
+  @retval TRUE    PCI device is HPC.\r
+  @retval FALSE   PCI device is not HPC.\r
+\r
+**/\r
+BOOLEAN\r
+IsSHPC (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+{\r
+\r
+  EFI_STATUS  Status;\r
+  UINT8       Offset;\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  Offset = 0;\r
+  Status = LocateCapabilityRegBlock (\r
+            PciIoDevice,\r
+            EFI_PCI_CAPABILITY_ID_HOTPLUG,\r
+            &Offset,\r
+            NULL\r
+            );\r
+\r
+  //\r
+  // If the PCI-PCI bridge has the hot plug controller build-in,\r
+  // then return TRUE;\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get resource padding if the specified PCI bridge is a hot plug bus.\r
+\r
+  @param PciIoDevice    PCI bridge instance.\r
+\r
+**/\r
+VOID\r
+GetResourcePaddingForHpb (\r
+  IN PCI_IO_DEVICE      *PciIoDevice\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_HPC_STATE                     State;\r
+  UINT64                            PciAddress;\r
+  EFI_HPC_PADDING_ATTRIBUTES        Attributes;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+  if (IsPciHotPlugBus (PciIoDevice)) {\r
+    //\r
+    // If PCI-PCI bridge device is PCI Hot Plug bus.\r
+    //\r
+    PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+    Status = gPciHotPlugInit->GetResourcePadding (\r
+                                gPciHotPlugInit,\r
+                                PciIoDevice->DevicePath,\r
+                                PciAddress,\r
+                                &State,\r
+                                (VOID **) &Descriptors,\r
+                                &Attributes\r
+                                );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return;\r
+    }\r
+\r
+    if ((State & EFI_HPC_STATE_ENABLED) != 0 && (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
+      PciIoDevice->ResourcePaddingDescriptors = Descriptors;\r
+      PciIoDevice->PaddingAttributes          = Attributes;\r
+    }\r
+\r
+    return;\r
+  }\r
+}\r
+\r
+/**\r
+  Test whether PCI device is hot plug bus.\r
+\r
+  @param PciIoDevice  PCI device instance.\r
+\r
+  @retval TRUE    PCI device is a hot plug bus.\r
+  @retval FALSE   PCI device is not a hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciHotPlugBus (\r
+  PCI_IO_DEVICE                       *PciIoDevice\r
+  )\r
+{\r
+  if (IsSHPC (PciIoDevice)) {\r
+    //\r
+    // If the PPB has the hot plug controller build-in,\r
+    // then return TRUE;\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Otherwise, see if it is a Root HPC\r
+  //\r
+  if(IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.h
new file mode 100644 (file)
index 0000000..a84e256
--- /dev/null
@@ -0,0 +1,189 @@
+/** @file\r
+  PCI Hot Plug support functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H_\r
+#define _EFI_PCI_HOT_PLUG_SUPPORT_H_\r
+\r
+//\r
+// stall 1 second, its unit is 100ns\r
+//\r
+#define STALL_1_SECOND        1000000\r
+\r
+//\r
+// PCI Hot Plug controller private data\r
+//\r
+typedef struct {\r
+  EFI_EVENT Event;\r
+  BOOLEAN   Initialized;\r
+  VOID      *Padding;\r
+} ROOT_HPC_DATA;\r
+\r
+//\r
+// Reference of some global variabes\r
+//\r
+extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;\r
+extern EFI_HPC_LOCATION               *gPciRootHpcPool;\r
+extern ROOT_HPC_DATA                  *gPciRootHpcData;\r
+\r
+/**\r
+  Event notification function to set Hot Plug controller status.\r
+\r
+  @param  Event                    The event that invoke this function.\r
+  @param  Context                  The calling context, pointer to ROOT_HPC_DATA.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHPCInitialized (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  );\r
+\r
+/**\r
+  Compare two device pathes to check if they are exactly same.\r
+\r
+  @param DevicePath1    A pointer to the first device path data structure.\r
+  @param DevicePath2    A pointer to the second device path data structure.\r
+\r
+  @retval TRUE    They are same.\r
+  @retval FALSE   They are not same.\r
+\r
+**/\r
+BOOLEAN\r
+EfiCompareDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2\r
+  );\r
+\r
+/**\r
+  Check hot plug support and initialize root hot plug private data.\r
+\r
+  If Hot Plug is supported by the platform, call PCI Hot Plug Init protocol\r
+  to get PCI Hot Plug controller's information and constructor the root hot plug\r
+  private data structure.\r
+\r
+  @retval EFI_SUCCESS           They are same.\r
+  @retval EFI_UNSUPPORTED       No PCI Hot Plug controler on the platform.\r
+  @retval EFI_OUT_OF_RESOURCES  No memory to constructor root hot plug private\r
+                                data structure.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotPlugSupport (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Test whether PCI device is hot plug bus.\r
+\r
+  @param PciIoDevice  PCI device instance.\r
+\r
+  @retval TRUE    PCI device is a hot plug bus.\r
+  @retval FALSE   PCI device is not a hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsPciHotPlugBus (\r
+  PCI_IO_DEVICE                       *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Test whether device path is for root pci hot plug bus.\r
+\r
+  @param HpbDevicePath  A pointer to device path data structure to be tested.\r
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
+                        plug in global array when TRUE is retuned.\r
+\r
+  @retval TRUE          The device path is for root pci hot plug bus.\r
+  @retval FALSE         The device path is not for root pci hot plug bus.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugBus (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *HpbDevicePath,\r
+  OUT UINTN                           *HpIndex    OPTIONAL\r
+  );\r
+\r
+/**\r
+  Test whether device path is for root pci hot plug controller.\r
+\r
+  @param HpcDevicePath  A pointer to device path data structure to be tested.\r
+  @param HpIndex        If HpIndex is not NULL, return the index of root hot\r
+                        plug in global array when TRUE is retuned.\r
+\r
+  @retval TRUE          The device path is for root pci hot plug controller.\r
+  @retval FALSE         The device path is not for root pci hot plug controller.\r
+\r
+**/\r
+BOOLEAN\r
+IsRootPciHotPlugController (\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,\r
+  OUT UINTN                           *HpIndex\r
+  );\r
+\r
+/**\r
+  Creating event object for PCI Hot Plug controller.\r
+\r
+  @param  HpIndex   Index of hot plug device in global array.\r
+  @param  Event     The retuned event that invoke this function.\r
+\r
+  @return Status of create event invoken.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateEventForHpc (\r
+  IN  UINTN      HpIndex,\r
+  OUT EFI_EVENT  *Event\r
+  );\r
+\r
+/**\r
+  Wait for all root PCI Hot Plug controller finished initializing.\r
+\r
+  @param TimeoutInMicroSeconds  Microseconds to wait for all root HPCs' initialization.\r
+\r
+  @retval EFI_SUCCESS           All HPCs initialization finished.\r
+  @retval EFI_TIMEOUT           Not ALL HPCs initialization finished in Microseconds.\r
+\r
+**/\r
+EFI_STATUS\r
+AllRootHPCInitialized (\r
+  IN  UINTN           TimeoutInMicroSeconds\r
+  );\r
+\r
+/**\r
+  Check whether PCI-PCI bridge has PCI Hot Plug capability register block.\r
+\r
+  @param PciIoDevice    A Pointer to the PCI-PCI bridge.\r
+\r
+  @retval TRUE    PCI device is HPC.\r
+  @retval FALSE   PCI device is not HPC.\r
+\r
+**/\r
+BOOLEAN\r
+IsSHPC (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Get resource padding if the specified PCI bridge is a hot plug bus.\r
+\r
+  @param PciIoDevice    PCI bridge instance.\r
+\r
+**/\r
+VOID\r
+GetResourcePaddingForHpb (\r
+  IN PCI_IO_DEVICE      *PciIoDevice\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
new file mode 100644 (file)
index 0000000..5cc5967
--- /dev/null
@@ -0,0 +1,1877 @@
+/** @file\r
+  EFI PCI IO protocol functions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// Pci Io Protocol Interface\r
+//\r
+EFI_PCI_IO_PROTOCOL  mPciIoInterface = {\r
+  PciIoPollMem,\r
+  PciIoPollIo,\r
+  {\r
+    PciIoMemRead,\r
+    PciIoMemWrite\r
+  },\r
+  {\r
+    PciIoIoRead,\r
+    PciIoIoWrite\r
+  },\r
+  {\r
+    PciIoConfigRead,\r
+    PciIoConfigWrite\r
+  },\r
+  PciIoCopyMem,\r
+  PciIoMap,\r
+  PciIoUnmap,\r
+  PciIoAllocateBuffer,\r
+  PciIoFreeBuffer,\r
+  PciIoFlush,\r
+  PciIoGetLocation,\r
+  PciIoAttributes,\r
+  PciIoGetBarAttributes,\r
+  PciIoSetBarAttributes,\r
+  0,\r
+  NULL\r
+};\r
+\r
+/**\r
+  Report a error Status code of PCI bus driver controller.\r
+\r
+  @param PciIoDevice Pci device instance.\r
+  @param Code        Status code value.\r
+\r
+**/\r
+EFI_STATUS\r
+ReportErrorStatusCode (\r
+  IN PCI_IO_DEVICE               *PciIoDevice,\r
+  IN EFI_STATUS_CODE_VALUE       Code\r
+  )\r
+{\r
+  return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+          EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+          Code,\r
+          PciIoDevice->DevicePath\r
+          );\r
+}\r
+\r
+/**\r
+  Initializes a PCI I/O Instance.\r
+\r
+  @param PciIoDevice    Pci device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciIoInstance (\r
+  IN PCI_IO_DEVICE               *PciIoDevice\r
+  )\r
+{\r
+  CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
+}\r
+\r
+/**\r
+  Verifies access to a PCI Base Address Register (BAR).\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param BarIndex     The BAR index of the standard PCI Configuration header to use as the\r
+                      base address for the memory or I/O operation to perform.\r
+  @param Type         Operation type could be memory or I/O.\r
+  @param Width        Signifies the width of the memory or I/O operations.\r
+  @param Count        The number of memory or I/O operations to perform.\r
+  @param Offset       The offset within the PCI configuration space for the PCI controller.\r
+\r
+  @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
+  @retval EFI_SUCCESS           Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  IN PCI_IO_DEVICE                   *PciIoDevice,\r
+  IN UINT8                           BarIndex,\r
+  IN PCI_BAR_TYPE                    Type,\r
+  IN IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN IN UINTN                        Count,\r
+  IN UINT64                          *Offset\r
+  )\r
+{\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // BarIndex 0-5 is legal\r
+  //\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+    Count = 1;\r
+  }\r
+\r
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+\r
+  if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Verifies access to a PCI Configuration Header.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Width        Signifies the width of the memory or I/O operations.\r
+  @param Count        The number of memory or I/O operations to perform.\r
+  @param Offset       The offset within the PCI configuration space for the PCI controller.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Invalid Width\r
+  @retval EFI_UNSUPPORTED        Offset overflowed.\r
+  @retval EFI_SUCCESS            Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  IN PCI_IO_DEVICE              *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+  )\r
+{\r
+  UINT64  ExtendOffset;\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
+\r
+  if (PciIoDevice->IsPciExp) {\r
+    if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    ExtendOffset  = LShiftU64 (*Offset, 32);\r
+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+    *Offset       = (*Offset) | ExtendOffset;\r
+\r
+  } else {\r
+    if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+  satisfied or after a defined duration.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory operation.\r
+  @param  Mask                  Mask used for the polling criteria.\r
+  @param  Value                 The comparison value used for the polling exit criteria.\r
+  @param  Delay                 The number of 100 ns units to poll.\r
+  @param  Result                Pointer to the last value read from the memory location.\r
+\r
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.\r
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
+                                           PciIoDevice->PciRootBridgeIo,\r
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                           Offset,\r
+                                           Mask,\r
+                                           Value,\r
+                                           Delay,\r
+                                           Result\r
+                                           );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+  satisfied or after a defined duration.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory operation.\r
+  @param  Mask                  Mask used for the polling criteria.\r
+  @param  Value                 The comparison value used for the polling exit criteria.\r
+  @param  Delay                 The number of 100 ns units to poll.\r
+  @param  Result                Pointer to the last value read from the memory location.\r
+\r
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.\r
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
+                                           PciIoDevice->PciRootBridgeIo,\r
+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                           Offset,\r
+                                           Mask,\r
+                                           Value,\r
+                                           Delay,\r
+                                           Result\r
+                                           );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.\r
+  @param  Count                 The number of PCI configuration operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI configuration header of the PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
+                                               PciIoDevice->PciRootBridgeIo,\r
+                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                               Address,\r
+                                               Count,\r
+                                               Buffer\r
+                                               );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.\r
+  @param  Count                 The number of PCI configuration operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI configuration header of the PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Address,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
+  memory space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  DestBarIndex          The BAR index in the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  DestOffset            The destination offset within the BAR specified by DestBarIndex to\r
+                                start the memory writes for the copy operation.\r
+  @param  SrcBarIndex           The BAR index in the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  SrcOffset             The source offset within the BAR specified by SrcBarIndex to start\r
+                                the memory reads for the copy operation.\r
+  @param  Count                 The number of memory operations to perform. Bytes moved is Width\r
+                                size * Count, starting at DestOffset and SrcOffset.\r
+\r
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.\r
+  @retval EFI_UNSUPPORTED       DestBarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       SrcBarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by DestOffset, Width, and Count\r
+                                is not valid for the PCI BAR specified by DestBarIndex.\r
+  @retval EFI_UNSUPPORTED       The address range specified by SrcOffset, Width, and Count is\r
+                                not valid for the PCI BAR specified by SrcBarIndex.\r
+  @retval EFI_INVALID_PARAMETER Width is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == EfiPciIoWidthFifoUint8  ||\r
+      Width == EfiPciIoWidthFifoUint16 ||\r
+      Width == EfiPciIoWidthFifoUint32 ||\r
+      Width == EfiPciIoWidthFifoUint64 ||\r
+      Width == EfiPciIoWidthFillUint8  ||\r
+      Width == EfiPciIoWidthFillUint16 ||\r
+      Width == EfiPciIoWidthFillUint32 ||\r
+      Width == EfiPciIoWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          DestOffset,\r
+                                          SrcOffset,\r
+                                          Count\r
+                                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Provides the PCI controller-specific addresses needed to access system memory.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.\r
+  @param  HostAddress           The system memory address to map to the PCI controller.\r
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes\r
+                                that were mapped.\r
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param  Mapping               A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.\r
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
+    Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Map (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+                                          HostAddress,\r
+                                          NumberOfBytes,\r
+                                          DeviceAddress,\r
+                                          Mapping\r
+                                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Mapping               The mapping value returned from Map().\r
+\r
+  @retval EFI_SUCCESS           The range was unmapped.\r
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Mapping\r
+                                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
+  mapping.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Type                  This parameter is not used and must be ignored.\r
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or\r
+                                EfiRuntimeServicesData.\r
+  @param  Pages                 The number of pages to allocate.\r
+  @param  HostAddress           A pointer to store the base system memory address of the\r
+                                allocated range.\r
+  @param  Attributes            The requested bit mask of attributes for the allocated range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 Pages,\r
+  OUT VOID                  **HostAddress,\r
+  IN  UINT64                Attributes\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if ((Attributes &\r
+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Type,\r
+                                          MemoryType,\r
+                                          Pages,\r
+                                          HostAddress,\r
+                                          Attributes\r
+                                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Frees memory that was allocated with AllocateBuffer().\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Pages                 The number of pages to free.\r
+  @param  HostAddress           The base system memory address of the allocated range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were freed.\r
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
+                                was not allocated with AllocateBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Pages,\r
+                                          HostAddress\r
+                                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host\r
+                                bridge to system memory.\r
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI\r
+                                host bridge due to a hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Flush (\r
+                                           PciIoDevice->PciRootBridgeIo\r
+                                           );\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  SegmentNumber         The PCI controller's current PCI segment number.\r
+  @param  BusNumber             The PCI controller's current PCI bus number.\r
+  @param  DeviceNumber          The PCI controller's current PCI device number.\r
+  @param  FunctionNumber        The PCI controller's current PCI function number.\r
+\r
+  @retval EFI_SUCCESS           The PCI controller location was returned.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  )\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
+  *Bus      = PciIoDevice->BusNumber;\r
+  *Device   = PciIoDevice->DeviceNumber;\r
+  *Function = PciIoDevice->FunctionNumber;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check BAR type for PCI resource.\r
+\r
+  @param PciIoDevice   PCI device instance.\r
+  @param BarIndex      The BAR index of the standard PCI Configuration header to use as the\r
+                       base address for the memory or I/O operation to perform.\r
+  @param BarType       Memory or I/O.\r
+\r
+  @retval TRUE         Pci device's bar type is same with input BarType.\r
+  @retval TRUE         Pci device's bar type is not same with input BarType.\r
+\r
+**/\r
+BOOLEAN\r
+CheckBarType (\r
+  IN PCI_IO_DEVICE          *PciIoDevice,\r
+  IN UINT8                  BarIndex,\r
+  IN PCI_BAR_TYPE           BarType\r
+  )\r
+{\r
+  switch (BarType) {\r
+\r
+  case PciBarTypeMem:\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  case PciBarTypeIo:\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Set/Disable new attributes to a Root Bridge.\r
+\r
+  @param  PciIoDevice  Pci device instance.\r
+  @param  Attributes   New attribute want to be set.\r
+  @param  Operation    Set or Disable.\r
+\r
+  @retval  EFI_UNSUPPORTED  If root bridge does not support change attribute.\r
+  @retval  EFI_SUCCESS      Successfully set new attributs.\r
+\r
+**/\r
+EFI_STATUS\r
+ModifyRootBridgeAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  UINT64                                   Attributes,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation\r
+  )\r
+{\r
+  UINT64      PciRootBridgeSupports;\r
+  UINT64      PciRootBridgeAttributes;\r
+  UINT64      NewPciRootBridgeAttributes;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Get the current attributes of this PCI device's PCI Root Bridge\r
+  //\r
+  Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          &PciRootBridgeSupports,\r
+                                          &PciRootBridgeAttributes\r
+                                          );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Record the new attribute of the Root Bridge\r
+  //\r
+  if (Operation == EfiPciIoAttributeOperationEnable) {\r
+    NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;\r
+  } else {\r
+    NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);\r
+  }\r
+\r
+  //\r
+  // Call the PCI Root Bridge to attempt to modify the attributes\r
+  //\r
+  if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {\r
+\r
+    Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
+                                            PciIoDevice->PciRootBridgeIo,\r
+                                            NewPciRootBridgeAttributes,\r
+                                            NULL,\r
+                                            NULL\r
+                                            );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // The PCI Root Bridge could not modify the attributes, so return the error.\r
+      //\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Also update the attributes for this Root Bridge structure\r
+  //\r
+  PciIoDevice->Attributes = NewPciRootBridgeAttributes;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether this device can be enable/disable to snoop.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Operation    Enable/Disable.\r
+\r
+  @retval EFI_UNSUPPORTED  Pci device is not GFX device or not support snoop.\r
+  @retval EFI_SUCCESS      Snoop can be supported.\r
+\r
+**/\r
+EFI_STATUS\r
+SupportPaletteSnoopAttributes (\r
+  IN PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation\r
+  )\r
+{\r
+  PCI_IO_DEVICE *Temp;\r
+  UINT16        VGACommand;\r
+\r
+  //\r
+  // Snoop attribute can be only modified by GFX\r
+  //\r
+  if (!IS_PCI_GFX (&PciIoDevice->Pci)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Get the boot VGA on the same segement\r
+  //\r
+  Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+  if (Temp == NULL) {\r
+    //\r
+    // If there is no VGA device on the segement, set\r
+    // this graphics card to decode the palette range\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Check these two agents are on the same path\r
+  //\r
+  if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {\r
+    //\r
+    // they are not on the same path, so snoop can be enabled or disabled\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Check if they are on the same bus\r
+  //\r
+  if (Temp->Parent == PciIoDevice->Parent) {\r
+\r
+    PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);\r
+\r
+    //\r
+    // If they are on the same bus, either one can\r
+    // be set to snoop, the other set to decode\r
+    //\r
+    if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
+      //\r
+      // VGA has set to snoop, so GFX can be only set to disable snoop\r
+      //\r
+      if (Operation == EfiPciIoAttributeOperationEnable) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+    } else {\r
+      //\r
+      // VGA has disabled to snoop, so GFX can be only enabled\r
+      //\r
+      if (Operation == EfiPciIoAttributeOperationDisable) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // If they are on  the same path but on the different bus\r
+  // The first agent is set to snoop, the second one set to\r
+  // decode\r
+  //\r
+\r
+  if (Temp->BusNumber < PciIoDevice->BusNumber) {\r
+    //\r
+    // GFX should be set to decode\r
+    //\r
+    if (Operation == EfiPciIoAttributeOperationDisable) {\r
+      PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+      Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+    } else {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+  } else {\r
+    //\r
+    // GFX should be set to snoop\r
+    //\r
+    if (Operation == EfiPciIoAttributeOperationEnable) {\r
+      PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+      Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+    } else {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Performs an operation on the attributes that this PCI controller supports. The operations include\r
+  getting the set of supported attributes, retrieving the current attributes, setting the current\r
+  attributes, enabling attributes, and disabling attributes.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Operation             The operation to perform on the attributes for this PCI controller.\r
+  @param  Attributes            The mask of attributes that are used for Set, Enable, and Disable\r
+                                operations.\r
+  @param  Result                A pointer to the result mask of attributes that are returned for the Get\r
+                                and Supported operations.\r
+\r
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_UNSUPPORTED       one or more of the bits set in\r
+                                Attributes are not supported by this PCI controller or one of\r
+                                its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL                       * This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  PCI_IO_DEVICE *UpStreamBridge;\r
+  PCI_IO_DEVICE *Temp;\r
+\r
+  UINT64        Supports;\r
+  UINT64        UpStreamAttributes;\r
+  UINT16        BridgeControl;\r
+  UINT16        Command;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  switch (Operation) {\r
+  case EfiPciIoAttributeOperationGet:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Attributes;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationSupported:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Supports;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationSet:\r
+    Status = PciIoDevice->PciIo.Attributes (\r
+                                  &(PciIoDevice->PciIo),\r
+                                  EfiPciIoAttributeOperationEnable,\r
+                                  Attributes,\r
+                                  NULL\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    Status = PciIoDevice->PciIo.Attributes (\r
+                                  &(PciIoDevice->PciIo),\r
+                                  EfiPciIoAttributeOperationDisable,\r
+                                  (~Attributes) & (PciIoDevice->Supports),\r
+                                  NULL\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationEnable:\r
+  case EfiPciIoAttributeOperationDisable:\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Just a trick for ENABLE attribute\r
+  // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.\r
+  // So, this logic doesn't confrom to UEFI spec, which should be removed.\r
+  // But this trick logic is still kept for some binary drivers that depend on it.\r
+  //\r
+  if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {\r
+    Attributes &= (PciIoDevice->Supports);\r
+\r
+    //\r
+    // Raise the EFI_P_PC_ENABLE Status code\r
+    //\r
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+      EFI_PROGRESS_CODE,\r
+      EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,\r
+      PciIoDevice->DevicePath\r
+      );\r
+  }\r
+\r
+  //\r
+  // If no attributes can be supported, then return.\r
+  // Otherwise, set the attributes that it can support.\r
+  //\r
+  Supports = (PciIoDevice->Supports) & Attributes;\r
+  if (Supports != Attributes) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // For Root Bridge, just call RootBridgeIo to set attributes;\r
+  //\r
+  if (PciIoDevice->Parent == NULL) {\r
+    Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);\r
+    return Status;\r
+  }\r
+\r
+  Command       = 0;\r
+  BridgeControl = 0;\r
+\r
+  //\r
+  // Check VGA and VGA16, they can not be set at the same time\r
+  //\r
+  if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0         &&\r
+       (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0)         ||\r
+      ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0         &&\r
+       (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ||\r
+      ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
+       (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0)         ||\r
+      ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
+       (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // For PPB & P2C, set relevant attribute bits\r
+  //\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+    }\r
+\r
+    if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {\r
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+    }\r
+\r
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
+      Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+    }\r
+\r
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
+      BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
+    }\r
+\r
+  } else {\r
+    //\r
+    // Do with the attributes on VGA\r
+    // Only for VGA's legacy resource, we just can enable once.\r
+    //\r
+    if ((Attributes &\r
+        (EFI_PCI_IO_ATTRIBUTE_VGA_IO    |\r
+         EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |\r
+         EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {\r
+      //\r
+      // Check if a VGA has been enabled before enabling a new one\r
+      //\r
+      if (Operation == EfiPciIoAttributeOperationEnable) {\r
+        //\r
+        // Check if there have been an active VGA device on the same segment\r
+        //\r
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+        if (Temp != NULL && Temp != PciIoDevice) {\r
+          //\r
+          // An active VGA has been detected, so can not enable another\r
+          //\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // Do with the attributes on GFX\r
+    //\r
+    if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
+\r
+      if (Operation == EfiPciIoAttributeOperationEnable) {\r
+        //\r
+        // Check if snoop can be enabled in current configuration\r
+        //\r
+        Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);\r
+\r
+        if (EFI_ERROR (Status)) {\r
+\r
+          //\r
+          // Enable operation is forbidden, so mask the bit in attributes\r
+          // so as to keep consistent with the actual Status\r
+          //\r
+          // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
+          //\r
+          //\r
+          //\r
+          return EFI_UNSUPPORTED;\r
+\r
+        }\r
+      }\r
+\r
+      //\r
+      // It can be supported, so get ready to set the bit\r
+      //\r
+      Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+    }\r
+  }\r
+\r
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
+    Command |= EFI_PCI_COMMAND_IO_SPACE;\r
+  }\r
+\r
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {\r
+    Command |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+  }\r
+\r
+  if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {\r
+    Command |= EFI_PCI_COMMAND_BUS_MASTER;\r
+  }\r
+  //\r
+  // The upstream bridge should be also set to revelant attribute\r
+  // expect for IO, Mem and BusMaster\r
+  //\r
+  UpStreamAttributes = Attributes &\r
+                       (~(EFI_PCI_IO_ATTRIBUTE_IO     |\r
+                          EFI_PCI_IO_ATTRIBUTE_MEMORY |\r
+                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
+                          )\r
+                        );\r
+  UpStreamBridge = PciIoDevice->Parent;\r
+\r
+  if (Operation == EfiPciIoAttributeOperationEnable) {\r
+    //\r
+    // Enable relevant attributes to command register and bridge control register\r
+    //\r
+    Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
+    if (BridgeControl != 0) {\r
+      Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+    }\r
+\r
+    PciIoDevice->Attributes |= Attributes;\r
+\r
+    //\r
+    // Enable attributes of the upstream bridge\r
+    //\r
+    Status = UpStreamBridge->PciIo.Attributes (\r
+                                    &(UpStreamBridge->PciIo),\r
+                                    EfiPciIoAttributeOperationEnable,\r
+                                    UpStreamAttributes,\r
+                                    NULL\r
+                                    );\r
+  } else {\r
+\r
+    //\r
+    // Disable relevant attributes to command register and bridge control register\r
+    //\r
+    Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
+    if (BridgeControl != 0) {\r
+      Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
+    }\r
+\r
+    PciIoDevice->Attributes &= (~Attributes);\r
+    Status = EFI_SUCCESS;\r
+\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Gets the attributes that this PCI controller supports setting on a BAR using\r
+  SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for resource range. The legal range for this field is 0..5.\r
+  @param  Supports              A pointer to the mask of attributes that this PCI controller supports\r
+                                setting for this BAR with SetBarAttributes().\r
+  @param  Resources             A pointer to the ACPI 2.0 resource descriptors that describe the current\r
+                                configuration of this BAR of the PCI controller.\r
+\r
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI\r
+                                controller supports are returned in Supports. If Resources\r
+                                is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
+                                controller is currently using are returned in Resources.\r
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate\r
+                                Resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL             * This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports, OPTIONAL\r
+  OUT VOID                           **Resources OPTIONAL\r
+  )\r
+{\r
+\r
+  UINT8                             *Configuration;\r
+  UINT8                             NumConfig;\r
+  PCI_IO_DEVICE                     *PciIoDevice;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
+\r
+  NumConfig   = 0;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Supports == NULL && Resources == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // This driver does not support modifications to the WRITE_COMBINE or\r
+  // CACHED attributes for BAR ranges.\r
+  //\r
+  if (Supports != NULL) {\r
+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+  }\r
+\r
+  if (Resources != NULL) {\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
+      NumConfig = 1;\r
+    }\r
+\r
+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    if (Configuration == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+    if (NumConfig == 1) {\r
+      Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+\r
+      Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+      Ptr->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;\r
+      Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
+\r
+      switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+      case PciBarTypeIo16:\r
+      case PciBarTypeIo32:\r
+        //\r
+        // Io\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+        break;\r
+\r
+      case PciBarTypeMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypePMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypeMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      case PciBarTypePMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+    }\r
+\r
+    //\r
+    // put the checksum\r
+    //\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+    PtrEnd->Checksum  = 0;\r
+\r
+    *Resources        = Configuration;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Sets the attributes for a range of a BAR on a PCI controller.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Attributes            The mask of attributes to set for the resource range specified by\r
+                                BarIndex, Offset, and Length.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for resource range. The legal range for this field is 0..5.\r
+  @param  Offset                A pointer to the BAR relative base address of the resource range to be\r
+                                modified by the attributes specified by Attributes.\r
+  @param  Length                A pointer to the length of the resource range to be modified by the\r
+                                attributes specified by Attributes.\r
+\r
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource\r
+                                range specified by BarIndex, Offset, and Length were\r
+                                set on the PCI controller, and the actual resource range is returned\r
+                                in Offset and Length.\r
+  @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the\r
+                                resource range specified by BarIndex, Offset, and\r
+                                Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        NonRelativeOffset;\r
+  UINT64        Supports;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  //\r
+  // Make sure Offset and Length are not NULL\r
+  //\r
+  if (Offset == NULL || Length == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
+  // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
+  //\r
+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+\r
+  if (Attributes != (Attributes & Supports)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and\r
+  // Length are valid for this PCI device.\r
+  //\r
+  NonRelativeOffset = *Offset;\r
+  Status = PciIoVerifyBarAccess (\r
+            PciIoDevice,\r
+            BarIndex,\r
+            PciBarTypeMem,\r
+            EfiPciIoWidthUint8,\r
+            (UINT32) *Length,\r
+            &NonRelativeOffset\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Program parent bridge's attribute recurrently.\r
+\r
+  @param PciIoDevice  Child Pci device instance\r
+  @param Operation    The operation to perform on the attributes for this PCI controller.\r
+  @param Attributes   The mask of attributes that are used for Set, Enable, and Disable\r
+                      operations.\r
+\r
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_UNSUPPORTED       one or more of the bits set in\r
+                                Attributes are not supported by this PCI controller or one of\r
+                                its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+  IN PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN UINT64                                   Attributes\r
+  )\r
+{\r
+  PCI_IO_DEVICE       *Parent;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Parent = PciIoDevice->Parent;\r
+\r
+  while (Parent != NULL && IS_PCI_BRIDGE (&Parent->Pci)) {\r
+\r
+    //\r
+    // Get the PciIo Protocol\r
+    //\r
+    PciIo = &Parent->PciIo;\r
+\r
+    PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
+\r
+    Parent = Parent->Parent;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Test whether two Pci devices has same parent bridge.\r
+\r
+  @param PciDevice1  The first pci device for testing.\r
+  @param PciDevice2  The second pci device for testing.\r
+\r
+  @retval TRUE       Two Pci device has the same parent bridge.\r
+  @retval FALSE      Two Pci device has not the same parent bridge.\r
+\r
+**/\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE        *PciDevice1,\r
+  IN PCI_IO_DEVICE        *PciDevice2\r
+  )\r
+{\r
+  BOOLEAN   Existed1;\r
+  BOOLEAN   Existed2;\r
+\r
+  if (PciDevice1->Parent == PciDevice2->Parent) {\r
+    return TRUE;\r
+  }\r
+\r
+  Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);\r
+  Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);\r
+\r
+  return (BOOLEAN) (Existed1 || Existed2);\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.h
new file mode 100644 (file)
index 0000000..fbfd2b4
--- /dev/null
@@ -0,0 +1,687 @@
+/** @file\r
+  EFI PCI IO protocol functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_IO_PROTOCOL_H_\r
+#define _EFI_PCI_IO_PROTOCOL_H_\r
+\r
+/**\r
+  Initializes a PCI I/O Instance.\r
+\r
+  @param PciIoDevice    Pci device instance.\r
+\r
+**/\r
+VOID\r
+InitializePciIoInstance (\r
+  IN PCI_IO_DEVICE               *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Verifies access to a PCI Base Address Register (BAR).\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param BarIndex     The BAR index of the standard PCI Configuration header to use as the\r
+                      base address for the memory or I/O operation to perform.\r
+  @param Type         Operation type could be memory or I/O.\r
+  @param Width        Signifies the width of the memory or I/O operations.\r
+  @param Count        The number of memory or I/O operations to perform.\r
+  @param Offset       The offset within the PCI configuration space for the PCI controller.\r
+\r
+  @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
+  @retval EFI_SUCCESS           Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  IN PCI_IO_DEVICE                   *PciIoDevice,\r
+  IN UINT8                           BarIndex,\r
+  IN PCI_BAR_TYPE                    Type,\r
+  IN IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN IN UINTN                        Count,\r
+  IN UINT64                          *Offset\r
+  );\r
+\r
+/**\r
+  Verifies access to a PCI Configuration Header.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Width        Signifies the width of the memory or I/O operations.\r
+  @param Count        The number of memory or I/O operations to perform.\r
+  @param Offset       The offset within the PCI configuration space for the PCI controller.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Invalid Width\r
+  @retval EFI_UNSUPPORTED        Offset overflowed.\r
+  @retval EFI_SUCCESS            Successfully verified.\r
+\r
+**/\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  IN PCI_IO_DEVICE              *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+  );\r
+\r
+/**\r
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+  satisfied or after a defined duration.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory operation.\r
+  @param  Mask                  Mask used for the polling criteria.\r
+  @param  Value                 The comparison value used for the polling exit criteria.\r
+  @param  Delay                 The number of 100 ns units to poll.\r
+  @param  Result                Pointer to the last value read from the memory location.\r
+\r
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.\r
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  );\r
+\r
+/**\r
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
+  satisfied or after a defined duration.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory operation.\r
+  @param  Mask                  Mask used for the polling criteria.\r
+  @param  Value                 The comparison value used for the polling exit criteria.\r
+  @param  Delay                 The number of 100 ns units to poll.\r
+  @param  Result                Pointer to the last value read from the memory location.\r
+\r
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.\r
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory or I/O operations.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for the memory or I/O operation to perform.\r
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.\r
+  @param  Count                 The number of memory or I/O operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI BAR specified by BarIndex.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.\r
+  @param  Count                 The number of PCI configuration operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI configuration header of the PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.\r
+  @param  Count                 The number of PCI configuration operations to perform.\r
+  @param  Buffer                For read operations, the destination buffer to store the results. For write\r
+                                operations, the source buffer to write data from.\r
+\r
+\r
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not\r
+                                valid for the PCI configuration header of the PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  );\r
+\r
+/**\r
+  Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
+  memory space.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Width                 Signifies the width of the memory operations.\r
+  @param  DestBarIndex          The BAR index in the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  DestOffset            The destination offset within the BAR specified by DestBarIndex to\r
+                                start the memory writes for the copy operation.\r
+  @param  SrcBarIndex           The BAR index in the standard PCI Configuration header to use as the\r
+                                base address for the memory operation to perform.\r
+  @param  SrcOffset             The source offset within the BAR specified by SrcBarIndex to start\r
+                                the memory reads for the copy operation.\r
+  @param  Count                 The number of memory operations to perform. Bytes moved is Width\r
+                                size * Count, starting at DestOffset and SrcOffset.\r
+\r
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.\r
+  @retval EFI_UNSUPPORTED       DestBarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       SrcBarIndex not valid for this PCI controller.\r
+  @retval EFI_UNSUPPORTED       The address range specified by DestOffset, Width, and Count\r
+                                is not valid for the PCI BAR specified by DestBarIndex.\r
+  @retval EFI_UNSUPPORTED       The address range specified by SrcOffset, Width, and Count is\r
+                                not valid for the PCI BAR specified by SrcBarIndex.\r
+  @retval EFI_INVALID_PARAMETER Width is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+  );\r
+\r
+/**\r
+  Provides the PCI controller-specific addresses needed to access system memory.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.\r
+  @param  HostAddress           The system memory address to map to the PCI controller.\r
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes\r
+                                that were mapped.\r
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to\r
+                                access the hosts HostAddress.\r
+  @param  Mapping               A resulting value to pass to Unmap().\r
+\r
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.\r
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+  );\r
+\r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Mapping               The mapping value returned from Map().\r
+\r
+  @retval EFI_SUCCESS           The range was unmapped.\r
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+  );\r
+\r
+/**\r
+  Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
+  mapping.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Type                  This parameter is not used and must be ignored.\r
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or\r
+                                EfiRuntimeServicesData.\r
+  @param  Pages                 The number of pages to allocate.\r
+  @param  HostAddress           A pointer to store the base system memory address of the\r
+                                allocated range.\r
+  @param  Attributes            The requested bit mask of attributes for the allocated range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 Pages,\r
+  OUT VOID                  **HostAddress,\r
+  IN  UINT64                Attributes\r
+  );\r
+\r
+/**\r
+  Frees memory that was allocated with AllocateBuffer().\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Pages                 The number of pages to free.\r
+  @param  HostAddress           The base system memory address of the allocated range.\r
+\r
+  @retval EFI_SUCCESS           The requested memory pages were freed.\r
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
+                                was not allocated with AllocateBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  );\r
+\r
+/**\r
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host\r
+                                bridge to system memory.\r
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI\r
+                                host bridge due to a hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  );\r
+\r
+/**\r
+  Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  SegmentNumber         The PCI controller's current PCI segment number.\r
+  @param  BusNumber             The PCI controller's current PCI bus number.\r
+  @param  DeviceNumber          The PCI controller's current PCI device number.\r
+  @param  FunctionNumber        The PCI controller's current PCI function number.\r
+\r
+  @retval EFI_SUCCESS           The PCI controller location was returned.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  );\r
+\r
+/**\r
+  Check BAR type for PCI resource.\r
+\r
+  @param PciIoDevice   PCI device instance.\r
+  @param BarIndex      The BAR index of the standard PCI Configuration header to use as the\r
+                       base address for the memory or I/O operation to perform.\r
+  @param BarType       Memory or I/O.\r
+\r
+  @retval TRUE         Pci device's bar type is same with input BarType.\r
+  @retval TRUE         Pci device's bar type is not same with input BarType.\r
+\r
+**/\r
+BOOLEAN\r
+CheckBarType (\r
+  IN PCI_IO_DEVICE          *PciIoDevice,\r
+  IN UINT8                  BarIndex,\r
+  IN PCI_BAR_TYPE           BarType\r
+  );\r
+\r
+/**\r
+  Set/Disable new attributes to a Root Bridge.\r
+\r
+  @param  PciIoDevice  Pci device instance.\r
+  @param  Attributes   New attribute want to be set.\r
+  @param  Operation    Set or Disable.\r
+\r
+  @retval  EFI_UNSUPPORTED  If root bridge does not support change attribute.\r
+  @retval  EFI_SUCCESS      Successfully set new attributs.\r
+\r
+**/\r
+EFI_STATUS\r
+ModifyRootBridgeAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  UINT64                                   Attributes,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation\r
+  );\r
+\r
+/**\r
+  Check whether this device can be enable/disable to snoop.\r
+\r
+  @param PciIoDevice  Pci device instance.\r
+  @param Operation    Enable/Disable.\r
+\r
+  @retval EFI_UNSUPPORTED  Pci device is not GFX device or not support snoop.\r
+  @retval EFI_SUCCESS      Snoop can be supported.\r
+\r
+**/\r
+EFI_STATUS\r
+SupportPaletteSnoopAttributes (\r
+  IN PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation\r
+  );\r
+\r
+/**\r
+  Performs an operation on the attributes that this PCI controller supports. The operations include\r
+  getting the set of supported attributes, retrieving the current attributes, setting the current\r
+  attributes, enabling attributes, and disabling attributes.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Operation             The operation to perform on the attributes for this PCI controller.\r
+  @param  Attributes            The mask of attributes that are used for Set, Enable, and Disable\r
+                                operations.\r
+  @param  Result                A pointer to the result mask of attributes that are returned for the Get\r
+                                and Supported operations.\r
+\r
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_UNSUPPORTED       one or more of the bits set in\r
+                                Attributes are not supported by this PCI controller or one of\r
+                                its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL                       * This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result OPTIONAL\r
+  );\r
+\r
+/**\r
+  Gets the attributes that this PCI controller supports setting on a BAR using\r
+  SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for resource range. The legal range for this field is 0..5.\r
+  @param  Supports              A pointer to the mask of attributes that this PCI controller supports\r
+                                setting for this BAR with SetBarAttributes().\r
+  @param  Resources             A pointer to the ACPI 2.0 resource descriptors that describe the current\r
+                                configuration of this BAR of the PCI controller.\r
+\r
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI\r
+                                controller supports are returned in Supports. If Resources\r
+                                is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
+                                controller is currently using are returned in Resources.\r
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate\r
+                                Resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL             * This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports, OPTIONAL\r
+  OUT VOID                           **Resources OPTIONAL\r
+  );\r
+\r
+/**\r
+  Sets the attributes for a range of a BAR on a PCI controller.\r
+\r
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
+  @param  Attributes            The mask of attributes to set for the resource range specified by\r
+                                BarIndex, Offset, and Length.\r
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the\r
+                                base address for resource range. The legal range for this field is 0..5.\r
+  @param  Offset                A pointer to the BAR relative base address of the resource range to be\r
+                                modified by the attributes specified by Attributes.\r
+  @param  Length                A pointer to the length of the resource range to be modified by the\r
+                                attributes specified by Attributes.\r
+\r
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource\r
+                                range specified by BarIndex, Offset, and Length were\r
+                                set on the PCI controller, and the actual resource range is returned\r
+                                in Offset and Length.\r
+  @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the\r
+                                resource range specified by BarIndex, Offset, and\r
+                                Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  );\r
+\r
+/**\r
+  Program parent bridge's attribute recurrently.\r
+\r
+  @param PciIoDevice  Child Pci device instance\r
+  @param Operation    The operation to perform on the attributes for this PCI controller.\r
+  @param Attributes   The mask of attributes that are used for Set, Enable, and Disable\r
+                      operations.\r
+\r
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.\r
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
+  @retval EFI_UNSUPPORTED       one or more of the bits set in\r
+                                Attributes are not supported by this PCI controller or one of\r
+                                its parent bridges when Operation is Set, Enable or Disable.\r
+\r
+**/\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+  IN PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN UINT64                                   Attributes\r
+  );\r
+\r
+/**\r
+  Test whether two Pci devices has same parent bridge.\r
+\r
+  @param PciDevice1  The first pci device for testing.\r
+  @param PciDevice2  The second pci device for testing.\r
+\r
+  @retval TRUE       Two Pci device has the same parent bridge.\r
+  @retval FALSE      Two Pci device has not the same parent bridge.\r
+\r
+**/\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE        *PciDevice1,\r
+  IN PCI_IO_DEVICE        *PciDevice2\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
new file mode 100644 (file)
index 0000000..f400006
--- /dev/null
@@ -0,0 +1,1359 @@
+/** @file\r
+  Internal library implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+\r
+/**\r
+  Retrieve the PCI Card device BAR information via PciIo interface.\r
+\r
+  @param PciIoDevice        PCI Card device instance.\r
+\r
+**/\r
+VOID\r
+GetBackPcCardBar (\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+  )\r
+{\r
+  UINT32  Address;\r
+\r
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Read PciBar information from the bar register\r
+  //\r
+  if (!gFullEnumeration) {\r
+    Address = 0;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoWidthUint32,\r
+                             PCI_CARD_MEMORY_BASE_0,\r
+                             1,\r
+                             &Address\r
+                             );\r
+\r
+    (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress  = (UINT64) (Address);\r
+    (PciIoDevice->PciBar)[P2C_MEM_1].Length       = 0x2000000;\r
+    (PciIoDevice->PciBar)[P2C_MEM_1].BarType      = PciBarTypeMem32;\r
+\r
+    Address = 0;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoWidthUint32,\r
+                             PCI_CARD_MEMORY_BASE_1,\r
+                             1,\r
+                             &Address\r
+                             );\r
+    (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress  = (UINT64) (Address);\r
+    (PciIoDevice->PciBar)[P2C_MEM_2].Length       = 0x2000000;\r
+    (PciIoDevice->PciBar)[P2C_MEM_2].BarType      = PciBarTypePMem32;\r
+\r
+    Address = 0;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoWidthUint32,\r
+                             PCI_CARD_IO_BASE_0_LOWER,\r
+                             1,\r
+                             &Address\r
+                             );\r
+    (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);\r
+    (PciIoDevice->PciBar)[P2C_IO_1].Length      = 0x100;\r
+    (PciIoDevice->PciBar)[P2C_IO_1].BarType     = PciBarTypeIo16;\r
+\r
+    Address = 0;\r
+    PciIoDevice->PciIo.Pci.Read (\r
+                             &(PciIoDevice->PciIo),\r
+                             EfiPciIoWidthUint32,\r
+                             PCI_CARD_IO_BASE_1_LOWER,\r
+                             1,\r
+                             &Address\r
+                             );\r
+    (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);\r
+    (PciIoDevice->PciBar)[P2C_IO_2].Length      = 0x100;\r
+    (PciIoDevice->PciBar)[P2C_IO_2].BarType     = PciBarTypeIo16;\r
+\r
+  }\r
+\r
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    GetResourcePaddingForHpb (PciIoDevice);\r
+  }\r
+}\r
+\r
+/**\r
+  Remove rejected pci device from specific root bridge\r
+  handle.\r
+\r
+  @param RootBridgeHandle  Specific parent root bridge handle.\r
+  @param Bridge            Bridge device instance.\r
+\r
+**/\r
+VOID\r
+RemoveRejectedPciDevices (\r
+  IN EFI_HANDLE        RootBridgeHandle,\r
+  IN PCI_IO_DEVICE     *Bridge\r
+  )\r
+{\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+  LIST_ENTRY      *LastLink;\r
+\r
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    return;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+      //\r
+      // Remove rejected devices recusively\r
+      //\r
+      RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
+    } else {\r
+      //\r
+      // Skip rejection for all PPBs, while detect rejection for others\r
+      //\r
+      if (IsPciDeviceRejected (Temp)) {\r
+\r
+        //\r
+        // For P2C, remove all devices on it\r
+        //\r
+        if (!IsListEmpty (&Temp->ChildList)) {\r
+          RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
+        }\r
+\r
+        //\r
+        // Finally remove itself\r
+        //\r
+        LastLink = CurrentLink->BackLink;\r
+        RemoveEntryList (CurrentLink);\r
+        FreePciDevice (Temp);\r
+\r
+        CurrentLink = LastLink;\r
+      }\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
+\r
+  @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS           Successfully finished resource allocation.\r
+  @retval EFI_NOT_FOUND         Cannot get root bridge instance.\r
+  @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.\r
+  @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeResourceAllocator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  )\r
+{\r
+  PCI_IO_DEVICE                                  *RootBridgeDev;\r
+  EFI_HANDLE                                     RootBridgeHandle;\r
+  VOID                                           *AcpiConfig;\r
+  EFI_STATUS                                     Status;\r
+  UINT64                                         IoBase;\r
+  UINT64                                         Mem32Base;\r
+  UINT64                                         PMem32Base;\r
+  UINT64                                         Mem64Base;\r
+  UINT64                                         PMem64Base;\r
+  UINT64                                         IoResStatus;\r
+  UINT64                                         Mem32ResStatus;\r
+  UINT64                                         PMem32ResStatus;\r
+  UINT64                                         Mem64ResStatus;\r
+  UINT64                                         PMem64ResStatus;\r
+  UINT64                                         MaxOptionRomSize;\r
+  PCI_RESOURCE_NODE                              *IoBridge;\r
+  PCI_RESOURCE_NODE                              *Mem32Bridge;\r
+  PCI_RESOURCE_NODE                              *PMem32Bridge;\r
+  PCI_RESOURCE_NODE                              *Mem64Bridge;\r
+  PCI_RESOURCE_NODE                              *PMem64Bridge;\r
+  PCI_RESOURCE_NODE                              IoPool;\r
+  PCI_RESOURCE_NODE                              Mem32Pool;\r
+  PCI_RESOURCE_NODE                              PMem32Pool;\r
+  PCI_RESOURCE_NODE                              Mem64Pool;\r
+  PCI_RESOURCE_NODE                              PMem64Pool;\r
+  BOOLEAN                                        ReAllocate;\r
+  EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD        HandleExtendedData;\r
+  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD  AllocFailExtendedData;\r
+\r
+  //\r
+  // Reallocate flag\r
+  //\r
+  ReAllocate = FALSE;\r
+\r
+  //\r
+  // It may try several times if the resource allocation fails\r
+  //\r
+  while (TRUE) {\r
+    //\r
+    // Initialize resource pool\r
+    //\r
+    InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
+    InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
+    InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
+    InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
+    InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
+\r
+    RootBridgeDev     = NULL;\r
+    RootBridgeHandle  = 0;\r
+\r
+    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+      //\r
+      // Get Root Bridge Device by handle\r
+      //\r
+      RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+      if (RootBridgeDev == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Create the entire system resource map from the information collected by\r
+      // enumerator. Several resource tree was created\r
+      //\r
+\r
+      IoBridge = CreateResourceNode (\r
+                   RootBridgeDev,\r
+                   0,\r
+                   0xFFF,\r
+                   0,\r
+                   PciBarTypeIo16,\r
+                   PciResUsageTypical\r
+                   );\r
+\r
+      Mem32Bridge = CreateResourceNode (\r
+                      RootBridgeDev,\r
+                      0,\r
+                      0xFFFFF,\r
+                      0,\r
+                      PciBarTypeMem32,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem32Bridge = CreateResourceNode (\r
+                       RootBridgeDev,\r
+                       0,\r
+                       0xFFFFF,\r
+                       0,\r
+                       PciBarTypePMem32,\r
+                       PciResUsageTypical\r
+                       );\r
+\r
+      Mem64Bridge = CreateResourceNode (\r
+                      RootBridgeDev,\r
+                      0,\r
+                      0xFFFFF,\r
+                      0,\r
+                      PciBarTypeMem64,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem64Bridge = CreateResourceNode (\r
+                       RootBridgeDev,\r
+                       0,\r
+                       0xFFFFF,\r
+                       0,\r
+                       PciBarTypePMem64,\r
+                       PciResUsageTypical\r
+                       );\r
+\r
+      //\r
+      // Create resourcemap by going through all the devices subject to this root bridge\r
+      //\r
+      CreateResourceMap (\r
+        RootBridgeDev,\r
+        IoBridge,\r
+        Mem32Bridge,\r
+        PMem32Bridge,\r
+        Mem64Bridge,\r
+        PMem64Bridge\r
+        );\r
+\r
+      //\r
+      // Get the max ROM size that the root bridge can process\r
+      //\r
+      RootBridgeDev->RomSize = Mem32Bridge->Length;\r
+\r
+      //\r
+      // Skip to enlarge the resource request during realloction\r
+      //\r
+      if (!ReAllocate) {\r
+        //\r
+        // Get Max Option Rom size for current root bridge\r
+        //\r
+        MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
+\r
+        //\r
+        // Enlarger the mem32 resource to accomdate the option rom\r
+        // if the mem32 resource is not enough to hold the rom\r
+        //\r
+        if (MaxOptionRomSize > Mem32Bridge->Length) {\r
+\r
+          Mem32Bridge->Length     = MaxOptionRomSize;\r
+          RootBridgeDev->RomSize  = MaxOptionRomSize;\r
+\r
+          //\r
+          // Alignment should be adjusted as well\r
+          //\r
+          if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {\r
+            Mem32Bridge->Alignment = MaxOptionRomSize - 1;\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      // Based on the all the resource tree, contruct ACPI resource node to\r
+      // submit the resource aperture to pci host bridge protocol\r
+      //\r
+      Status = ConstructAcpiResourceRequestor (\r
+                 RootBridgeDev,\r
+                 IoBridge,\r
+                 Mem32Bridge,\r
+                 PMem32Bridge,\r
+                 Mem64Bridge,\r
+                 PMem64Bridge,\r
+                 &AcpiConfig\r
+                 );\r
+\r
+      //\r
+      // Insert these resource nodes into the database\r
+      //\r
+      InsertResourceNode (&IoPool, IoBridge);\r
+      InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
+      InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
+      InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
+      InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
+\r
+      if (Status == EFI_SUCCESS) {\r
+        //\r
+        // Submit the resource requirement\r
+        //\r
+        Status = PciResAlloc->SubmitResources (\r
+                                PciResAlloc,\r
+                                RootBridgeDev->Handle,\r
+                                AcpiConfig\r
+                                );\r
+      }\r
+\r
+      //\r
+      // Free acpi resource node\r
+      //\r
+      if (AcpiConfig != NULL) {\r
+        FreePool (AcpiConfig);\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Destroy all the resource tree\r
+        //\r
+        DestroyResourceTree (&IoPool);\r
+        DestroyResourceTree (&Mem32Pool);\r
+        DestroyResourceTree (&PMem32Pool);\r
+        DestroyResourceTree (&Mem64Pool);\r
+        DestroyResourceTree (&PMem64Pool);\r
+        return Status;\r
+      }\r
+    }\r
+    //\r
+    // End while, at least one Root Bridge should be found.\r
+    //\r
+    ASSERT (RootBridgeDev != NULL);\r
+\r
+    //\r
+    // Notify platform to start to program the resource\r
+    //\r
+    Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
+    if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+      //\r
+      // If Hot Plug is not supported\r
+      //\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Allocation failed, then return\r
+        //\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Allocation succeed.\r
+      // Get host bridge handle for status report, and then skip the main while\r
+      //\r
+      HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
+\r
+      break;\r
+\r
+    } else {\r
+      //\r
+      // If Hot Plug is supported\r
+      //\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Allocation succeed, then continue the following\r
+        //\r
+        break;\r
+      }\r
+\r
+      //\r
+      // If the resource allocation is unsuccessful, free resources on bridge\r
+      //\r
+\r
+      RootBridgeDev     = NULL;\r
+      RootBridgeHandle  = 0;\r
+\r
+      IoResStatus       = EFI_RESOURCE_SATISFIED;\r
+      Mem32ResStatus    = EFI_RESOURCE_SATISFIED;\r
+      PMem32ResStatus   = EFI_RESOURCE_SATISFIED;\r
+      Mem64ResStatus    = EFI_RESOURCE_SATISFIED;\r
+      PMem64ResStatus   = EFI_RESOURCE_SATISFIED;\r
+\r
+      while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+        //\r
+        // Get RootBridg Device by handle\r
+        //\r
+        RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+        if (RootBridgeDev == NULL) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        //\r
+        // Get host bridge handle for status report\r
+        //\r
+        HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
+\r
+        //\r
+        // Get acpi resource node for all the resource types\r
+        //\r
+        AcpiConfig = NULL;\r
+\r
+        Status = PciResAlloc->GetProposedResources (\r
+                                PciResAlloc,\r
+                                RootBridgeDev->Handle,\r
+                                &AcpiConfig\r
+                                );\r
+\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        if (AcpiConfig != NULL) {\r
+          //\r
+          // Adjust resource allocation policy for each RB\r
+          //\r
+          GetResourceAllocationStatus (\r
+            AcpiConfig,\r
+            &IoResStatus,\r
+            &Mem32ResStatus,\r
+            &PMem32ResStatus,\r
+            &Mem64ResStatus,\r
+            &PMem64ResStatus\r
+            );\r
+          FreePool (AcpiConfig);\r
+        }\r
+      }\r
+      //\r
+      // End while\r
+      //\r
+\r
+      //\r
+      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
+      //\r
+      //\r
+      // It is very difficult to follow the spec here\r
+      // Device path , Bar index can not be get here\r
+      //\r
+      ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
+\r
+      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+            EFI_PROGRESS_CODE,\r
+            EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
+            (VOID *) &AllocFailExtendedData,\r
+            sizeof (AllocFailExtendedData)\r
+            );\r
+\r
+      Status = PciHostBridgeAdjustAllocation (\r
+                 &IoPool,\r
+                 &Mem32Pool,\r
+                 &PMem32Pool,\r
+                 &Mem64Pool,\r
+                 &PMem64Pool,\r
+                 IoResStatus,\r
+                 Mem32ResStatus,\r
+                 PMem32ResStatus,\r
+                 Mem64ResStatus,\r
+                 PMem64ResStatus\r
+                 );\r
+\r
+      //\r
+      // Destroy all the resource tree\r
+      //\r
+      DestroyResourceTree (&IoPool);\r
+      DestroyResourceTree (&Mem32Pool);\r
+      DestroyResourceTree (&PMem32Pool);\r
+      DestroyResourceTree (&Mem64Pool);\r
+      DestroyResourceTree (&PMem64Pool);\r
+\r
+      NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ReAllocate = TRUE;\r
+    }\r
+  }\r
+  //\r
+  // End main while\r
+  //\r
+\r
+  //\r
+  // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
+  //\r
+  REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
+        EFI_PROGRESS_CODE,\r
+        EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,\r
+        (VOID *) &HandleExtendedData,\r
+        sizeof (HandleExtendedData)\r
+        );\r
+\r
+  //\r
+  // Notify pci bus driver starts to program the resource\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
+\r
+  RootBridgeDev     = NULL;\r
+\r
+  RootBridgeHandle  = 0;\r
+\r
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+    //\r
+    // Get RootBridg Device by handle\r
+    //\r
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Get acpi resource node for all the resource types\r
+    //\r
+    AcpiConfig = NULL;\r
+    Status = PciResAlloc->GetProposedResources (\r
+                            PciResAlloc,\r
+                            RootBridgeDev->Handle,\r
+                            &AcpiConfig\r
+                            );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Get the resource base by interpreting acpi resource node\r
+    //\r
+    //\r
+    GetResourceBase (\r
+      AcpiConfig,\r
+      &IoBase,\r
+      &Mem32Base,\r
+      &PMem32Base,\r
+      &Mem64Base,\r
+      &PMem64Base\r
+      );\r
+\r
+    //\r
+    // Process option rom for this root bridge\r
+    //\r
+    ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);\r
+\r
+    //\r
+    // Create the entire system resource map from the information collected by\r
+    // enumerator. Several resource tree was created\r
+    //\r
+    GetResourceMap (\r
+      RootBridgeDev,\r
+      &IoBridge,\r
+      &Mem32Bridge,\r
+      &PMem32Bridge,\r
+      &Mem64Bridge,\r
+      &PMem64Bridge,\r
+      &IoPool,\r
+      &Mem32Pool,\r
+      &PMem32Pool,\r
+      &Mem64Pool,\r
+      &PMem64Pool\r
+      );\r
+\r
+    //\r
+    // Program IO resources\r
+    //\r
+    ProgramResource (\r
+      IoBase,\r
+      IoBridge\r
+      );\r
+\r
+    //\r
+    // Program Mem32 resources\r
+    //\r
+    ProgramResource (\r
+      Mem32Base,\r
+      Mem32Bridge\r
+      );\r
+\r
+    //\r
+    // Program PMem32 resources\r
+    //\r
+    ProgramResource (\r
+      PMem32Base,\r
+      PMem32Bridge\r
+      );\r
+\r
+    //\r
+    // Program Mem64 resources\r
+    //\r
+    ProgramResource (\r
+      Mem64Base,\r
+      Mem64Bridge\r
+      );\r
+\r
+    //\r
+    // Program PMem64 resources\r
+    //\r
+    ProgramResource (\r
+      PMem64Base,\r
+      PMem64Bridge\r
+      );\r
+\r
+    FreePool (AcpiConfig);\r
+  }\r
+\r
+  //\r
+  // Destroy all the resource tree\r
+  //\r
+  DestroyResourceTree (&IoPool);\r
+  DestroyResourceTree (&Mem32Pool);\r
+  DestroyResourceTree (&PMem32Pool);\r
+  DestroyResourceTree (&Mem64Pool);\r
+  DestroyResourceTree (&PMem64Pool);\r
+\r
+  //\r
+  // Notify the resource allocation phase is to end\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Scan pci bus and assign bus number to the given PCI bus system.\r
+\r
+  @param  Bridge           Bridge device instance.\r
+  @param  StartBusNumber   start point.\r
+  @param  SubBusNumber     Point to sub bus number.\r
+  @param  PaddedBusRange   Customized bus number.\r
+\r
+  @retval EFI_SUCCESS      Successfully scanned and assigned bus number.\r
+  @retval other            Some error occurred when scanning pci bus.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciScanBus (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber,\r
+  OUT UINT8                             *SubBusNumber,\r
+  OUT UINT8                             *PaddedBusRange\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  PCI_TYPE00                        Pci;\r
+  UINT8                             Device;\r
+  UINT8                             Func;\r
+  UINT64                            Address;\r
+  UINTN                             SecondBus;\r
+  UINT16                            Register;\r
+  UINTN                             HpIndex;\r
+  PCI_IO_DEVICE                     *PciDevice;\r
+  EFI_EVENT                         Event;\r
+  EFI_HPC_STATE                     State;\r
+  UINT64                            PciAddress;\r
+  EFI_HPC_PADDING_ATTRIBUTES        Attributes;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+  UINT16                            BusRange;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
+  BOOLEAN                           BusPadding;\r
+  UINT32                            TempReservedBusNum;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  SecondBus       = 0;\r
+  Register        = 0;\r
+  State           = 0;\r
+  Attributes      = (EFI_HPC_PADDING_ATTRIBUTES) 0;\r
+  BusRange        = 0;\r
+  BusPadding      = FALSE;\r
+  PciDevice       = NULL;\r
+  PciAddress      = 0;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+    TempReservedBusNum = 0;\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether a pci device is present\r
+      //\r
+      Status = PciDevicePresent (\r
+                PciRootBridgeIo,\r
+                &Pci,\r
+                StartBusNumber,\r
+                Device,\r
+                Func\r
+                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        if (Func == 0) {\r
+          //\r
+          // Skip sub functions, this is not a multi function device\r
+          //\r
+          Func = PCI_MAX_FUNC;\r
+        }\r
+\r
+        continue;\r
+      }\r
+\r
+      DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));\r
+\r
+      if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+        //\r
+        // Get the PCI device information\r
+        //\r
+        Status = PciSearchDevice (\r
+                  Bridge,\r
+                  &Pci,\r
+                  StartBusNumber,\r
+                  Device,\r
+                  Func,\r
+                  &PciDevice\r
+                  );\r
+\r
+        ASSERT (!EFI_ERROR (Status));\r
+\r
+        PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
+\r
+        if (!IS_PCI_BRIDGE (&Pci)) {\r
+          //\r
+          // PCI bridges will be called later\r
+          // Here just need for PCI device or PCI to cardbus controller\r
+          // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
+          //\r
+          PreprocessController (\r
+              PciDevice,\r
+              PciDevice->BusNumber,\r
+              PciDevice->DeviceNumber,\r
+              PciDevice->FunctionNumber,\r
+              EfiPciBeforeChildBusEnumeration\r
+              );\r
+        }\r
+\r
+        //\r
+        // For Pci Hotplug controller devcie only\r
+        //\r
+        if (gPciHotPlugInit != NULL) {\r
+          //\r
+          // Check if it is a Hotplug PCI controller\r
+          //\r
+          if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
+\r
+            if (!gPciRootHpcData[HpIndex].Initialized) {\r
+\r
+              Status = CreateEventForHpc (HpIndex, &Event);\r
+\r
+              ASSERT (!EFI_ERROR (Status));\r
+\r
+              Status = gPciHotPlugInit->InitializeRootHpc (\r
+                                          gPciHotPlugInit,\r
+                                          gPciRootHpcPool[HpIndex].HpcDevicePath,\r
+                                          PciAddress,\r
+                                          Event,\r
+                                          &State\r
+                                          );\r
+\r
+              PreprocessController (\r
+                PciDevice,\r
+                PciDevice->BusNumber,\r
+                PciDevice->DeviceNumber,\r
+                PciDevice->FunctionNumber,\r
+                EfiPciBeforeChildBusEnumeration\r
+              );\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
+        //\r
+        // For PPB\r
+        //\r
+        if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+          //\r
+          // If Hot Plug is not supported,\r
+          // get the bridge information\r
+          //\r
+          Status = PciSearchDevice (\r
+                    Bridge,\r
+                    &Pci,\r
+                    StartBusNumber,\r
+                    Device,\r
+                    Func,\r
+                    &PciDevice\r
+                    );\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        } else {\r
+          //\r
+          // If Hot Plug is supported,\r
+          // Get the bridge information\r
+          //\r
+          BusPadding = FALSE;\r
+          if (gPciHotPlugInit != NULL) {\r
+\r
+            if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {\r
+\r
+              //\r
+              // If it is initialized, get the padded bus range\r
+              //\r
+              Status = gPciHotPlugInit->GetResourcePadding (\r
+                                          gPciHotPlugInit,\r
+                                          gPciRootHpcPool[HpIndex].HpbDevicePath,\r
+                                          PciAddress,\r
+                                          &State,\r
+                                          (VOID **) &Descriptors,\r
+                                          &Attributes\r
+                                          );\r
+\r
+              if (EFI_ERROR (Status)) {\r
+                return Status;\r
+              }\r
+\r
+              BusRange = 0;\r
+              Status = PciGetBusRange (\r
+                        &Descriptors,\r
+                        NULL,\r
+                        NULL,\r
+                        &BusRange\r
+                        );\r
+\r
+              FreePool (Descriptors);\r
+\r
+              if (EFI_ERROR (Status)) {\r
+                return Status;\r
+              }\r
+\r
+              BusPadding = TRUE;\r
+            }\r
+          }\r
+        }\r
+\r
+        //\r
+        // Add feature to support customized secondary bus number\r
+        //\r
+        if (*SubBusNumber == 0) {\r
+          *SubBusNumber   = *PaddedBusRange;\r
+          *PaddedBusRange = 0;\r
+        }\r
+\r
+        (*SubBusNumber)++;\r
+        SecondBus = *SubBusNumber;\r
+\r
+        Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);\r
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
+\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint16,\r
+                                        Address,\r
+                                        1,\r
+                                        &Register\r
+                                        );\r
+\r
+\r
+        //\r
+        // If it is PPB, resursively search down this bridge\r
+        //\r
+        if (IS_PCI_BRIDGE (&Pci)) {\r
+\r
+          //\r
+          // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
+          // PCI configuration transaction to go through any PPB\r
+          //\r
+          Register  = 0xFF;\r
+          Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
+          Status = PciRootBridgeIo->Pci.Write (\r
+                                          PciRootBridgeIo,\r
+                                          EfiPciWidthUint8,\r
+                                          Address,\r
+                                          1,\r
+                                          &Register\r
+                                          );\r
+\r
+          //\r
+          // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
+          //\r
+          PreprocessController (\r
+            PciDevice,\r
+            PciDevice->BusNumber,\r
+            PciDevice->DeviceNumber,\r
+            PciDevice->FunctionNumber,\r
+            EfiPciBeforeChildBusEnumeration\r
+            );\r
+\r
+          DEBUG((EFI_D_INFO, "Scan  PPB(%02d,%02d,%02d)\n", PciDevice->BusNumber, PciDevice->DeviceNumber,PciDevice->FunctionNumber));\r
+          Status = PciScanBus (\r
+                    PciDevice,\r
+                    (UINT8) (SecondBus),\r
+                    SubBusNumber,\r
+                    PaddedBusRange\r
+                    );\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        }\r
+\r
+        if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
+          //\r
+          // Ensure the device is enabled and initialized\r
+          //\r
+          if ((Attributes == EfiPaddingPciRootBridge) &&\r
+              (State & EFI_HPC_STATE_ENABLED) != 0    &&\r
+              (State & EFI_HPC_STATE_INITIALIZED) != 0) {\r
+            *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);\r
+          } else {\r
+            *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);\r
+          }\r
+        }\r
+\r
+        //\r
+        // Set the current maximum bus number under the PPB\r
+        //\r
+        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
+\r
+        Status = PciRootBridgeIo->Pci.Write (\r
+                                        PciRootBridgeIo,\r
+                                        EfiPciWidthUint8,\r
+                                        Address,\r
+                                        1,\r
+                                        SubBusNumber\r
+                                        );\r
+      } else  {\r
+        //\r
+        // It is device. Check PCI IOV for Bus reservation\r
+        //\r
+        if (PciDevice == NULL) {\r
+          //\r
+          // No PciDevice found, conitue Scan\r
+          //\r
+          continue;\r
+        }\r
+        //\r
+        // Go through each function, just reserve the MAX ReservedBusNum for one device\r
+        //\r
+        if ((PciDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+\r
+          if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
+\r
+            (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);\r
+            TempReservedBusNum = PciDevice->ReservedBusNum;\r
+\r
+            if (Func == 0) {\r
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
+            } else {\r
+              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+        //\r
+        // Skip sub functions, this is not a multi function device\r
+        //\r
+\r
+        Func = PCI_MAX_FUNC;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Process Option Rom on the specified root bridge.\r
+\r
+  @param Bridge  Pci root bridge device instance.\r
+\r
+  @retval EFI_SUCCESS   Success process.\r
+  @retval other         Some error occurred when processing Option Rom on the root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeP2CProcess (\r
+  IN PCI_IO_DEVICE *Bridge\r
+  )\r
+{\r
+  LIST_ENTRY      *CurrentLink;\r
+  PCI_IO_DEVICE   *Temp;\r
+  EFI_HPC_STATE   State;\r
+  UINT64          PciAddress;\r
+  EFI_STATUS      Status;\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+\r
+      if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+\r
+        //\r
+        // Raise the EFI_IOB_PCI_HPC_INIT status code\r
+        //\r
+        REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+          EFI_PROGRESS_CODE,\r
+          EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,\r
+          Temp->DevicePath\r
+          );\r
+\r
+        PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
+        Status = gPciHotPlugInit->InitializeRootHpc (\r
+                                    gPciHotPlugInit,\r
+                                    Temp->DevicePath,\r
+                                    PciAddress,\r
+                                    NULL,\r
+                                    &State\r
+                                    );\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          Status = PciBridgeEnumerator (Temp);\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        }\r
+\r
+        CurrentLink = CurrentLink->ForwardLink;\r
+        continue;\r
+\r
+      }\r
+    }\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      Status = PciRootBridgeP2CProcess (Temp);\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Process Option Rom on the specified host bridge.\r
+\r
+  @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS   Success process.\r
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+  @retval other         Some error occurred when processing Option Rom on the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  )\r
+{\r
+  EFI_HANDLE    RootBridgeHandle;\r
+  PCI_IO_DEVICE *RootBridgeDev;\r
+  EFI_STATUS    Status;\r
+\r
+  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  RootBridgeHandle = NULL;\r
+\r
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // Get RootBridg Device by handle\r
+    //\r
+    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to enumerate the entire host bridge\r
+  in a given platform.\r
+\r
+  @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.\r
+\r
+  @retval EFI_SUCCESS            Successfully enumerated the host bridge.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory available.\r
+  @retval other                  Some error occurred when enumerating the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeEnumerator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc\r
+  )\r
+{\r
+  EFI_HANDLE                        RootBridgeHandle;\r
+  PCI_IO_DEVICE                     *RootBridgeDev;\r
+  EFI_STATUS                        Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
+  UINT16                            MinBus;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+  UINT8                             StartBusNumber;\r
+  LIST_ENTRY                        RootBridgeList;\r
+  LIST_ENTRY                        *Link;\r
+\r
+  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    InitializeHotPlugSupport ();\r
+  }\r
+\r
+  InitializeListHead (&RootBridgeList);\r
+\r
+  //\r
+  // Notify the bus allocation phase is about to start\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+  DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));\r
+  RootBridgeHandle = NULL;\r
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // if a root bridge instance is found, create root bridge device for it\r
+    //\r
+\r
+    RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Enumerate all the buses under this root bridge\r
+    //\r
+    Status = PciRootBridgeEnumerator (\r
+              PciResAlloc,\r
+              RootBridgeDev\r
+              );\r
+\r
+    if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+      InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
+    } else {\r
+      DestroyRootBridge (RootBridgeDev);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Notify the bus allocation phase is finished for the first time\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
+\r
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    //\r
+    // Reset all assigned PCI bus number in all PPB\r
+    //\r
+    RootBridgeHandle = NULL;\r
+    Link = GetFirstNode (&RootBridgeList);\r
+    while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
+      (!IsNull (&RootBridgeList, Link))) {\r
+      RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
+      //\r
+      // Get the Bus information\r
+      //\r
+      Status = PciResAlloc->StartBusEnumeration (\r
+                              PciResAlloc,\r
+                              RootBridgeHandle,\r
+                              (VOID **) &Configuration\r
+                              );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Get the bus number to start with\r
+      //\r
+      StartBusNumber  = (UINT8) (Configuration->AddrRangeMin);\r
+\r
+      ResetAllPpbBusNumber (\r
+        RootBridgeDev,\r
+        StartBusNumber\r
+      );\r
+\r
+      FreePool (Configuration);\r
+      Link = GetNextNode (&RootBridgeList, Link);\r
+      DestroyRootBridge (RootBridgeDev);\r
+    }\r
+\r
+    //\r
+    // Wait for all HPC initialized\r
+    //\r
+    Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Notify the bus allocation phase is about to start for the 2nd time\r
+    //\r
+    NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
+\r
+    DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));\r
+    RootBridgeHandle = NULL;\r
+    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+      //\r
+      // if a root bridge instance is found, create root bridge device for it\r
+      //\r
+      RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+      if (RootBridgeDev == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      //\r
+      // Enumerate all the buses under this root bridge\r
+      //\r
+      Status = PciRootBridgeEnumerator (\r
+                PciResAlloc,\r
+                RootBridgeDev\r
+                );\r
+\r
+      DestroyRootBridge (RootBridgeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Notify the bus allocation phase is to end for the 2nd time\r
+    //\r
+    NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
+  }\r
+\r
+  //\r
+  // Notify the resource allocation phase is to start\r
+  //\r
+  NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
+\r
+  RootBridgeHandle = NULL;\r
+  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // if a root bridge instance is found, create root bridge device for it\r
+    //\r
+    RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
+\r
+    if (RootBridgeDev == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Status = StartManagingRootBridge (RootBridgeDev);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
+    Status          = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Determine root bridge attribute by calling interface of Pcihostbridge\r
+    // protocol\r
+    //\r
+    DetermineRootBridgeAttributes (\r
+      PciResAlloc,\r
+      RootBridgeDev\r
+      );\r
+\r
+    //\r
+    // Collect all the resource information under this root bridge\r
+    // A database that records all the information about pci device subject to this\r
+    // root bridge will then be created\r
+    //\r
+    Status = PciPciDeviceInfoCollector (\r
+              RootBridgeDev,\r
+              (UINT8) MinBus\r
+              );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    InsertRootBridge (RootBridgeDev);\r
+\r
+    //\r
+    // Record the hostbridge handle\r
+    //\r
+    AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
new file mode 100644 (file)
index 0000000..43e3e48
--- /dev/null
@@ -0,0 +1,144 @@
+/** @file\r
+  Internal library declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_LIB_H_\r
+#define _EFI_PCI_LIB_H_\r
+\r
+\r
+typedef struct {\r
+  EFI_HANDLE            Handle;\r
+} EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD;\r
+\r
+typedef struct {\r
+  UINT32                             Bar;\r
+  UINT16                             DevicePathSize;\r
+  UINT16                             ReqResSize;\r
+  UINT16                             AllocResSize;\r
+  UINT8                              *DevicePath;\r
+  UINT8                              *ReqRes;\r
+  UINT8                              *AllocRes;\r
+} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD;\r
+\r
+\r
+/**\r
+  Retrieve the PCI Card device BAR information via PciIo interface.\r
+\r
+  @param PciIoDevice        PCI Card device instance.\r
+\r
+**/\r
+VOID\r
+GetBackPcCardBar (\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Remove rejected pci device from specific root bridge\r
+  handle.\r
+\r
+  @param RootBridgeHandle  Specific parent root bridge handle.\r
+  @param Bridge            Bridge device instance.\r
+\r
+**/\r
+VOID\r
+RemoveRejectedPciDevices (\r
+  IN EFI_HANDLE        RootBridgeHandle,\r
+  IN PCI_IO_DEVICE     *Bridge\r
+  );\r
+\r
+/**\r
+  Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
+\r
+  @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS           Successfully finished resource allocation.\r
+  @retval EFI_NOT_FOUND         Cannot get root bridge instance.\r
+  @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.\r
+  @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeResourceAllocator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  );\r
+\r
+/**\r
+  Scan pci bus and assign bus number to the given PCI bus system.\r
+\r
+  @param  Bridge           Bridge device instance.\r
+  @param  StartBusNumber   start point.\r
+  @param  SubBusNumber     Point to sub bus number.\r
+  @param  PaddedBusRange   Customized bus number.\r
+\r
+  @retval EFI_SUCCESS      Successfully scanned and assigned bus number.\r
+  @retval other            Some error occurred when scanning pci bus.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
+\r
+**/\r
+EFI_STATUS\r
+PciScanBus (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber,\r
+  OUT UINT8                             *SubBusNumber,\r
+  OUT UINT8                             *PaddedBusRange\r
+  );\r
+\r
+/**\r
+  Process Option Rom on the specified root bridge.\r
+\r
+  @param Bridge  Pci root bridge device instance.\r
+\r
+  @retval EFI_SUCCESS   Success process.\r
+  @retval other         Some error occurred when processing Option Rom on the root bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciRootBridgeP2CProcess (\r
+  IN PCI_IO_DEVICE *Bridge\r
+  );\r
+\r
+/**\r
+  Process Option Rom on the specified host bridge.\r
+\r
+  @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
+\r
+  @retval EFI_SUCCESS   Success process.\r
+  @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
+  @retval other         Some error occurred when processing Option Rom on the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeP2CProcess (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
+  );\r
+\r
+/**\r
+  This function is used to enumerate the entire host bridge\r
+  in a given platform.\r
+\r
+  @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.\r
+\r
+  @retval EFI_SUCCESS            Successfully enumerated the host bridge.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory available.\r
+  @retval other                  Some error occurred when enumerating the host bridge.\r
+\r
+**/\r
+EFI_STATUS\r
+PciHostBridgeEnumerator (\r
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
new file mode 100644 (file)
index 0000000..19803ef
--- /dev/null
@@ -0,0 +1,735 @@
+/** @file\r
+  PCI Rom supporting funtions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  Load the EFI Image from Option ROM\r
+\r
+  @param PciIoDevice   PCI IO device instance.\r
+  @param FilePath      The file path of the EFI Image\r
+  @param BufferSize    On input the size of Buffer in bytes. On output with a return\r
+                       code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+                       On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+                       the size of Buffer required to retrieve the requested file.\r
+  @param Buffer        The memory buffer to transfer the file to. If Buffer is NULL,\r
+                       then no the size of the requested file is returned in BufferSize.\r
+\r
+  @retval EFI_SUCCESS           The file was loaded.\r
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+                                BufferSize is NULL.\r
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.\r
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.\r
+                                BufferSize has been updated with the size needed to complete the request.\r
+**/\r
+EFI_STATUS\r
+LocalLoadFile2 (\r
+  IN PCI_IO_DEVICE            *PciIoDevice,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer      OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH   *EfiOpRomImageNode;\r
+  EFI_PCI_EXPANSION_ROM_HEADER              *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE                        *Pcir;\r
+  UINT32                                    ImageSize;\r
+  UINT8                                     *ImageBuffer;\r
+  UINT32                                    ImageLength;\r
+  UINT32                                    DestinationSize;\r
+  UINT32                                    ScratchSize;\r
+  VOID                                      *Scratch;\r
+  EFI_DECOMPRESS_PROTOCOL                   *Decompress;\r
+\r
+  EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;\r
+  if ((EfiOpRomImageNode == NULL) ||\r
+      (DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||\r
+      (DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||\r
+      (DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||\r
+      (!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||\r
+      (EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||\r
+      (EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||\r
+      (BufferSize == NULL)\r
+      ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (\r
+      (UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset\r
+      );\r
+  if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+\r
+  Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);\r
+\r
+\r
+  if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
+      (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
+      ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
+       (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&\r
+      (EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)\r
+       ) {\r
+\r
+    ImageSize               = (UINT32) EfiRomHeader->InitializationSize * 512;\r
+    ImageBuffer             = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;\r
+    ImageLength             = ImageSize - EfiRomHeader->EfiImageHeaderOffset;\r
+\r
+    if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+      //\r
+      // Uncompressed: Copy the EFI Image directly to user's buffer\r
+      //\r
+      if (Buffer == NULL || *BufferSize < ImageLength) {\r
+        *BufferSize = ImageLength;\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+\r
+      *BufferSize = ImageLength;\r
+      CopyMem (Buffer, ImageBuffer, ImageLength);\r
+      return EFI_SUCCESS;\r
+\r
+    } else {\r
+      //\r
+      // Compressed: Uncompress before copying\r
+      //\r
+      Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      Status = Decompress->GetInfo (\r
+                             Decompress,\r
+                             ImageBuffer,\r
+                             ImageLength,\r
+                             &DestinationSize,\r
+                             &ScratchSize\r
+                             );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      if (Buffer == NULL || *BufferSize < DestinationSize) {\r
+        *BufferSize = DestinationSize;\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+\r
+      *BufferSize = DestinationSize;\r
+      Scratch = AllocatePool (ScratchSize);\r
+      if (Scratch == NULL) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+\r
+      Status = Decompress->Decompress (\r
+                             Decompress,\r
+                             ImageBuffer,\r
+                             ImageLength,\r
+                             Buffer,\r
+                             DestinationSize,\r
+                             Scratch,\r
+                             ScratchSize\r
+                             );\r
+      FreePool (Scratch);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Initialize a PCI LoadFile2 instance.\r
+\r
+  @param PciIoDevice   PCI IO Device.\r
+\r
+**/\r
+VOID\r
+InitializePciLoadFile2 (\r
+  IN PCI_IO_DEVICE       *PciIoDevice\r
+  )\r
+{\r
+  PciIoDevice->LoadFile2.LoadFile = LoadFile2;\r
+}\r
+\r
+/**\r
+  Causes the driver to load a specified file.\r
+\r
+  @param This        Indicates a pointer to the calling context.\r
+  @param FilePath    The device specific path of the file to load.\r
+  @param BootPolicy  Should always be FALSE.\r
+  @param BufferSize  On input the size of Buffer in bytes. On output with a return\r
+                     code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+                     On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+                     the size of Buffer required to retrieve the requested file.\r
+  @param Buffer      The memory buffer to transfer the file to. If Buffer is NULL,\r
+                     then no the size of the requested file is returned in BufferSize.\r
+\r
+  @retval EFI_SUCCESS           The file was loaded.\r
+  @retval EFI_UNSUPPORTED       BootPolicy is TRUE.\r
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+                                BufferSize is NULL.\r
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.\r
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.\r
+                                BufferSize has been updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LoadFile2 (\r
+  IN EFI_LOAD_FILE2_PROTOCOL  *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+  IN BOOLEAN                  BootPolicy,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer      OPTIONAL\r
+  )\r
+{\r
+  PCI_IO_DEVICE                             *PciIoDevice;\r
+\r
+  if (BootPolicy) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);\r
+\r
+  return LocalLoadFile2 (\r
+           PciIoDevice,\r
+           FilePath,\r
+           BufferSize,\r
+           Buffer\r
+           );\r
+}\r
+\r
+/**\r
+  Get Pci device's oprom information.\r
+\r
+  @param PciIoDevice    Input Pci device instance.\r
+                        Output Pci device instance with updated OptionRom size.\r
+\r
+  @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
+  @retval EFI_SUCCESS   Pci device has Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+  IN OUT PCI_IO_DEVICE    *PciIoDevice\r
+  )\r
+{\r
+  UINT8                           RomBarIndex;\r
+  UINT32                          AllOnes;\r
+  UINT64                          Address;\r
+  EFI_STATUS                      Status;\r
+  UINT8                           Bus;\r
+  UINT8                           Device;\r
+  UINT8                           Function;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  Bus             = PciIoDevice->BusNumber;\r
+  Device          = PciIoDevice->DeviceNumber;\r
+  Function        = PciIoDevice->FunctionNumber;\r
+\r
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
+\r
+  //\r
+  // Offset is 0x30 if is not ppb\r
+  //\r
+\r
+  //\r
+  // 0x30\r
+  //\r
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
+\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+    //\r
+    // If is ppb, 0x38\r
+    //\r
+    RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+  }\r
+  //\r
+  // The bit0 is 0 to prevent the enabling of the Rom address decoder\r
+  //\r
+  AllOnes = 0xfffffffe;\r
+  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
+\r
+  Status = PciRootBridgeIo->Pci.Write (\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  &AllOnes\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Read back\r
+  //\r
+  Status = PciRootBridgeIo->Pci.Read(\r
+                                  PciRootBridgeIo,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  &AllOnes\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Bits [1, 10] are reserved\r
+  //\r
+  AllOnes &= 0xFFFFF800;\r
+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check if the RomImage contains EFI Images.\r
+\r
+  @param  RomImage  The ROM address of Image for check.\r
+  @param  RomSize   Size of ROM for check.\r
+\r
+  @retval TRUE     ROM contain EFI Image.\r
+  @retval FALSE    ROM not contain EFI Image.\r
+\r
+**/\r
+BOOLEAN\r
+ContainEfiImage (\r
+  IN VOID            *RomImage,\r
+  IN UINT64          RomSize\r
+  )\r
+{\r
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;\r
+  PCI_DATA_STRUCTURE        *RomPcir;\r
+  BOOLEAN                   FirstCheck;\r
+\r
+  FirstCheck = TRUE;\r
+  RomHeader  = RomImage;\r
+\r
+  while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) {\r
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      if (FirstCheck) {\r
+        return FALSE;\r
+      } else {\r
+        RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck = FALSE;\r
+    RomPcir    = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);\r
+\r
+    if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+      return TRUE;\r
+    }\r
+\r
+    RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Load Option Rom image for specified PCI device.\r
+\r
+  @param PciDevice Pci device instance.\r
+  @param RomBase   Base address of Option Rom.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
+  @retval EFI_SUCESS           Successfully loaded Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT64          RomBase\r
+  )\r
+{\r
+  UINT8                     RomBarIndex;\r
+  UINT8                     Indicator;\r
+  UINT16                    OffsetPcir;\r
+  UINT32                    RomBarOffset;\r
+  UINT32                    RomBar;\r
+  EFI_STATUS                RetStatus;\r
+  BOOLEAN                   FirstCheck;\r
+  UINT8                     *Image;\r
+  PCI_EXPANSION_ROM_HEADER  *RomHeader;\r
+  PCI_DATA_STRUCTURE        *RomPcir;\r
+  UINT64                    RomSize;\r
+  UINT64                    RomImageSize;\r
+  UINT8                     *RomInMemory;\r
+  UINT8                     CodeType;\r
+\r
+  RomSize       = PciDevice->RomSize;\r
+\r
+  Indicator     = 0;\r
+  RomImageSize  = 0;\r
+  RomInMemory   = NULL;\r
+  CodeType      = 0xFF;\r
+\r
+  //\r
+  // Get the RomBarIndex\r
+  //\r
+\r
+  //\r
+  // 0x30\r
+  //\r
+  RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
+  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
+    //\r
+    // if is ppb\r
+    //\r
+\r
+    //\r
+    // 0x38\r
+    //\r
+    RomBarIndex = PCI_BRIDGE_ROMBAR;\r
+  }\r
+  //\r
+  // Allocate memory for Rom header and PCIR\r
+  //\r
+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
+  if (RomHeader == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
+  if (RomPcir == NULL) {\r
+    FreePool (RomHeader);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  RomBar = (UINT32) RomBase;\r
+\r
+  //\r
+  // Enable RomBar\r
+  //\r
+  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
+\r
+  RomBarOffset  = RomBar;\r
+  RetStatus     = EFI_NOT_FOUND;\r
+  FirstCheck    = TRUE;\r
+\r
+  do {\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBarOffset,\r
+                                      sizeof (PCI_EXPANSION_ROM_HEADER),\r
+                                      (UINT8 *) RomHeader\r
+                                      );\r
+\r
+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      RomBarOffset = RomBarOffset + 512;\r
+      if (FirstCheck) {\r
+        break;\r
+      } else {\r
+        RomImageSize = RomImageSize + 512;\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck  = FALSE;\r
+    OffsetPcir  = RomHeader->PcirOffset;\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBarOffset + OffsetPcir,\r
+                                      sizeof (PCI_DATA_STRUCTURE),\r
+                                      (UINT8 *) RomPcir\r
+                                      );\r
+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
+    }\r
+    Indicator     = RomPcir->Indicator;\r
+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;\r
+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;\r
+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
+\r
+  //\r
+  // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
+  // of the legacy length and the PCIR Image Length\r
+  //\r
+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
+    RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
+  }\r
+\r
+  if (RomImageSize > 0) {\r
+    RetStatus = EFI_SUCCESS;\r
+    Image     = AllocatePool ((UINT32) RomImageSize);\r
+    if (Image == NULL) {\r
+      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+      FreePool (RomHeader);\r
+      FreePool (RomPcir);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Copy Rom image into memory\r
+    //\r
+    PciDevice->PciRootBridgeIo->Mem.Read (\r
+                                      PciDevice->PciRootBridgeIo,\r
+                                      EfiPciWidthUint8,\r
+                                      RomBar,\r
+                                      (UINT32) RomImageSize,\r
+                                      Image\r
+                                      );\r
+    RomInMemory = Image;\r
+  }\r
+\r
+  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
+\r
+  PciDevice->PciIo.RomSize  = RomImageSize;\r
+  PciDevice->PciIo.RomImage = RomInMemory;\r
+\r
+  //\r
+  // For OpROM read from PCI device:\r
+  //   Add the Rom Image to internal database for later PCI light enumeration\r
+  //\r
+  PciRomAddImageMapping (\r
+    NULL,\r
+    PciDevice->PciRootBridgeIo->SegmentNumber,\r
+    PciDevice->BusNumber,\r
+    PciDevice->DeviceNumber,\r
+    PciDevice->FunctionNumber,\r
+    (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
+    PciDevice->PciIo.RomSize\r
+    );\r
+\r
+  //\r
+  // Free allocated memory\r
+  //\r
+  FreePool (RomHeader);\r
+  FreePool (RomPcir);\r
+\r
+  return RetStatus;\r
+}\r
+\r
+/**\r
+  Enable/Disable Option Rom decode.\r
+\r
+  @param PciDevice    Pci device instance.\r
+  @param RomBarIndex  The BAR index of the standard PCI Configuration header to use as the\r
+                      base address for resource range. The legal range for this field is 0..5.\r
+  @param RomBar       Base address of Option Rom.\r
+  @param Enable       Flag for enable/disable decode.\r
+\r
+**/\r
+VOID\r
+RomDecode (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT8           RomBarIndex,\r
+  IN UINT32          RomBar,\r
+  IN BOOLEAN         Enable\r
+  )\r
+{\r
+  UINT32              Value32;\r
+  UINT32              Offset;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &PciDevice->PciIo;\r
+  if (Enable) {\r
+    //\r
+    // Clear all bars\r
+    //\r
+    for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
+      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
+    }\r
+\r
+    //\r
+    // set the Rom base address: now is hardcode\r
+    // enable its decoder\r
+    //\r
+    Value32 = RomBar | 0x1;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
+                 RomBarIndex,\r
+                 1,\r
+                 &Value32\r
+                 );\r
+\r
+    //\r
+    // Programe all upstream bridge\r
+    //\r
+    ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
+\r
+    //\r
+    // Setting the memory space bit in the function's command register\r
+    //\r
+    PCI_ENABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+\r
+  } else {\r
+\r
+    //\r
+    // disable command register decode to memory\r
+    //\r
+    PCI_DISABLE_COMMAND_REGISTER(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+\r
+    //\r
+    // Destroy the programmed bar in all the upstream bridge.\r
+    //\r
+    ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
+\r
+    //\r
+    // disable rom decode\r
+    //\r
+    Value32 = 0xFFFFFFFE;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
+                 RomBarIndex,\r
+                 1,\r
+                 &Value32\r
+                 );\r
+\r
+  }\r
+}\r
+\r
+/**\r
+  Load and start the Option Rom image.\r
+\r
+  @param PciDevice       Pci device instance.\r
+\r
+  @retval EFI_SUCCESS    Successfully loaded and started PCI Option Rom image.\r
+  @retval EFI_NOT_FOUND  Failed to process PCI Option Rom image.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+  IN  PCI_IO_DEVICE   *PciDevice\r
+  )\r
+{\r
+  UINT8                                    Indicator;\r
+  UINT32                                   ImageSize;\r
+  VOID                                     *RomBar;\r
+  UINT8                                    *RomBarOffset;\r
+  EFI_HANDLE                               ImageHandle;\r
+  EFI_STATUS                               Status;\r
+  EFI_STATUS                               RetStatus;\r
+  BOOLEAN                                  FirstCheck;\r
+  EFI_PCI_EXPANSION_ROM_HEADER             *EfiRomHeader;\r
+  PCI_DATA_STRUCTURE                       *Pcir;\r
+  EFI_DEVICE_PATH_PROTOCOL                 *PciOptionRomImageDevicePath;\r
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH  EfiOpRomImageNode;\r
+  VOID                                     *Buffer;\r
+  UINTN                                    BufferSize;\r
+\r
+  Indicator = 0;\r
+\r
+  //\r
+  // Get the Address of the Option Rom image\r
+  //\r
+  RomBar        = PciDevice->PciIo.RomImage;\r
+  RomBarOffset  = (UINT8 *) RomBar;\r
+  RetStatus     = EFI_NOT_FOUND;\r
+  FirstCheck    = TRUE;\r
+\r
+  do {\r
+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+      RomBarOffset += 512;\r
+      if (FirstCheck) {\r
+        break;\r
+      } else {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    FirstCheck  = FALSE;\r
+    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
+    ImageSize   = (UINT32) (Pcir->ImageLength * 512);\r
+    Indicator   = Pcir->Indicator;\r
+\r
+    //\r
+    // Create Pci Option Rom Image device path header\r
+    //\r
+    EfiOpRomImageNode.Header.Type     = MEDIA_DEVICE_PATH;\r
+    EfiOpRomImageNode.Header.SubType  = MEDIA_RELATIVE_OFFSET_RANGE_DP;\r
+    SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));\r
+    EfiOpRomImageNode.StartingOffset  = (UINTN) RomBarOffset - (UINTN) RomBar;\r
+    EfiOpRomImageNode.EndingOffset    = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;\r
+\r
+    PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);\r
+    ASSERT (PciOptionRomImageDevicePath != NULL);\r
+\r
+    //\r
+    // load image and start image\r
+    //\r
+    BufferSize  = 0;\r
+    Buffer      = NULL;\r
+    Status      = EFI_SUCCESS;\r
+    ImageHandle = NULL;\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gBS->LoadImage (\r
+                      FALSE,\r
+                      gPciBusDriverBinding.DriverBindingHandle,\r
+                      PciOptionRomImageDevicePath,\r
+                      Buffer,\r
+                      BufferSize,\r
+                      &ImageHandle\r
+                      );\r
+    }\r
+\r
+    //\r
+    // load image and start image\r
+    //\r
+     if (!EFI_ERROR (Status)) {\r
+      Status = gBS->LoadImage (\r
+                      FALSE,\r
+                      gPciBusDriverBinding.DriverBindingHandle,\r
+                      PciOptionRomImageDevicePath,\r
+                      Buffer,\r
+                      BufferSize,\r
+                      &ImageHandle\r
+                      );\r
+    }\r
+\r
+    FreePool (PciOptionRomImageDevicePath);\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
+      if (!EFI_ERROR (Status)) {\r
+        AddDriver (PciDevice, ImageHandle);\r
+        PciRomAddImageMapping (\r
+          ImageHandle,\r
+          PciDevice->PciRootBridgeIo->SegmentNumber,\r
+          PciDevice->BusNumber,\r
+          PciDevice->DeviceNumber,\r
+          PciDevice->FunctionNumber,\r
+          (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
+          PciDevice->PciIo.RomSize\r
+          );\r
+        RetStatus = EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    RomBarOffset += ImageSize;\r
+\r
+  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
+\r
+  return RetStatus;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
new file mode 100644 (file)
index 0000000..4615a5f
--- /dev/null
@@ -0,0 +1,143 @@
+/** @file\r
+  PCI Rom supporting funtions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_OPTION_ROM_SUPPORT_H_\r
+#define _EFI_PCI_OPTION_ROM_SUPPORT_H_\r
+\r
+\r
+/**\r
+  Initialize a PCI LoadFile2 instance.\r
+\r
+  @param PciIoDevice   PCI IO Device.\r
+\r
+**/\r
+VOID\r
+InitializePciLoadFile2 (\r
+  IN PCI_IO_DEVICE       *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Causes the driver to load a specified file.\r
+\r
+  @param This        Indicates a pointer to the calling context.\r
+  @param FilePath    The device specific path of the file to load.\r
+  @param BootPolicy  Should always be FALSE.\r
+  @param BufferSize  On input the size of Buffer in bytes. On output with a return\r
+                     code of EFI_SUCCESS, the amount of data transferred to Buffer.\r
+                     On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+                     the size of Buffer required to retrieve the requested file.\r
+  @param Buffer      The memory buffer to transfer the file to. If Buffer is NULL,\r
+                     then no the size of the requested file is returned in BufferSize.\r
+\r
+  @retval EFI_SUCCESS           The file was loaded.\r
+  @retval EFI_UNSUPPORTED       BootPolicy is TRUE.\r
+  @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+                                BufferSize is NULL.\r
+  @retval EFI_NOT_FOUND         Not found PCI Option Rom on PCI device.\r
+  @retval EFI_DEVICE_ERROR      Failed to decompress PCI Option Rom image.\r
+  @retval EFI_BUFFER_TOO_SMALL  The BufferSize is too small to read the current directory entry.\r
+                                BufferSize has been updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LoadFile2 (\r
+  IN EFI_LOAD_FILE2_PROTOCOL  *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+  IN BOOLEAN                  BootPolicy,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer      OPTIONAL\r
+  );\r
+\r
+/**\r
+  Check if the RomImage contains EFI Images.\r
+\r
+  @param  RomImage  The ROM address of Image for check.\r
+  @param  RomSize   Size of ROM for check.\r
+\r
+  @retval TRUE     ROM contain EFI Image.\r
+  @retval FALSE    ROM not contain EFI Image.\r
+\r
+**/\r
+BOOLEAN\r
+ContainEfiImage (\r
+  IN VOID            *RomImage,\r
+  IN UINT64          RomSize\r
+  );\r
+\r
+\r
+/**\r
+  Get Pci device's oprom information.\r
+\r
+  @param PciIoDevice    Input Pci device instance.\r
+                        Output Pci device instance with updated OptionRom size.\r
+\r
+  @retval EFI_NOT_FOUND Pci device has not Option Rom.\r
+  @retval EFI_SUCCESS   Pci device has Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+GetOpRomInfo (\r
+  IN OUT PCI_IO_DEVICE    *PciIoDevice\r
+  );\r
+\r
+/**\r
+  Load Option Rom image for specified PCI device.\r
+\r
+  @param PciDevice Pci device instance.\r
+  @param RomBase   Base address of Option Rom.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES No enough memory to hold image.\r
+  @retval EFI_SUCESS           Successfully loaded Option Rom.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT64          RomBase\r
+  );\r
+\r
+/**\r
+  Enable/Disable Option Rom decode.\r
+\r
+  @param PciDevice    Pci device instance.\r
+  @param RomBarIndex  The BAR index of the standard PCI Configuration header to use as the\r
+                      base address for resource range. The legal range for this field is 0..5.\r
+  @param RomBar       Base address of Option Rom.\r
+  @param Enable       Flag for enable/disable decode.\r
+\r
+**/\r
+VOID\r
+RomDecode (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT8           RomBarIndex,\r
+  IN UINT32          RomBar,\r
+  IN BOOLEAN         Enable\r
+  );\r
+\r
+/**\r
+  Load and start the Option Rom image.\r
+\r
+  @param PciDevice       Pci device instance.\r
+\r
+  @retval EFI_SUCCESS    Successfully loaded and started PCI Option Rom image.\r
+  @retval EFI_NOT_FOUND  Failed to process PCI Option Rom image.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOpRomImage (\r
+  IN PCI_IO_DEVICE   *PciDevice\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.c
new file mode 100644 (file)
index 0000000..860d427
--- /dev/null
@@ -0,0 +1,68 @@
+/** @file\r
+  Power management support fucntions implementation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  This function is intended to turn off PWE assertion and\r
+  put the device to D0 state if the device supports\r
+  PCI Power Management.\r
+\r
+  @param PciIoDevice      PCI device instance.\r
+\r
+  @retval EFI_UNSUPPORTED PCI Device does not support power management.\r
+  @retval EFI_SUCCESS     Turned off PWE successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       PowerManagementRegBlock;\r
+  UINT16      PowerManagementCSR;\r
+\r
+  PowerManagementRegBlock = 0;\r
+\r
+  Status = LocateCapabilityRegBlock (\r
+            PciIoDevice,\r
+            EFI_PCI_CAPABILITY_ID_PMI,\r
+            &PowerManagementRegBlock,\r
+            NULL\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Turn off the PWE assertion and put the device into D0 State\r
+  //\r
+  PowerManagementCSR = 0x8000;\r
+\r
+  //\r
+  // Write PMCSR\r
+  //\r
+  PciIoDevice->PciIo.Pci.Write (\r
+                           &PciIoDevice->PciIo,\r
+                           EfiPciIoWidthUint16,\r
+                           PowerManagementRegBlock + 4,\r
+                           1,\r
+                           &PowerManagementCSR\r
+                           );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPowerManagement.h
new file mode 100644 (file)
index 0000000..8846270
--- /dev/null
@@ -0,0 +1,34 @@
+/** @file\r
+  Power management support fucntions delaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H_\r
+#define _EFI_PCI_POWER_MANAGEMENT_H_\r
+\r
+/**\r
+  This function is intended to turn off PWE assertion and\r
+  put the device to D0 state if the device supports\r
+  PCI Power Management.\r
+\r
+  @param PciIoDevice      PCI device instance.\r
+\r
+  @retval EFI_UNSUPPORTED PCI Device does not support power management.\r
+  @retval EFI_SUCCESS     Turned off PWE successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ResetPowerManagementFeature (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
new file mode 100644 (file)
index 0000000..2cacd44
--- /dev/null
@@ -0,0 +1,2344 @@
+/** @file\r
+  PCI resouces support functions implemntation for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+/**\r
+  The function is used to skip VGA range.\r
+\r
+  @param Start    Returned start address including VGA range.\r
+  @param Length   The length of VGA range.\r
+\r
+**/\r
+VOID\r
+SkipVGAAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  )\r
+{\r
+  UINT64  Original;\r
+  UINT64  Mask;\r
+  UINT64  StartOffset;\r
+  UINT64  LimitOffset;\r
+\r
+  ASSERT (Start != NULL);\r
+  //\r
+  // For legacy VGA, bit 10 to bit 15 is not decoded\r
+  //\r
+  Mask        = 0x3FF;\r
+\r
+  Original    = *Start;\r
+  StartOffset = Original & Mask;\r
+  LimitOffset = ((*Start) + Length - 1) & Mask;\r
+  if (LimitOffset >= VGABASE1) {\r
+    *Start = *Start - StartOffset + VGALIMIT2 + 1;\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to skip ISA aliasing aperture.\r
+\r
+  @param Start    Returned start address including ISA aliasing aperture.\r
+  @param Length   The length of ISA aliasing aperture.\r
+\r
+**/\r
+VOID\r
+SkipIsaAliasAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  )\r
+{\r
+\r
+  UINT64  Original;\r
+  UINT64  Mask;\r
+  UINT64  StartOffset;\r
+  UINT64  LimitOffset;\r
+\r
+  ASSERT (Start != NULL);\r
+\r
+  //\r
+  // For legacy ISA, bit 10 to bit 15 is not decoded\r
+  //\r
+  Mask        = 0x3FF;\r
+\r
+  Original    = *Start;\r
+  StartOffset = Original & Mask;\r
+  LimitOffset = ((*Start) + Length - 1) & Mask;\r
+\r
+  if (LimitOffset >= ISABASE) {\r
+    *Start = *Start - StartOffset + ISALIMIT + 1;\r
+  }\r
+}\r
+\r
+/**\r
+  This function inserts a resource node into the resource list.\r
+  The resource list is sorted in descend order.\r
+\r
+  @param Bridge  PCI resource node for bridge.\r
+  @param ResNode Resource node want to be inserted.\r
+\r
+**/\r
+VOID\r
+InsertResourceNode (\r
+  IN OUT PCI_RESOURCE_NODE   *Bridge,\r
+  IN     PCI_RESOURCE_NODE   *ResNode\r
+  )\r
+{\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Temp;\r
+  UINT64            ResNodeAlignRest;\r
+  UINT64            TempAlignRest;\r
+\r
+  ASSERT (Bridge  != NULL);\r
+  ASSERT (ResNode != NULL);\r
+\r
+  InsertHeadList (&Bridge->ChildList, &ResNode->Link);\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (ResNode->Alignment > Temp->Alignment) {\r
+      break;\r
+    } else if (ResNode->Alignment == Temp->Alignment) {\r
+      ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;\r
+      TempAlignRest     = Temp->Length & Temp->Alignment;\r
+      if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    SwapListEntries (&ResNode->Link, CurrentLink);\r
+\r
+    CurrentLink = ResNode->Link.ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  This routine is used to merge two different resource trees in need of\r
+  resoure degradation.\r
+\r
+  For example, if an upstream PPB doesn't support,\r
+  prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+  to merge prefectchable memory resource list into normal memory list.\r
+\r
+  If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+  type.\r
+  If Dst is NULL or Res is NULL, ASSERT ().\r
+\r
+  @param Dst        Point to destination resource tree.\r
+  @param Res        Point to source resource tree.\r
+  @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of\r
+                    destination resource type.\r
+\r
+**/\r
+VOID\r
+MergeResourceTree (\r
+  IN PCI_RESOURCE_NODE   *Dst,\r
+  IN PCI_RESOURCE_NODE   *Res,\r
+  IN BOOLEAN             TypeMerge\r
+  )\r
+{\r
+\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Temp;\r
+\r
+  ASSERT (Dst != NULL);\r
+  ASSERT (Res != NULL);\r
+\r
+  while (!IsListEmpty (&Res->ChildList)) {\r
+    CurrentLink = Res->ChildList.ForwardLink;\r
+\r
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (TypeMerge) {\r
+      Temp->ResType = Dst->ResType;\r
+    }\r
+\r
+    RemoveEntryList (CurrentLink);\r
+    InsertResourceNode (Dst, Temp);\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to calculate the IO16 aperture\r
+  for a bridge.\r
+\r
+  @param Bridge    PCI resource node for bridge.\r
+\r
+**/\r
+VOID\r
+CalculateApertureIo16 (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINT64                  Aperture;\r
+  LIST_ENTRY              *CurrentLink;\r
+  PCI_RESOURCE_NODE       *Node;\r
+  UINT64                  Offset;\r
+  BOOLEAN                 IsaEnable;\r
+  BOOLEAN                 VGAEnable;\r
+  EFI_PCI_PLATFORM_POLICY PciPolicy;\r
+\r
+  //\r
+  // Always assume there is ISA device and VGA device on the platform\r
+  // will be customized later\r
+  //\r
+  IsaEnable = FALSE;\r
+  VGAEnable = FALSE;\r
+\r
+  //\r
+  // Check PciPlatform policy\r
+  //\r
+  if (gPciPlatformProtocol != NULL) {\r
+    Status = gPciPlatformProtocol->GetPlatformPolicy (\r
+                                     gPciPlatformProtocol,\r
+                                     &PciPolicy\r
+                                     );\r
+    if (!EFI_ERROR (Status)) {\r
+      if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
+        IsaEnable = TRUE;\r
+      }\r
+      if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
+        VGAEnable = TRUE;\r
+      }\r
+    }\r
+  } else if (gPciOverrideProtocol != NULL) {\r
+    Status = gPciOverrideProtocol->GetPlatformPolicy (\r
+                                     gPciOverrideProtocol,\r
+                                     &PciPolicy\r
+                                     );\r
+    if (!EFI_ERROR (Status)) {\r
+      if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
+        IsaEnable = TRUE;\r
+      }\r
+      if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
+        VGAEnable = TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  Aperture = 0;\r
+\r
+  if (Bridge == NULL) {\r
+    return ;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Assume the bridge is aligned\r
+  //\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Consider the aperture alignment\r
+    //\r
+    Offset = Aperture & (Node->Alignment);\r
+\r
+    if (Offset != 0) {\r
+\r
+      Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+\r
+    }\r
+\r
+    //\r
+    // IsaEnable and VGAEnable can not be implemented now.\r
+    // If both of them are enabled, then the IO resource would\r
+    // become too limited to meet the requirement of most of devices.\r
+    //\r
+    if (IsaEnable || VGAEnable) {\r
+      if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+        //\r
+        // Check if there is need to support ISA/VGA decoding\r
+        // If so, we need to avoid isa/vga aliasing range\r
+        //\r
+        if (IsaEnable) {\r
+          SkipIsaAliasAperture (\r
+            &Aperture,\r
+            Node->Length\r
+            );\r
+          Offset = Aperture & (Node->Alignment);\r
+          if (Offset != 0) {\r
+            Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+          }\r
+        } else if (VGAEnable) {\r
+          SkipVGAAperture (\r
+            &Aperture,\r
+            Node->Length\r
+            );\r
+          Offset = Aperture & (Node->Alignment);\r
+          if (Offset != 0) {\r
+            Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    Node->Offset = Aperture;\r
+\r
+    //\r
+    // Increment aperture by the length of node\r
+    //\r
+    Aperture += Node->Length;\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // At last, adjust the aperture with the bridge's\r
+  // alignment\r
+  //\r
+  Offset = Aperture & (Bridge->Alignment);\r
+\r
+  if (Offset != 0) {\r
+    Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
+  }\r
+\r
+  Bridge->Length = Aperture;\r
+  //\r
+  // At last, adjust the bridge's alignment to the first child's alignment\r
+  // if the bridge has at least one child\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  if (CurrentLink != &Bridge->ChildList) {\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    if (Node->Alignment > Bridge->Alignment) {\r
+      Bridge->Alignment = Node->Alignment;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to calculate the resource aperture\r
+  for a given bridge device.\r
+\r
+  @param Bridge      PCI resouce node for given bridge device.\r
+\r
+**/\r
+VOID\r
+CalculateResourceAperture (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  )\r
+{\r
+  UINT64            Aperture;\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  UINT64            Offset;\r
+\r
+  Aperture = 0;\r
+\r
+  if (Bridge == NULL) {\r
+    return ;\r
+  }\r
+\r
+  if (Bridge->ResType == PciBarTypeIo16) {\r
+\r
+    CalculateApertureIo16 (Bridge);\r
+    return ;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Assume the bridge is aligned\r
+  //\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Apply padding resource if available\r
+    //\r
+    Offset = Aperture & (Node->Alignment);\r
+\r
+    if (Offset != 0) {\r
+\r
+      Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
+\r
+    }\r
+\r
+    //\r
+    // Recode current aperture as a offset\r
+    // this offset will be used in future real allocation\r
+    //\r
+    Node->Offset = Aperture;\r
+\r
+    //\r
+    // Increment aperture by the length of node\r
+    //\r
+    Aperture += Node->Length;\r
+\r
+    //\r
+    // Consider the aperture alignment\r
+    //\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // At last, adjust the aperture with the bridge's\r
+  // alignment\r
+  //\r
+  Offset = Aperture & (Bridge->Alignment);\r
+  if (Offset != 0) {\r
+    Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
+  }\r
+\r
+  //\r
+  // If the bridge has already padded the resource and the\r
+  // amount of padded resource is larger, then keep the\r
+  // padded resource\r
+  //\r
+  if (Bridge->Length < Aperture) {\r
+    Bridge->Length = Aperture;\r
+  }\r
+\r
+  //\r
+  // At last, adjust the bridge's alignment to the first child's alignment\r
+  // if the bridge has at least one child\r
+  //\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  if (CurrentLink != &Bridge->ChildList) {\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    if (Node->Alignment > Bridge->Alignment) {\r
+      Bridge->Alignment = Node->Alignment;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get IO/Memory resource infor for given PCI device.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO .\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+GetResourceFromDevice (\r
+  IN     PCI_IO_DEVICE     *PciDev,\r
+  IN OUT PCI_RESOURCE_NODE *IoNode,\r
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+{\r
+\r
+  UINT8             Index;\r
+  PCI_RESOURCE_NODE *Node;\r
+  BOOLEAN           ResourceRequested;\r
+\r
+  Node              = NULL;\r
+  ResourceRequested = FALSE;\r
+\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+    switch ((PciDev->PciBar)[Index].BarType) {\r
+\r
+    case PciBarTypeMem32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem32Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeMem64:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem64Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypePMem64:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem64Node,\r
+        Node\r
+        );\r
+\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypePMem32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem32Node,\r
+        Node\r
+        );\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeIo16:\r
+    case PciBarTypeIo32:\r
+\r
+      Node = CreateResourceNode (\r
+              PciDev,\r
+              (PciDev->PciBar)[Index].Length,\r
+              (PciDev->PciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeIo16,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        IoNode,\r
+        Node\r
+        );\r
+      ResourceRequested = TRUE;\r
+      break;\r
+\r
+    case PciBarTypeUnknown:\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Add VF resource\r
+  //\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+    switch ((PciDev->VfPciBar)[Index].BarType) {\r
+\r
+    case PciBarTypeMem32:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem32Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypeMem64:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypeMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        Mem64Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypePMem64:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem64,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem64Node,\r
+        Node\r
+        );\r
+\r
+      break;\r
+\r
+    case PciBarTypePMem32:\r
+\r
+      Node = CreateVfResourceNode (\r
+              PciDev,\r
+              (PciDev->VfPciBar)[Index].Length,\r
+              (PciDev->VfPciBar)[Index].Alignment,\r
+              Index,\r
+              PciBarTypePMem32,\r
+              PciResUsageTypical\r
+              );\r
+\r
+      InsertResourceNode (\r
+        PMem32Node,\r
+        Node\r
+        );\r
+      break;\r
+\r
+    case PciBarTypeIo16:\r
+    case PciBarTypeIo32:\r
+      break;\r
+\r
+    case PciBarTypeUnknown:\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+  // If there is no resource requested from this device,\r
+  // then we indicate this device has been allocated naturally.\r
+  //\r
+  if (!ResourceRequested) {\r
+    PciDev->Allocated = TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to create a resource node.\r
+\r
+  @param PciDev       Pci device instance.\r
+  @param Length       Length of Io/Memory resource.\r
+  @param Alignment    Alignment of resource.\r
+  @param Bar          Bar index.\r
+  @param ResType      Type of resource: IO/Memory.\r
+  @param ResUsage     Resource usage.\r
+\r
+  @return PCI resource node created for given PCI device.\r
+          NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  Node    = NULL;\r
+\r
+  Node    = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));\r
+  ASSERT (Node != NULL);\r
+  if (Node == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Node->Signature     = PCI_RESOURCE_SIGNATURE;\r
+  Node->PciDev        = PciDev;\r
+  Node->Length        = Length;\r
+  Node->Alignment     = Alignment;\r
+  Node->Bar           = Bar;\r
+  Node->ResType       = ResType;\r
+  Node->Reserved      = FALSE;\r
+  Node->ResourceUsage = ResUsage;\r
+  InitializeListHead (&Node->ChildList);\r
+\r
+  return Node;\r
+}\r
+\r
+/**\r
+  This function is used to create a IOV VF resource node.\r
+\r
+  @param PciDev       Pci device instance.\r
+  @param Length       Length of Io/Memory resource.\r
+  @param Alignment    Alignment of resource.\r
+  @param Bar          Bar index.\r
+  @param ResType      Type of resource: IO/Memory.\r
+  @param ResUsage     Resource usage.\r
+\r
+  @return PCI resource node created for given VF PCI device.\r
+          NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
+    (UINTN)PciDev->BusNumber,\r
+    (UINTN)PciDev->DeviceNumber,\r
+    (UINTN)PciDev->FunctionNumber,\r
+    (UINTN)Bar,\r
+    (UINTN)ResType,\r
+    (UINTN)Length\r
+    ));\r
+\r
+  Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
+  if (Node == NULL) {\r
+    return Node;\r
+  }\r
+\r
+  Node->Virtual = TRUE;\r
+\r
+  return Node;\r
+}\r
+\r
+/**\r
+  This function is used to extract resource request from\r
+  device node list.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+CreateResourceMap (\r
+  IN     PCI_IO_DEVICE     *Bridge,\r
+  IN OUT PCI_RESOURCE_NODE *IoNode,\r
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+{\r
+  PCI_IO_DEVICE     *Temp;\r
+  PCI_RESOURCE_NODE *IoBridge;\r
+  PCI_RESOURCE_NODE *Mem32Bridge;\r
+  PCI_RESOURCE_NODE *PMem32Bridge;\r
+  PCI_RESOURCE_NODE *Mem64Bridge;\r
+  PCI_RESOURCE_NODE *PMem64Bridge;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    //\r
+    // Create resource nodes for this device by scanning the\r
+    // Bar array in the device private data\r
+    // If the upstream bridge doesn't support this device,\r
+    // no any resource node will be created for this device\r
+    //\r
+    GetResourceFromDevice (\r
+      Temp,\r
+      IoNode,\r
+      Mem32Node,\r
+      PMem32Node,\r
+      Mem64Node,\r
+      PMem64Node\r
+      );\r
+\r
+    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+      //\r
+      // If the device has children, create a bridge resource node for this PPB\r
+      // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
+      // is aligned with 4KB\r
+      // This device is typically a bridge device like PPB and P2C\r
+      // Note: 0x1000 aligned\r
+      //\r
+      IoBridge = CreateResourceNode (\r
+                   Temp,\r
+                   0,\r
+                   0xFFF,\r
+                   PPB_IO_RANGE,\r
+                   PciBarTypeIo16,\r
+                   PciResUsageTypical\r
+                   );\r
+\r
+      Mem32Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_MEM32_RANGE,\r
+                      PciBarTypeMem32,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem32Bridge = CreateResourceNode (\r
+                       Temp,\r
+                       0,\r
+                       0xFFFFF,\r
+                       PPB_PMEM32_RANGE,\r
+                       PciBarTypePMem32,\r
+                       PciResUsageTypical\r
+                       );\r
+\r
+      Mem64Bridge = CreateResourceNode (\r
+                      Temp,\r
+                      0,\r
+                      0xFFFFF,\r
+                      PPB_MEM64_RANGE,\r
+                      PciBarTypeMem64,\r
+                      PciResUsageTypical\r
+                      );\r
+\r
+      PMem64Bridge = CreateResourceNode (\r
+                       Temp,\r
+                       0,\r
+                       0xFFFFF,\r
+                       PPB_PMEM64_RANGE,\r
+                       PciBarTypePMem64,\r
+                       PciResUsageTypical\r
+                       );\r
+\r
+      //\r
+      // Recursively create resouce map on this bridge\r
+      //\r
+      CreateResourceMap (\r
+        Temp,\r
+        IoBridge,\r
+        Mem32Bridge,\r
+        PMem32Bridge,\r
+        Mem64Bridge,\r
+        PMem64Bridge\r
+        );\r
+\r
+      if (ResourceRequestExisted (IoBridge)) {\r
+        InsertResourceNode (\r
+          IoNode,\r
+          IoBridge\r
+          );\r
+      } else {\r
+        FreePool (IoBridge);\r
+        IoBridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (Mem32Bridge)) {\r
+        InsertResourceNode (\r
+          Mem32Node,\r
+          Mem32Bridge\r
+          );\r
+      } else {\r
+        FreePool (Mem32Bridge);\r
+        Mem32Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (PMem32Bridge)) {\r
+        InsertResourceNode (\r
+          PMem32Node,\r
+          PMem32Bridge\r
+          );\r
+      } else {\r
+        FreePool (PMem32Bridge);\r
+        PMem32Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (Mem64Bridge)) {\r
+        InsertResourceNode (\r
+          Mem64Node,\r
+          Mem64Bridge\r
+          );\r
+      } else {\r
+        FreePool (Mem64Bridge);\r
+        Mem64Bridge = NULL;\r
+      }\r
+\r
+      //\r
+      // If there is node under this resource bridge,\r
+      // then calculate bridge's aperture of this type\r
+      // and insert it into the respective resource tree.\r
+      // If no, delete this resource bridge\r
+      //\r
+      if (ResourceRequestExisted (PMem64Bridge)) {\r
+        InsertResourceNode (\r
+          PMem64Node,\r
+          PMem64Bridge\r
+          );\r
+      } else {\r
+        FreePool (PMem64Bridge);\r
+        PMem64Bridge = NULL;\r
+      }\r
+\r
+    }\r
+\r
+    //\r
+    // If it is P2C, apply hard coded resource padding\r
+    //\r
+    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+      ResourcePaddingForCardBusBridge (\r
+        Temp,\r
+        IoNode,\r
+        Mem32Node,\r
+        PMem32Node,\r
+        Mem64Node,\r
+        PMem64Node\r
+        );\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // To do some platform specific resource padding ...\r
+  //\r
+  ResourcePaddingPolicy (\r
+    Bridge,\r
+    IoNode,\r
+    Mem32Node,\r
+    PMem32Node,\r
+    Mem64Node,\r
+    PMem64Node\r
+    );\r
+\r
+  //\r
+  // Degrade resource if necessary\r
+  //\r
+  DegradeResource (\r
+    Bridge,\r
+    Mem32Node,\r
+    PMem32Node,\r
+    Mem64Node,\r
+    PMem64Node\r
+    );\r
+\r
+  //\r
+  // Calculate resource aperture for this bridge device\r
+  //\r
+  CalculateResourceAperture (Mem32Node);\r
+  CalculateResourceAperture (PMem32Node);\r
+  CalculateResourceAperture (Mem64Node);\r
+  CalculateResourceAperture (PMem64Node);\r
+  CalculateResourceAperture (IoNode);\r
+}\r
+\r
+/**\r
+  This function is used to do the resource padding for a specific platform.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingPolicy (\r
+  IN PCI_IO_DEVICE     *PciDev,\r
+  IN PCI_RESOURCE_NODE *IoNode,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+{\r
+  //\r
+  // Create padding resource node\r
+  //\r
+  if (PciDev->ResourcePaddingDescriptors != NULL) {\r
+    ApplyResourcePadding (\r
+      PciDev,\r
+      IoNode,\r
+      Mem32Node,\r
+      PMem32Node,\r
+      Mem64Node,\r
+      PMem64Node\r
+      );\r
+  }\r
+}\r
+\r
+/**\r
+  This function is used to degrade resource if the upstream bridge\r
+  doesn't support certain resource. Degradation path is\r
+  PMEM64 -> MEM64  -> MEM32\r
+  PMEM64 -> PMEM32 -> MEM32\r
+  IO32   -> IO16.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+DegradeResource (\r
+  IN PCI_IO_DEVICE     *Bridge,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  )\r
+{\r
+  BOOLEAN              HasOprom;\r
+  PCI_IO_DEVICE        *Temp;\r
+  LIST_ENTRY           *CurrentLink;\r
+\r
+  //\r
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+  // to find if this bridge and downstream has OptionRom.\r
+  //\r
+  HasOprom = FALSE;\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    if (Temp->RomSize != 0) {\r
+      HasOprom = TRUE;\r
+      break;\r
+    }\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // If bridge doesn't support Prefetchable\r
+  // memory64, degrade it to Prefetchable memory32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      PMem32Node,\r
+      PMem64Node,\r
+      TRUE\r
+      );\r
+  } else {\r
+    //\r
+    // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32\r
+    //\r
+    if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {\r
+      //\r
+      // Fixed the issue that there is no resource for 64-bit (above 4G)\r
+      //\r
+      MergeResourceTree (\r
+        PMem32Node,\r
+        PMem64Node,\r
+        TRUE\r
+        );\r
+    }\r
+  }\r
+\r
+\r
+  //\r
+  // If bridge doesn't support Mem64\r
+  // degrade it to mem32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      Mem64Node,\r
+      TRUE\r
+      );\r
+  }\r
+\r
+  //\r
+  // If bridge doesn't support Pmem32\r
+  // degrade it to mem32\r
+  //\r
+  if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      PMem32Node,\r
+      TRUE\r
+      );\r
+  }\r
+\r
+  //\r
+  // if bridge supports combined Pmem Mem decoding\r
+  // merge these two type of resource\r
+  //\r
+  if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
+    MergeResourceTree (\r
+      Mem32Node,\r
+      PMem32Node,\r
+      FALSE\r
+      );\r
+\r
+    MergeResourceTree (\r
+      Mem64Node,\r
+      PMem64Node,\r
+      FALSE\r
+      );\r
+  }\r
+}\r
+\r
+/**\r
+  Test whether bridge device support decode resource.\r
+\r
+  @param Bridge    Bridge device instance.\r
+  @param Decode    Decode type according to resource type.\r
+\r
+  @return TRUE     The bridge device support decode resource.\r
+  @return FALSE    The bridge device don't support decode resource.\r
+\r
+**/\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+  IN PCI_IO_DEVICE *Bridge,\r
+  IN UINT32        Decode\r
+  )\r
+{\r
+  if (((Bridge->Decodes) & Decode) != 0) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function is used to program the resource allocated\r
+  for each resource node under specified bridge.\r
+\r
+  @param Base     Base address of resource to be progammed.\r
+  @param Bridge   PCI resource node for the bridge device.\r
+\r
+  @retval EFI_SUCCESS            Successfully to program all resouces\r
+                                 on given PCI bridge device.\r
+  @retval EFI_OUT_OF_RESOURCES   Base is all one.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramResource (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+{\r
+  LIST_ENTRY        *CurrentLink;\r
+  PCI_RESOURCE_NODE *Node;\r
+  EFI_STATUS        Status;\r
+\r
+  if (Base == gAllOne) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Bridge->ChildList) {\r
+\r
+    Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
+\r
+      if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+        //\r
+        // Program the PCI Card Bus device\r
+        //\r
+        ProgramP2C (Base, Node);\r
+      } else {\r
+        //\r
+        // Program the PCI device BAR\r
+        //\r
+        ProgramBar (Base, Node);\r
+      }\r
+    } else {\r
+      //\r
+      // Program the PCI devices under this bridge\r
+      //\r
+      Status = ProgramResource (Base + Node->Offset, Node);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ProgramPpbApperture (Base, Node);\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Program Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  ASSERT (Node->Bar < PCI_MAX_BAR);\r
+\r
+  //\r
+  // Check VF BAR\r
+  //\r
+  if (Node->Virtual) {\r
+    ProgramVfBar (Base, Node);\r
+  }\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+  case PciBarTypeIo16:\r
+  case PciBarTypeIo32:\r
+  case PciBarTypeMem32:\r
+  case PciBarTypePMem32:\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    break;\r
+\r
+  case PciBarTypeMem64:\r
+  case PciBarTypePMem64:\r
+\r
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Program IOV VF Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  ASSERT (Node->Bar < PCI_MAX_BAR);\r
+  ASSERT (Node->Virtual);\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {\r
+\r
+  case PciBarTypeMem32:\r
+  case PciBarTypePMem32:\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address\r
+                );\r
+\r
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
+      (UINTN)Node->PciDev->BusNumber,\r
+      (UINTN)Node->PciDev->DeviceNumber,\r
+      (UINTN)Node->PciDev->FunctionNumber,\r
+      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+      (UINTN)Address\r
+      ));\r
+\r
+    break;\r
+\r
+  case PciBarTypeMem64:\r
+  case PciBarTypePMem64:\r
+\r
+    Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+\r
+    PciIo->Pci.Write (\r
+                PciIo,\r
+                EfiPciIoWidthUint32,\r
+                ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),\r
+                1,\r
+                &Address32\r
+                );\r
+\r
+    Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
+      (UINTN)Node->PciDev->BusNumber,\r
+      (UINTN)Node->PciDev->DeviceNumber,\r
+      (UINTN)Node->PciDev->FunctionNumber,\r
+      (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
+      (UINT64)Address\r
+      ));\r
+\r
+    break;\r
+\r
+  case PciBarTypeIo16:\r
+  case PciBarTypeIo32:\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Program PCI-PCI bridge apperture.\r
+\r
+  @param Base  Base address for resource.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramPpbApperture (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT32              Address32;\r
+\r
+  Address = 0;\r
+  //\r
+  // If no device resource of this PPB, return anyway\r
+  // Apperture is set default in the initialization code\r
+  //\r
+  if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
+    //\r
+    // For padding resource node, just ignore when programming\r
+    //\r
+    return ;\r
+  }\r
+\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate the PPB resource has been allocated\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch (Node->Bar) {\r
+\r
+  case PPB_BAR_0:\r
+  case PPB_BAR_1:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+\r
+    break;\r
+\r
+  case PPB_IO_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 8;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint8,\r
+                 0x1C,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 >>= 8;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x30,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 8;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint8,\r
+                 0x1D,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 >>= 8;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x32,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case PPB_MEM32_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 16;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x20,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 16;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x22,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case PPB_PMEM32_RANGE:\r
+  case PPB_PMEM64_RANGE:\r
+\r
+    Address32 = ((UINT32) (Address)) >> 16;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x24,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) (Address + Node->Length - 1);\r
+    Address32 = ((UINT32) (Address32)) >> 16;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint16,\r
+                 0x26,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) RShiftU64 (Address, 32);\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 0x28,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 0x2C,\r
+                 1,\r
+                 &Address32\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Program parent bridge for Option Rom.\r
+\r
+  @param PciDevice      Pci deivce instance.\r
+  @param OptionRomBase  Base address for Optiona Rom.\r
+  @param Enable         Enable or disable PCI memory.\r
+\r
+**/\r
+VOID\r
+ProgrameUpstreamBridgeForRom (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT32          OptionRomBase,\r
+  IN BOOLEAN         Enable\r
+  )\r
+{\r
+  PCI_IO_DEVICE     *Parent;\r
+  PCI_RESOURCE_NODE Node;\r
+  //\r
+  // For root bridge, just return.\r
+  //\r
+  Parent = PciDevice->Parent;\r
+  ZeroMem (&Node, sizeof (Node));\r
+  while (Parent != NULL) {\r
+    if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
+      break;\r
+    }\r
+\r
+    Node.PciDev     = Parent;\r
+    Node.Length     = PciDevice->RomSize;\r
+    Node.Alignment  = 0;\r
+    Node.Bar        = PPB_MEM32_RANGE;\r
+    Node.ResType    = PciBarTypeMem32;\r
+    Node.Offset     = 0;\r
+\r
+    //\r
+    // Program PPB to only open a single <= 16MB apperture\r
+    //\r
+    if (Enable) {\r
+      ProgramPpbApperture (OptionRomBase, &Node);\r
+      PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    } else {\r
+      InitializePpb (Parent);\r
+      PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+    }\r
+\r
+    Parent = Parent->Parent;\r
+  }\r
+}\r
+\r
+/**\r
+  Test whether resource exists for a bridge.\r
+\r
+  @param Bridge  Point to resource node for a bridge.\r
+\r
+  @retval TRUE   There is resource on the given bridge.\r
+  @retval FALSE  There isn't resource on the given bridge.\r
+\r
+**/\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  )\r
+{\r
+  if (Bridge != NULL) {\r
+    if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Initialize resource pool structure.\r
+\r
+  @param ResourcePool Point to resource pool structure. This pool\r
+                      is reset to all zero when returned.\r
+  @param ResourceType Type of resource.\r
+\r
+**/\r
+VOID\r
+InitializeResourcePool (\r
+  IN OUT PCI_RESOURCE_NODE   *ResourcePool,\r
+  IN     PCI_BAR_TYPE        ResourceType\r
+  )\r
+{\r
+  ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
+  ResourcePool->ResType   = ResourceType;\r
+  ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
+  InitializeListHead (&ResourcePool->ChildList);\r
+}\r
+\r
+\r
+/**\r
+  Get all resource information for given Pci device.\r
+\r
+  @param PciDev         Pci device instance.\r
+  @param IoBridge       Io resource node.\r
+  @param Mem32Bridge    32-bit memory node.\r
+  @param PMem32Bridge   32-bit Pmemory node.\r
+  @param Mem64Bridge    64-bit memory node.\r
+  @param PMem64Bridge   64-bit PMemory node.\r
+  @param IoPool         Link list header for Io resource.\r
+  @param Mem32Pool      Link list header for 32-bit memory.\r
+  @param PMem32Pool     Link list header for 32-bit Prefetchable memory.\r
+  @param Mem64Pool      Link list header for 64-bit memory.\r
+  @param PMem64Pool     Link list header for 64-bit Prefetchable memory.\r
+\r
+**/\r
+VOID\r
+GetResourceMap (\r
+  IN PCI_IO_DEVICE      *PciDev,\r
+  IN PCI_RESOURCE_NODE  **IoBridge,\r
+  IN PCI_RESOURCE_NODE  **Mem32Bridge,\r
+  IN PCI_RESOURCE_NODE  **PMem32Bridge,\r
+  IN PCI_RESOURCE_NODE  **Mem64Bridge,\r
+  IN PCI_RESOURCE_NODE  **PMem64Bridge,\r
+  IN PCI_RESOURCE_NODE  *IoPool,\r
+  IN PCI_RESOURCE_NODE  *Mem32Pool,\r
+  IN PCI_RESOURCE_NODE  *PMem32Pool,\r
+  IN PCI_RESOURCE_NODE  *Mem64Pool,\r
+  IN PCI_RESOURCE_NODE  *PMem64Pool\r
+  )\r
+{\r
+\r
+  PCI_RESOURCE_NODE *Temp;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  CurrentLink = IoPool->ChildList.ForwardLink;\r
+\r
+  //\r
+  // Get Io resource map\r
+  //\r
+  while (CurrentLink != &IoPool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *IoBridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Mem32 resource map\r
+  //\r
+  CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Mem32Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *Mem32Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Pmem32 resource map\r
+  //\r
+  CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &PMem32Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *PMem32Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Mem64 resource map\r
+  //\r
+  CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &Mem64Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *Mem64Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  //\r
+  // Get Pmem64 resource map\r
+  //\r
+  CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
+\r
+  while (CurrentLink != &PMem64Pool->ChildList) {\r
+\r
+    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+    if (Temp->PciDev == PciDev) {\r
+      *PMem64Bridge = Temp;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+}\r
+\r
+/**\r
+  Destory given resource tree.\r
+\r
+  @param Bridge  PCI resource root node of resource tree.\r
+\r
+**/\r
+VOID\r
+DestroyResourceTree (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Temp;\r
+  LIST_ENTRY        *CurrentLink;\r
+\r
+  while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+    CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+    Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+    ASSERT (Temp);\r
+\r
+    RemoveEntryList (CurrentLink);\r
+\r
+    if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
+      DestroyResourceTree (Temp);\r
+    }\r
+\r
+    FreePool (Temp);\r
+  }\r
+}\r
+\r
+/**\r
+  Insert resource padding for P2C.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingForCardBusBridge (\r
+  IN PCI_IO_DEVICE        *PciDev,\r
+  IN PCI_RESOURCE_NODE    *IoNode,\r
+  IN PCI_RESOURCE_NODE    *Mem32Node,\r
+  IN PCI_RESOURCE_NODE    *PMem32Node,\r
+  IN PCI_RESOURCE_NODE    *Mem64Node,\r
+  IN PCI_RESOURCE_NODE    *PMem64Node\r
+  )\r
+{\r
+  PCI_RESOURCE_NODE *Node;\r
+\r
+  Node = NULL;\r
+\r
+  //\r
+  // Memory Base/Limit Register 0\r
+  // Bar 1 denodes memory range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+           PciDev,\r
+           0x2000000,\r
+           0x1ffffff,\r
+           1,\r
+           PciBarTypeMem32,\r
+           PciResUsagePadding\r
+           );\r
+\r
+  InsertResourceNode (\r
+    Mem32Node,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Memory Base/Limit Register 1\r
+  // Bar 2 denodes memory range1\r
+  //\r
+  Node = CreateResourceNode (\r
+           PciDev,\r
+           0x2000000,\r
+           0x1ffffff,\r
+           2,\r
+           PciBarTypePMem32,\r
+           PciResUsagePadding\r
+           );\r
+\r
+  InsertResourceNode (\r
+    PMem32Node,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Io Base/Limit\r
+  // Bar 3 denodes io range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+           PciDev,\r
+           0x100,\r
+           0xff,\r
+           3,\r
+           PciBarTypeIo16,\r
+           PciResUsagePadding\r
+           );\r
+\r
+  InsertResourceNode (\r
+    IoNode,\r
+    Node\r
+    );\r
+\r
+  //\r
+  // Io Base/Limit\r
+  // Bar 4 denodes io range 0\r
+  //\r
+  Node = CreateResourceNode (\r
+           PciDev,\r
+           0x100,\r
+           0xff,\r
+           4,\r
+           PciBarTypeIo16,\r
+           PciResUsagePadding\r
+           );\r
+\r
+  InsertResourceNode (\r
+    IoNode,\r
+    Node\r
+    );\r
+}\r
+\r
+/**\r
+  Program PCI Card device register for given resource node.\r
+\r
+  @param Base    Base address of PCI Card device to be programmed.\r
+  @param Node    Given resource node.\r
+\r
+**/\r
+VOID\r
+ProgramP2C (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT64              Address;\r
+  UINT64              TempAddress;\r
+  UINT16              BridgeControl;\r
+\r
+  Address = 0;\r
+  PciIo   = &(Node->PciDev->PciIo);\r
+\r
+  Address = Base + Node->Offset;\r
+\r
+  //\r
+  // Indicate pci bus driver has allocated\r
+  // resource for this device\r
+  // It might be a temporary solution here since\r
+  // pci device could have multiple bar\r
+  //\r
+  Node->PciDev->Allocated = TRUE;\r
+\r
+  switch (Node->Bar) {\r
+\r
+  case P2C_BAR_0:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    break;\r
+\r
+  case P2C_MEM_1:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_MEMORY_BASE_0,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_MEMORY_LIMIT_0,\r
+                 1,\r
+                 &TempAddress\r
+                 );\r
+\r
+    if (Node->ResType == PciBarTypeMem32) {\r
+      //\r
+      // Set non-prefetchable bit\r
+      //\r
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+      BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
+      PciIo->Pci.Write (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+    } else {\r
+      //\r
+      // Set pre-fetchable bit\r
+      //\r
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+      BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
+      PciIo->Pci.Write (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+    }\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+\r
+    break;\r
+\r
+  case P2C_MEM_2:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_MEMORY_BASE_1,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_MEMORY_LIMIT_1,\r
+                 1,\r
+                 &TempAddress\r
+                 );\r
+\r
+    if (Node->ResType == PciBarTypeMem32) {\r
+\r
+      //\r
+      // Set non-prefetchable bit\r
+      //\r
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+      BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
+      PciIo->Pci.Write (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+    } else {\r
+\r
+      //\r
+      // Set pre-fetchable bit\r
+      //\r
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+\r
+      BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
+      PciIo->Pci.Write (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PCI_CARD_BRIDGE_CONTROL,\r
+                   1,\r
+                   &BridgeControl\r
+                   );\r
+    }\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+    break;\r
+\r
+  case P2C_IO_1:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_IO_BASE_0_LOWER,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_IO_LIMIT_0_LOWER,\r
+                 1,\r
+                 &TempAddress\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+\r
+    break;\r
+\r
+  case P2C_IO_2:\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_IO_BASE_1_LOWER,\r
+                 1,\r
+                 &Address\r
+                 );\r
+\r
+    TempAddress = Address + Node->Length - 1;\r
+    PciIo->Pci.Write (\r
+                 PciIo,\r
+                 EfiPciIoWidthUint32,\r
+                 PCI_CARD_IO_LIMIT_1_LOWER,\r
+                 1,\r
+                 &TempAddress\r
+                 );\r
+\r
+    Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+    Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
+    Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Create padding resource node.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ApplyResourcePadding (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN PCI_RESOURCE_NODE     *IoNode,\r
+  IN PCI_RESOURCE_NODE     *Mem32Node,\r
+  IN PCI_RESOURCE_NODE     *PMem32Node,\r
+  IN PCI_RESOURCE_NODE     *Mem64Node,\r
+  IN PCI_RESOURCE_NODE     *PMem64Node\r
+  )\r
+{\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  PCI_RESOURCE_NODE                 *Node;\r
+  UINT8                             DummyBarIndex;\r
+\r
+  DummyBarIndex = 0;\r
+  Ptr           = PciDev->ResourcePaddingDescriptors;\r
+\r
+  while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+      if (Ptr->AddrLen != 0) {\r
+\r
+        Node = CreateResourceNode (\r
+                PciDev,\r
+                Ptr->AddrLen,\r
+                Ptr->AddrRangeMax,\r
+                DummyBarIndex,\r
+                PciBarTypeIo16,\r
+                PciResUsagePadding\r
+                );\r
+        InsertResourceNode (\r
+          IoNode,\r
+          Node\r
+          );\r
+      }\r
+\r
+      Ptr++;\r
+      continue;\r
+    }\r
+\r
+    if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+      if (Ptr->AddrSpaceGranularity == 32) {\r
+\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0x6) {\r
+          if (Ptr->AddrLen != 0) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypePMem32,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              PMem32Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0) {\r
+          if (Ptr->AddrLen != 0) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypeMem32,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              Mem32Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+      }\r
+\r
+      if (Ptr->AddrSpaceGranularity == 64) {\r
+\r
+        //\r
+        // prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0x6) {\r
+          if (Ptr->AddrLen != 0) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypePMem64,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              PMem64Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+\r
+        //\r
+        // Non-prefechable\r
+        //\r
+        if (Ptr->SpecificFlag == 0) {\r
+          if (Ptr->AddrLen != 0) {\r
+            Node = CreateResourceNode (\r
+                    PciDev,\r
+                    Ptr->AddrLen,\r
+                    Ptr->AddrRangeMax,\r
+                    DummyBarIndex,\r
+                    PciBarTypeMem64,\r
+                    PciResUsagePadding\r
+                    );\r
+            InsertResourceNode (\r
+              Mem64Node,\r
+              Node\r
+              );\r
+          }\r
+\r
+          Ptr++;\r
+          continue;\r
+        }\r
+      }\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+}\r
+\r
+/**\r
+  Get padding resource for PCI-PCI bridge.\r
+\r
+  @param  PciIoDevice     PCI-PCI bridge device instance.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determines\r
+          whether need to pad resource for them.\r
+**/\r
+VOID\r
+GetResourcePaddingPpb (\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+  )\r
+{\r
+  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
+    if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+      GetResourcePaddingForHpb (PciIoDevice);\r
+    }\r
+  }\r
+}\r
+\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.h
new file mode 100644 (file)
index 0000000..faa6c0d
--- /dev/null
@@ -0,0 +1,492 @@
+/** @file\r
+  PCI resouces support functions declaration for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_RESOURCE_SUPPORT_H_\r
+#define _EFI_PCI_RESOURCE_SUPPORT_H_\r
+\r
+typedef enum {\r
+  PciResUsageTypical            = 0,\r
+  PciResUsagePadding,\r
+  PciResUsageOptionRomProcessing\r
+} PCI_RESOURCE_USAGE;\r
+\r
+#define PCI_RESOURCE_SIGNATURE  SIGNATURE_32 ('p', 'c', 'r', 'c')\r
+\r
+typedef struct {\r
+  UINT32              Signature;\r
+  LIST_ENTRY          Link;\r
+  LIST_ENTRY          ChildList;\r
+  PCI_IO_DEVICE       *PciDev;\r
+  UINT64              Alignment;\r
+  UINT64              Offset;\r
+  UINT8               Bar;\r
+  PCI_BAR_TYPE        ResType;\r
+  UINT64              Length;\r
+  BOOLEAN             Reserved;\r
+  PCI_RESOURCE_USAGE  ResourceUsage;\r
+  BOOLEAN             Virtual;\r
+} PCI_RESOURCE_NODE;\r
+\r
+#define RESOURCE_NODE_FROM_LINK(a) \\r
+  CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE)\r
+\r
+/**\r
+  The function is used to skip VGA range.\r
+\r
+  @param Start    Returned start address including VGA range.\r
+  @param Length   The length of VGA range.\r
+\r
+**/\r
+VOID\r
+SkipVGAAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  );\r
+\r
+/**\r
+  This function is used to skip ISA aliasing aperture.\r
+\r
+  @param Start    Returned start address including ISA aliasing aperture.\r
+  @param Length   The length of ISA aliasing aperture.\r
+\r
+**/\r
+VOID\r
+SkipIsaAliasAperture (\r
+  OUT UINT64   *Start,\r
+  IN  UINT64   Length\r
+  );\r
+\r
+/**\r
+  This function inserts a resource node into the resource list.\r
+  The resource list is sorted in descend order.\r
+\r
+  @param Bridge  PCI resource node for bridge.\r
+  @param ResNode Resource node want to be inserted.\r
+\r
+**/\r
+VOID\r
+InsertResourceNode (\r
+  IN OUT PCI_RESOURCE_NODE   *Bridge,\r
+  IN     PCI_RESOURCE_NODE   *ResNode\r
+  );\r
+\r
+/**\r
+  This routine is used to merge two different resource trees in need of\r
+  resoure degradation.\r
+\r
+  For example, if an upstream PPB doesn't support,\r
+  prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+  to merge prefectchable memory resource list into normal memory list.\r
+\r
+  If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+  type.\r
+  If Dst is NULL or Res is NULL, ASSERT ().\r
+\r
+  @param Dst        Point to destination resource tree.\r
+  @param Res        Point to source resource tree.\r
+  @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of\r
+                    destination resource type.\r
+\r
+**/\r
+VOID\r
+MergeResourceTree (\r
+  IN PCI_RESOURCE_NODE   *Dst,\r
+  IN PCI_RESOURCE_NODE   *Res,\r
+  IN BOOLEAN             TypeMerge\r
+  );\r
+\r
+/**\r
+  This function is used to calculate the IO16 aperture\r
+  for a bridge.\r
+\r
+  @param Bridge    PCI resource node for bridge.\r
+\r
+**/\r
+VOID\r
+CalculateApertureIo16 (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  );\r
+\r
+/**\r
+  This function is used to calculate the resource aperture\r
+  for a given bridge device.\r
+\r
+  @param Bridge      PCI resouce node for given bridge device.\r
+\r
+**/\r
+VOID\r
+CalculateResourceAperture (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  );\r
+\r
+/**\r
+  Get IO/Memory resource infor for given PCI device.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO .\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+GetResourceFromDevice (\r
+  IN     PCI_IO_DEVICE     *PciDev,\r
+  IN OUT PCI_RESOURCE_NODE *IoNode,\r
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+  );\r
+\r
+/**\r
+  This function is used to create a resource node.\r
+\r
+  @param PciDev       Pci device instance.\r
+  @param Length       Length of Io/Memory resource.\r
+  @param Alignment    Alignment of resource.\r
+  @param Bar          Bar index.\r
+  @param ResType      Type of resource: IO/Memory.\r
+  @param ResUsage     Resource usage.\r
+\r
+  @return PCI resource node created for given PCI device.\r
+          NULL means PCI resource node is not created.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  );\r
+\r
+/**\r
+  This function is used to extract resource request from\r
+  IOV VF device node list.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+PCI_RESOURCE_NODE *\r
+CreateVfResourceNode (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN UINT64                Length,\r
+  IN UINT64                Alignment,\r
+  IN UINT8                 Bar,\r
+  IN PCI_BAR_TYPE          ResType,\r
+  IN PCI_RESOURCE_USAGE    ResUsage\r
+  );\r
+\r
+/**\r
+  This function is used to extract resource request from\r
+  device node list.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+CreateResourceMap (\r
+  IN     PCI_IO_DEVICE     *Bridge,\r
+  IN OUT PCI_RESOURCE_NODE *IoNode,\r
+  IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
+  IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
+  IN OUT PCI_RESOURCE_NODE *PMem64Node\r
+  );\r
+\r
+/**\r
+  This function is used to do the resource padding for a specific platform.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingPolicy (\r
+  IN PCI_IO_DEVICE     *PciDev,\r
+  IN PCI_RESOURCE_NODE *IoNode,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  );\r
+\r
+/**\r
+  This function is used to degrade resource if the upstream bridge\r
+  doesn't support certain resource. Degradation path is\r
+  PMEM64 -> MEM64  -> MEM32\r
+  PMEM64 -> PMEM32 -> MEM32\r
+  IO32   -> IO16.\r
+\r
+  @param Bridge     Pci device instance.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+DegradeResource (\r
+  IN PCI_IO_DEVICE     *Bridge,\r
+  IN PCI_RESOURCE_NODE *Mem32Node,\r
+  IN PCI_RESOURCE_NODE *PMem32Node,\r
+  IN PCI_RESOURCE_NODE *Mem64Node,\r
+  IN PCI_RESOURCE_NODE *PMem64Node\r
+  );\r
+\r
+/**\r
+  Test whether bridge device support decode resource.\r
+\r
+  @param Bridge    Bridge device instance.\r
+  @param Decode    Decode type according to resource type.\r
+\r
+  @return TRUE     The bridge device support decode resource.\r
+  @return FALSE    The bridge device don't support decode resource.\r
+\r
+**/\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+  IN PCI_IO_DEVICE *Bridge,\r
+  IN UINT32        Decode\r
+  );\r
+\r
+/**\r
+  This function is used to program the resource allocated\r
+  for each resource node under specified bridge.\r
+\r
+  @param Base     Base address of resource to be progammed.\r
+  @param Bridge   PCI resource node for the bridge device.\r
+\r
+  @retval EFI_SUCCESS            Successfully to program all resouces\r
+                                 on given PCI bridge device.\r
+  @retval EFI_OUT_OF_RESOURCES   Base is all one.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramResource (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  );\r
+\r
+/**\r
+  Program Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  );\r
+\r
+/**\r
+  Program IOV VF Bar register for PCI device.\r
+\r
+  @param Base  Base address for PCI device resource to be progammed.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+EFI_STATUS\r
+ProgramVfBar (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  );\r
+\r
+/**\r
+  Program PCI-PCI bridge apperture.\r
+\r
+  @param Base  Base address for resource.\r
+  @param Node  Point to resoure node structure.\r
+\r
+**/\r
+VOID\r
+ProgramPpbApperture (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  );\r
+\r
+/**\r
+  Program parent bridge for Option Rom.\r
+\r
+  @param PciDevice      Pci deivce instance.\r
+  @param OptionRomBase  Base address for Optiona Rom.\r
+  @param Enable         Enable or disable PCI memory.\r
+\r
+**/\r
+VOID\r
+ProgrameUpstreamBridgeForRom (\r
+  IN PCI_IO_DEVICE   *PciDevice,\r
+  IN UINT32          OptionRomBase,\r
+  IN BOOLEAN         Enable\r
+  );\r
+\r
+/**\r
+  Test whether resource exists for a bridge.\r
+\r
+  @param Bridge  Point to resource node for a bridge.\r
+\r
+  @retval TRUE   There is resource on the given bridge.\r
+  @retval FALSE  There isn't resource on the given bridge.\r
+\r
+**/\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+  IN PCI_RESOURCE_NODE    *Bridge\r
+  );\r
+\r
+/**\r
+  Initialize resource pool structure.\r
+\r
+  @param ResourcePool Point to resource pool structure. This pool\r
+                      is reset to all zero when returned.\r
+  @param ResourceType Type of resource.\r
+\r
+**/\r
+VOID\r
+InitializeResourcePool (\r
+  IN OUT PCI_RESOURCE_NODE   *ResourcePool,\r
+  IN     PCI_BAR_TYPE        ResourceType\r
+  );\r
+\r
+/**\r
+  Get all resource information for given Pci device.\r
+\r
+  @param PciDev         Pci device instance.\r
+  @param IoBridge       Io resource node.\r
+  @param Mem32Bridge    32-bit memory node.\r
+  @param PMem32Bridge   32-bit Pmemory node.\r
+  @param Mem64Bridge    64-bit memory node.\r
+  @param PMem64Bridge   64-bit PMemory node.\r
+  @param IoPool         Link list header for Io resource.\r
+  @param Mem32Pool      Link list header for 32-bit memory.\r
+  @param PMem32Pool     Link list header for 32-bit Prefetchable memory.\r
+  @param Mem64Pool      Link list header for 64-bit memory.\r
+  @param PMem64Pool     Link list header for 64-bit Prefetchable memory.\r
+\r
+**/\r
+VOID\r
+GetResourceMap (\r
+  IN PCI_IO_DEVICE      *PciDev,\r
+  IN PCI_RESOURCE_NODE  **IoBridge,\r
+  IN PCI_RESOURCE_NODE  **Mem32Bridge,\r
+  IN PCI_RESOURCE_NODE  **PMem32Bridge,\r
+  IN PCI_RESOURCE_NODE  **Mem64Bridge,\r
+  IN PCI_RESOURCE_NODE  **PMem64Bridge,\r
+  IN PCI_RESOURCE_NODE  *IoPool,\r
+  IN PCI_RESOURCE_NODE  *Mem32Pool,\r
+  IN PCI_RESOURCE_NODE  *PMem32Pool,\r
+  IN PCI_RESOURCE_NODE  *Mem64Pool,\r
+  IN PCI_RESOURCE_NODE  *PMem64Pool\r
+  );\r
+\r
+/**\r
+  Destory given resource tree.\r
+\r
+  @param Bridge  PCI resource root node of resource tree.\r
+\r
+**/\r
+VOID\r
+DestroyResourceTree (\r
+  IN PCI_RESOURCE_NODE *Bridge\r
+  );\r
+\r
+/**\r
+  Insert resource padding for P2C.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ResourcePaddingForCardBusBridge (\r
+  IN PCI_IO_DEVICE        *PciDev,\r
+  IN PCI_RESOURCE_NODE    *IoNode,\r
+  IN PCI_RESOURCE_NODE    *Mem32Node,\r
+  IN PCI_RESOURCE_NODE    *PMem32Node,\r
+  IN PCI_RESOURCE_NODE    *Mem64Node,\r
+  IN PCI_RESOURCE_NODE    *PMem64Node\r
+  );\r
+\r
+/**\r
+  Program PCI Card device register for given resource node.\r
+\r
+  @param Base    Base address of PCI Card device to be programmed.\r
+  @param Node    Given resource node.\r
+\r
+**/\r
+VOID\r
+ProgramP2C (\r
+  IN UINT64            Base,\r
+  IN PCI_RESOURCE_NODE *Node\r
+  );\r
+\r
+/**\r
+  Create padding resource node.\r
+\r
+  @param PciDev     Pci device instance.\r
+  @param IoNode     Resource info node for IO.\r
+  @param Mem32Node  Resource info node for 32-bit memory.\r
+  @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
+  @param Mem64Node  Resource info node for 64-bit memory.\r
+  @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
+\r
+**/\r
+VOID\r
+ApplyResourcePadding (\r
+  IN PCI_IO_DEVICE         *PciDev,\r
+  IN PCI_RESOURCE_NODE     *IoNode,\r
+  IN PCI_RESOURCE_NODE     *Mem32Node,\r
+  IN PCI_RESOURCE_NODE     *PMem32Node,\r
+  IN PCI_RESOURCE_NODE     *Mem64Node,\r
+  IN PCI_RESOURCE_NODE     *PMem64Node\r
+  );\r
+\r
+/**\r
+  Get padding resource for PCI-PCI bridge.\r
+\r
+  @param  PciIoDevice     PCI-PCI bridge device instance.\r
+\r
+  @note   Feature flag PcdPciBusHotplugDeviceSupport determines\r
+          whether need to pad resource for them.\r
+**/\r
+VOID\r
+GetResourcePaddingPpb (\r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.c
new file mode 100644 (file)
index 0000000..9addcf9
--- /dev/null
@@ -0,0 +1,126 @@
+/** @file\r
+  Set up ROM Table for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciBus.h"\r
+\r
+//\r
+// PCI ROM image information\r
+//\r
+typedef struct {\r
+  EFI_HANDLE  ImageHandle;\r
+  UINTN       Seg;\r
+  UINT8       Bus;\r
+  UINT8       Dev;\r
+  UINT8       Func;\r
+  UINT64      RomAddress;\r
+  UINT64      RomLength;\r
+} EFI_PCI_ROM_IMAGE_MAPPING;\r
+\r
+UINTN                      mNumberOfPciRomImages     = 0;\r
+UINTN                      mMaxNumberOfPciRomImages  = 0;\r
+EFI_PCI_ROM_IMAGE_MAPPING  *mRomImageTable           = NULL;\r
+\r
+/**\r
+  Add the Rom Image to internal database for later PCI light enumeration.\r
+\r
+  @param ImageHandle    Option Rom image handle.\r
+  @param Seg            Segment of PCI space.\r
+  @param Bus            Bus NO of PCI space.\r
+  @param Dev            Dev NO of PCI space.\r
+  @param Func           Func NO of PCI space.\r
+  @param RomAddress     Base address of OptionRom.\r
+  @param RomLength      Length of rom image.\r
+\r
+**/\r
+VOID\r
+PciRomAddImageMapping (\r
+  IN  EFI_HANDLE  ImageHandle,\r
+  IN  UINTN       Seg,\r
+  IN  UINT8       Bus,\r
+  IN  UINT8       Dev,\r
+  IN  UINT8       Func,\r
+  IN  UINT64      RomAddress,\r
+  IN  UINT64      RomLength\r
+  )\r
+{\r
+  EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;\r
+\r
+  if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {\r
+\r
+    mMaxNumberOfPciRomImages += 0x20;\r
+\r
+    TempMapping = NULL;\r
+    TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+    if (TempMapping == NULL) {\r
+      return ;\r
+    }\r
+\r
+    CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));\r
+\r
+    if (mRomImageTable != NULL) {\r
+      FreePool (mRomImageTable);\r
+    }\r
+\r
+    mRomImageTable = TempMapping;\r
+  }\r
+\r
+  mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;\r
+  mRomImageTable[mNumberOfPciRomImages].Seg         = Seg;\r
+  mRomImageTable[mNumberOfPciRomImages].Bus         = Bus;\r
+  mRomImageTable[mNumberOfPciRomImages].Dev         = Dev;\r
+  mRomImageTable[mNumberOfPciRomImages].Func        = Func;\r
+  mRomImageTable[mNumberOfPciRomImages].RomAddress  = RomAddress;\r
+  mRomImageTable[mNumberOfPciRomImages].RomLength   = RomLength;\r
+  mNumberOfPciRomImages++;\r
+}\r
+\r
+/**\r
+  Get Option rom driver's mapping for PCI device.\r
+\r
+  @param PciIoDevice Device instance.\r
+\r
+  @retval TRUE   Found Image mapping.\r
+  @retval FALSE  Cannot found image mapping.\r
+\r
+**/\r
+BOOLEAN\r
+PciRomGetImageMapping (\r
+  IN  PCI_IO_DEVICE                       *PciIoDevice\r
+  )\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  UINTN                           Index;\r
+  BOOLEAN                         Found;\r
+\r
+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
+  Found           = FALSE;\r
+\r
+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {\r
+    if (mRomImageTable[Index].Seg  == PciRootBridgeIo->SegmentNumber &&\r
+        mRomImageTable[Index].Bus  == PciIoDevice->BusNumber         &&\r
+        mRomImageTable[Index].Dev  == PciIoDevice->DeviceNumber      &&\r
+        mRomImageTable[Index].Func == PciIoDevice->FunctionNumber    ) {\r
+        Found = TRUE;\r
+\r
+      if (mRomImageTable[Index].ImageHandle != NULL) {\r
+        AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);\r
+      } else {\r
+        PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress;\r
+        PciIoDevice->PciIo.RomSize  = (UINTN) mRomImageTable[Index].RomLength;\r
+      }\r
+    }\r
+  }\r
+\r
+  return Found;\r
+}\r
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciRomTable.h
new file mode 100644 (file)
index 0000000..e1b41a7
--- /dev/null
@@ -0,0 +1,55 @@
+/** @file\r
+  Set up ROM Table for PCI Bus module.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_PCI_ROM_TABLE_H_\r
+#define _EFI_PCI_ROM_TABLE_H_\r
+\r
+/**\r
+  Add the Rom Image to internal database for later PCI light enumeration.\r
+\r
+  @param ImageHandle    Option Rom image handle.\r
+  @param Seg            Segment of PCI space.\r
+  @param Bus            Bus NO of PCI space.\r
+  @param Dev            Dev NO of PCI space.\r
+  @param Func           Func NO of PCI space.\r
+  @param RomAddress     Base address of OptionRom.\r
+  @param RomLength      Length of rom image.\r
+\r
+**/\r
+VOID\r
+PciRomAddImageMapping (\r
+  IN  EFI_HANDLE  ImageHandle,\r
+  IN  UINTN       Seg,\r
+  IN  UINT8       Bus,\r
+  IN  UINT8       Dev,\r
+  IN  UINT8       Func,\r
+  IN  UINT64      RomAddress,\r
+  IN  UINT64      RomLength\r
+  );\r
+\r
+/**\r
+  Get Option rom driver's mapping for PCI device.\r
+\r
+  @param PciIoDevice Device instance.\r
+\r
+  @retval TRUE   Found Image mapping.\r
+  @retval FALSE  Cannot found image mapping.\r
+\r
+**/\r
+BOOLEAN\r
+PciRomGetImageMapping (\r
+  IN  PCI_IO_DEVICE                       *PciIoDevice\r
+  );\r
+\r
+#endif\r
index 7a167ac61959201cd5c8ffced1c2873fa8bb9f99..d3ca875c220d705500004e35c3c25c15cd05975f 100644 (file)
   #  If FALSE, DXE IPL will not support UEFI decompression to save space.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|TRUE|BOOLEAN|0x0001200c\r
 \r
+  ## This PCD specifies whether PciBus supports the hot plug device.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport|TRUE|BOOLEAN|0x0001003d\r
+\r
+  ## This PCD specifies whether the Single Root I/O virtualization support.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport|TRUE|BOOLEAN|0x10000044\r
+\r
+  ## This PCD specifies whether the Alternative Routing-ID support.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport|TRUE|BOOLEAN|0x10000045\r
+\r
+  ## This PCD specifies whether the Multi Root I/O virtualization support.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport|FALSE|BOOLEAN|0x10000046\r
+\r
+\r
 [PcdsFeatureFlag.IA32]\r
   ##\r
   # This feature flag specifies whether DxeIpl switches to long mode to enter DXE phase.\r
   ## FFS filename to find the ACPI tables\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile|{ 0x25, 0x4e, 0x37, 0x7e, 0x01, 0x8e, 0xee, 0x4f, 0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd }|VOID*|16\r
 \r
+  ## Single root I/O virtualization virtual function memory BAR alignment\r
+  #  BITN set indicates 2 of n+12 power\r
+  #  BIT0 set indicates 4KB alignment\r
+  #  BIT1 set indicates 8KB alignment\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047\r
+\r
 [PcdsFixedAtBuild,PcdsPatchableInModule]\r
   ## Maximun number of performance log entries during PEI phase.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f\r
index 0b4e258490296ecbc2c621bb9b86fed0c36f0d10..4d1d94184883dc13dd8eba4a39caa1bde09f35cd 100644 (file)
 [Components.common]\r
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf\r
 \r
+  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
+  MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf\r
   MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf\r
   MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf\r
   MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf\r