]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumeratorSupport.c
index 7d08246711b1fd9209edbbf5a1dda00508add3f8..c7eafff5935545cfafb9b55ad8a7e744b131ce24 100644 (file)
@@ -1,19 +1,21 @@
 /** @file\r
   PCI emumeration support functions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2010, 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
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "PciBus.h"\r
 \r
+extern CHAR16  *mBarTypeStr[];\r
+\r
+#define OLD_ALIGN   0xFFFFFFFFFFFFFFFFULL\r
+#define EVEN_ALIGN  0xFFFFFFFFFFFFFFFEULL\r
+#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL\r
+#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL\r
+\r
 /**\r
   This routine is used to check whether the pci device is present.\r
 \r
@@ -80,7 +82,7 @@ PciDevicePresent (
   root bridge will then be created.\r
 \r
   @param Bridge         Parent bridge instance.\r
-  @param StartBusNumber Bus number of begining.\r
+  @param StartBusNumber Bus number of beginning.\r
 \r
   @retval EFI_SUCCESS   PCI device is found.\r
   @retval other         Some error occurred when reading PCI bridge information.\r
@@ -117,6 +119,14 @@ PciPciDeviceInfoCollector (
                  (UINT8) Device,\r
                  (UINT8) Func\r
                  );\r
+\r
+      if (EFI_ERROR (Status) && Func == 0) {\r
+        //\r
+        // go to next device if there is no Function 0\r
+        //\r
+        break;\r
+      }\r
+\r
       if (!EFI_ERROR (Status)) {\r
 \r
         //\r
@@ -153,6 +163,14 @@ PciPciDeviceInfoCollector (
             return Status;\r
           }\r
 \r
+          //\r
+          // Ensure secondary bus number is greater than the primary bus number to avoid\r
+          // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE\r
+          //\r
+          if (SecBus <= StartBusNumber) {\r
+            break;\r
+          }\r
+\r
           //\r
           // Get resource padding for PPB\r
           //\r
@@ -184,7 +202,7 @@ PciPciDeviceInfoCollector (
 }\r
 \r
 /**\r
-  Seach required device and create PCI device instance.\r
+  Search required device and create PCI device instance.\r
 \r
   @param Bridge     Parent bridge instance.\r
   @param Pci        Input PCI device information block.\r
@@ -211,6 +229,15 @@ PciSearchDevice (
 \r
   PciIoDevice = NULL;\r
 \r
+  DEBUG ((\r
+    EFI_D_INFO,\r
+    "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",\r
+    IS_PCI_BRIDGE (Pci) ?     L"PPB" :\r
+    IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :\r
+                              L"PCI",\r
+    Bus, Device, Func\r
+    ));\r
+\r
   if (!IS_PCI_BRIDGE (Pci)) {\r
 \r
     if (IS_CARDBUS_BRIDGE (Pci)) {\r
@@ -304,6 +331,121 @@ PciSearchDevice (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Dump the PPB padding resource information.\r
+\r
+  @param PciIoDevice     PCI IO instance.\r
+  @param ResourceType    The desired resource type to dump.\r
+                         PciBarTypeUnknown means to dump all types of resources.\r
+**/\r
+VOID\r
+DumpPpbPaddingResource (\r
+  IN PCI_IO_DEVICE                    *PciIoDevice,\r
+  IN PCI_BAR_TYPE                     ResourceType\r
+  )\r
+{\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+  PCI_BAR_TYPE                      Type;\r
+\r
+  if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) {\r
+    ResourceType = PciBarTypeIo;\r
+  }\r
+\r
+  for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {\r
+\r
+    Type = PciBarTypeUnknown;\r
+    if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+      Type = PciBarTypeIo;\r
+    } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+      if (Descriptor->AddrSpaceGranularity == 32) {\r
+        //\r
+        // prefetchable\r
+        //\r
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+          Type = PciBarTypePMem32;\r
+        }\r
+\r
+        //\r
+        // Non-prefetchable\r
+        //\r
+        if (Descriptor->SpecificFlag == 0) {\r
+          Type = PciBarTypeMem32;\r
+        }\r
+      }\r
+\r
+      if (Descriptor->AddrSpaceGranularity == 64) {\r
+        //\r
+        // prefetchable\r
+        //\r
+        if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+          Type = PciBarTypePMem64;\r
+        }\r
+\r
+        //\r
+        // Non-prefetchable\r
+        //\r
+        if (Descriptor->SpecificFlag == 0) {\r
+          Type = PciBarTypeMem64;\r
+        }\r
+      }\r
+    }\r
+\r
+    if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",\r
+        mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen\r
+        ));\r
+    }\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Dump the PCI BAR information.\r
+\r
+  @param PciIoDevice     PCI IO instance.\r
+**/\r
+VOID\r
+DumpPciBars (\r
+  IN PCI_IO_DEVICE                    *PciIoDevice\r
+  )\r
+{\r
+  UINTN                               Index;\r
+\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+    if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",\r
+      Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],\r
+      PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset\r
+      ));\r
+  }\r
+\r
+  for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+    if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG ((\r
+      EFI_D_INFO,\r
+      " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",\r
+      Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],\r
+      PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset\r
+      ));\r
+  }\r
+  DEBUG ((EFI_D_INFO, "\n"));\r
+}\r
+\r
 /**\r
   Create PCI device instance for PCI device.\r
 \r
@@ -328,11 +470,9 @@ GatherDeviceInfo (
   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
+                  Bridge,\r
                   Pci,\r
                   Bus,\r
                   Device,\r
@@ -343,14 +483,6 @@ GatherDeviceInfo (
     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
@@ -370,7 +502,7 @@ GatherDeviceInfo (
   //\r
   // Parse the SR-IOV VF bars\r
   //\r
-  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+  if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 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
@@ -379,6 +511,8 @@ GatherDeviceInfo (
       Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
     }\r
   }\r
+\r
+  DEBUG_CODE (DumpPciBars (PciIoDevice););\r
   return PciIoDevice;\r
 }\r
 \r
@@ -403,16 +537,17 @@ GatherPpbInfo (
   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
+  UINT32                          PMemBaseLimit;\r
+  UINT16                          PrefetchableMemoryBase;\r
+  UINT16                          PrefetchableMemoryLimit;\r
 \r
-  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
   PciIoDevice = CreatePciIoDevice (\r
-                  PciRootBridgeIo,\r
+                  Bridge,\r
                   Pci,\r
                   Bus,\r
                   Device,\r
@@ -423,19 +558,11 @@ GatherPpbInfo (
     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
+    // Initialize the bridge control register\r
     //\r
     PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
 \r
@@ -471,14 +598,14 @@ GatherPpbInfo (
 \r
   //\r
   // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes\r
-  // PCI bridge supporting non-stardard I/O window alignment less than 4K.\r
+  // PCI bridge supporting non-standard I/O window alignment less than 4K.\r
   //\r
 \r
   PciIoDevice->BridgeIoAlignment = 0xFFF;\r
   if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {\r
     //\r
     // Check any bits of bit 3-1 of I/O Base Register are writable.\r
-    // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.\r
+    // if so, it is assumed non-standard I/O window alignment is supported by this bridge.\r
     // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.\r
     //\r
     Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));\r
@@ -503,14 +630,22 @@ GatherPpbInfo (
             PciIoDevice,\r
             0x24,\r
             NULL,\r
-            NULL\r
+            &PMemBaseLimit\r
             );\r
 \r
   //\r
   // Test if it supports 64 memory or not\r
   //\r
-  if (!EFI_ERROR (Status)) {\r
-\r
+  // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit\r
+  // registers:\r
+  //   0 - the bridge supports only 32 bit addresses.\r
+  //   1 - the bridge supports 64-bit addresses.\r
+  //\r
+  PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);\r
+  PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);\r
+  if (!EFI_ERROR (Status) &&\r
+      (PrefetchableMemoryBase & 0x000f) == 0x0001 &&\r
+      (PrefetchableMemoryLimit & 0x000f) == 0x0001) {\r
     Status = BarExisted (\r
               PciIoDevice,\r
               0x28,\r
@@ -533,6 +668,11 @@ GatherPpbInfo (
 \r
   GetResourcePaddingPpb (PciIoDevice);\r
 \r
+  DEBUG_CODE (\r
+    DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);\r
+    DumpPciBars (PciIoDevice);\r
+  );\r
+\r
   return PciIoDevice;\r
 }\r
 \r
@@ -558,12 +698,10 @@ GatherP2CInfo (
   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
+                  Bridge,\r
                   Pci,\r
                   Bus,\r
                   Device,\r
@@ -574,19 +712,11 @@ GatherP2CInfo (
     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
+    // Initialize the bridge control register\r
     //\r
     PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
   }\r
@@ -604,11 +734,13 @@ GatherP2CInfo (
                          EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
                          EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
 \r
+  DEBUG_CODE (DumpPciBars (PciIoDevice););\r
+\r
   return PciIoDevice;\r
 }\r
 \r
 /**\r
-  Create device path for pci deivce.\r
+  Create device path for pci device.\r
 \r
   @param ParentDevicePath  Parent bridge's path.\r
   @param PciIoDevice       Pci device instance.\r
@@ -784,7 +916,7 @@ BarExisted (
   @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
+  @param BridgeControl    Input 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
@@ -909,16 +1041,17 @@ PciSetDeviceAttribute (
 \r
   if (Option == EFI_SET_SUPPORTS) {\r
 \r
-    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
+    Attributes |= (UINT64) (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
+                  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
+    if (IS_PCI_LPC (&PciIoDevice->Pci)) {\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+        Attributes |= (mReserveIsaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO : \\r
+                                            (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);\r
     }\r
 \r
     if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
@@ -927,6 +1060,14 @@ PciSetDeviceAttribute (
       //\r
       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+\r
+      if (mReserveVgaAliases) {\r
+        Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \\r
+                                EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);\r
+      } else {\r
+        Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \\r
+                                EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
+      }\r
     } else {\r
 \r
       if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
@@ -936,7 +1077,8 @@ PciSetDeviceAttribute (
 \r
       if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
         Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
-        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+        Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
+                                            (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
       }\r
     }\r
 \r
@@ -946,6 +1088,15 @@ PciSetDeviceAttribute (
                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
 \r
   } else {\r
+    //\r
+    // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were\r
+    // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.\r
+    // When this attribute is set, the PCI option ROM described by the RomImage and RomSize\r
+    // fields is not from the the ROM BAR of the PCI controller.\r
+    //\r
+    if (!PciIoDevice->EmbeddedRom) {\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;\r
+    }\r
     PciIoDevice->Attributes = Attributes;\r
   }\r
 }\r
@@ -1048,7 +1199,7 @@ DetermineDeviceAttribute (
   EFI_STATUS      Status;\r
 \r
   //\r
-  // For Root Bridge, just copy it by RootBridgeIo proctocol\r
+  // For Root Bridge, just copy it by RootBridgeIo protocol\r
   // so as to keep consistent with the actual attribute\r
   //\r
   if (PciIoDevice->Parent == NULL) {\r
@@ -1060,6 +1211,13 @@ DetermineDeviceAttribute (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+    //\r
+    // Assume the PCI Root Bridge supports DAC\r
+    //\r
+    PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
+                              EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
+                              EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
+\r
   } else {\r
 \r
     //\r
@@ -1090,9 +1248,11 @@ DetermineDeviceAttribute (
     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
+    // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL\r
+    // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.\r
+    if (!PciIoDevice->IsPciExp) {\r
+      PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+    }\r
   }\r
 \r
   FastB2BSupport = TRUE;\r
@@ -1116,7 +1276,7 @@ DetermineDeviceAttribute (
       return Status;\r
     }\r
     //\r
-    // Detect Fast Bact to Bact support for the device under the bridge\r
+    // Detect Fast Back to Back support for the device under the bridge\r
     //\r
     Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
     if (FastB2BSupport && EFI_ERROR (Status)) {\r
@@ -1177,7 +1337,6 @@ UpdatePciInfo (
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             BarIndex;\r
-  UINTN                             BarEndIndex;\r
   BOOLEAN                           SetFlag;\r
   VOID                              *Configuration;\r
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
@@ -1185,7 +1344,7 @@ UpdatePciInfo (
   Configuration = NULL;\r
   Status        = EFI_SUCCESS;\r
 \r
-  if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
+  if (gIncompatiblePciDeviceSupport == NULL) {\r
     //\r
     // It can only be supported after the Incompatible PCI Device\r
     // Support Protocol has been installed\r
@@ -1193,7 +1352,7 @@ UpdatePciInfo (
     Status = gBS->LocateProtocol (\r
                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
                     NULL,\r
-                    (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+                    (VOID **) &gIncompatiblePciDeviceSupport\r
                     );\r
   }\r
   if (Status == EFI_SUCCESS) {\r
@@ -1201,15 +1360,15 @@ UpdatePciInfo (
       // 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
+      Status = gIncompatiblePciDeviceSupport->CheckDevice (\r
+                                                gIncompatiblePciDeviceSupport,\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
@@ -1231,23 +1390,19 @@ UpdatePciInfo (
       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
+    for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+      if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&\r
+          (Ptr->AddrTranslationOffset != MAX_UINT8) &&\r
+          (Ptr->AddrTranslationOffset != BarIndex)\r
+          ) {\r
+        //\r
+        // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).\r
+        // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.\r
+        // Comparing against MAX_UINT8 is to keep backward compatibility.\r
+        //\r
+        continue;\r
+      }\r
 \r
-    for (; BarIndex <= BarEndIndex; BarIndex++) {\r
       SetFlag = FALSE;\r
       switch (Ptr->ResType) {\r
       case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
@@ -1257,6 +1412,38 @@ UpdatePciInfo (
         //\r
         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
           SetFlag = TRUE;\r
+\r
+          //\r
+          // Ignored if granularity is 0.\r
+          // Ignored if PCI BAR is I/O or 32-bit memory.\r
+          // If PCI BAR is 64-bit memory and granularity is 32, then\r
+          // the PCI BAR resource is allocated below 4GB.\r
+          // If PCI BAR is 64-bit memory and granularity is 64, then\r
+          // the PCI BAR resource is allocated above 4GB.\r
+          //\r
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {\r
+            switch (Ptr->AddrSpaceGranularity) {\r
+            case 32:\r
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+            case 64:\r
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+              break;\r
+            default:\r
+              break;\r
+            }\r
+          }\r
+\r
+          if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {\r
+            switch (Ptr->AddrSpaceGranularity) {\r
+            case 32:\r
+              PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+            case 64:\r
+              PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+              break;\r
+            default:\r
+              break;\r
+            }\r
+          }\r
         }\r
         break;\r
 \r
@@ -1281,7 +1468,7 @@ UpdatePciInfo (
         //\r
         // Update the new length for the device\r
         //\r
-        if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+        if (Ptr->AddrLen != 0) {\r
           PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
         }\r
       }\r
@@ -1297,6 +1484,8 @@ UpdatePciInfo (
 \r
 /**\r
   This routine will update the alignment with the new alignment.\r
+  Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep\r
+  backward compatibility.\r
 \r
   @param Alignment    Input Old alignment. Output updated alignment.\r
   @param NewAlignment New alignment.\r
@@ -1315,15 +1504,15 @@ SetNewAlign (
   // The new alignment is the same as the original,\r
   // so skip it\r
   //\r
-  if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+  if ((NewAlignment == 0) || (NewAlignment == 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
+   if (NewAlignment != EVEN_ALIGN  &&\r
+       NewAlignment != SQUAD_ALIGN &&\r
+       NewAlignment != DQUAD_ALIGN ) {\r
     *Alignment = NewAlignment;\r
     return ;\r
   }\r
@@ -1342,15 +1531,15 @@ SetNewAlign (
   //\r
   // Adjust the alignment to even, quad or double quad boundary\r
   //\r
-  if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+  if (NewAlignment == EVEN_ALIGN) {\r
     if ((OldAlignment & 0x01) != 0) {\r
       OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
     }\r
-  } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+  } else if (NewAlignment == SQUAD_ALIGN) {\r
     if ((OldAlignment & 0x03) != 0) {\r
       OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
     }\r
-  } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+  } else if (NewAlignment == DQUAD_ALIGN) {\r
     if ((OldAlignment & 0x07) != 0) {\r
       OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
     }\r
@@ -1385,8 +1574,6 @@ PciIovParseVfBar (
   UINT32      Value;\r
   UINT32      OriginalValue;\r
   UINT32      Mask;\r
-  UINT32      Data;\r
-  UINT8       Index;\r
   EFI_STATUS  Status;\r
 \r
   //\r
@@ -1415,11 +1602,11 @@ PciIovParseVfBar (
     //\r
     // Scan all the BARs anyway\r
     //\r
-    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;\r
     return Offset + 4;\r
   }\r
 \r
-  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;\r
   if ((Value & 0x01) != 0) {\r
     //\r
     // Device I/Os. Impossible\r
@@ -1502,14 +1689,9 @@ PciIovParseVfBar (
       }\r
 \r
       //\r
-      // Fix the length to support some spefic 64 bit BAR\r
+      // Fix the length to support some special 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
+      Value |= ((UINT32) -1 << HighBitSet32 (Value));\r
 \r
       //\r
       // Calculate the size of 64bit bar\r
@@ -1548,7 +1730,7 @@ PciIovParseVfBar (
       break;\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Check the length again so as to keep compatible with some special bars\r
   //\r
@@ -1557,7 +1739,7 @@ PciIovParseVfBar (
     PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;\r
     PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;\r
   }\r
-  \r
+\r
   //\r
   // Increment number of bar\r
   //\r
@@ -1584,8 +1766,6 @@ PciParseBar (
   UINT32      Value;\r
   UINT32      OriginalValue;\r
   UINT32      Mask;\r
-  UINT32      Data;\r
-  UINT8       Index;\r
   EFI_STATUS  Status;\r
 \r
   OriginalValue = 0;\r
@@ -1610,6 +1790,7 @@ PciParseBar (
     return Offset + 4;\r
   }\r
 \r
+  PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;\r
   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
   if ((Value & 0x01) != 0) {\r
     //\r
@@ -1635,14 +1816,13 @@ PciParseBar (
 \r
     }\r
     //\r
-    // Workaround. Some platforms inplement IO bar with 0 length\r
+    // Workaround. Some platforms implement 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
@@ -1715,19 +1895,19 @@ PciParseBar (
           // some device implement MMIO bar with 0 length, need to treat it as no-bar\r
           //\r
           PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+          return Offset + 4;\r
         }\r
-        return Offset + 4;\r
       }\r
 \r
       //\r
-      // Fix the length to support some spefic 64 bit BAR\r
+      // Fix the length to support some special 64 bit BAR\r
       //\r
-      Data  = Value;\r
-      Index = 0;\r
-      for (Data = Value; Data != 0; Data >>= 1) {\r
-        Index ++;\r
+      if (Value == 0) {\r
+        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));\r
+        Value = (UINT32) -1;\r
+      } else {\r
+        Value |= ((UINT32)(-1) << HighBitSet32 (Value));\r
       }\r
-      Value |= ((UINT32)(-1) << Index);\r
 \r
       //\r
       // Calculate the size of 64bit bar\r
@@ -1801,7 +1981,7 @@ InitializePciDevice (
   //\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
+  // has not been allocated\r
   //\r
   for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
     PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
@@ -1891,10 +2071,10 @@ InitializeP2C (
 }\r
 \r
 /**\r
-  Create and initiliaze general PCI I/O device instance for\r
+  Create and initialize 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 Bridge            Parent bridge instance.\r
   @param Pci               Input Pci information block.\r
   @param Bus               Device Bus NO.\r
   @param Device            Device device NO.\r
@@ -1905,14 +2085,14 @@ InitializeP2C (
 **/\r
 PCI_IO_DEVICE *\r
 CreatePciIoDevice (\r
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\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
-  PCI_IO_DEVICE *PciIoDevice;\r
+  PCI_IO_DEVICE        *PciIoDevice;\r
   EFI_PCI_IO_PROTOCOL  *PciIo;\r
   EFI_STATUS           Status;\r
 \r
@@ -1923,7 +2103,7 @@ CreatePciIoDevice (
 \r
   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
   PciIoDevice->Handle           = NULL;\r
-  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
+  PciIoDevice->PciRootBridgeIo  = Bridge->PciRootBridgeIo;\r
   PciIoDevice->DevicePath       = NULL;\r
   PciIoDevice->BusNumber        = Bus;\r
   PciIoDevice->DeviceNumber     = Device;\r
@@ -1954,6 +2134,14 @@ CreatePciIoDevice (
   InitializePciLoadFile2 (PciIoDevice);\r
   PciIo = &PciIoDevice->PciIo;\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
   // Detect if PCI Express Device\r
   //\r
@@ -1968,146 +2156,198 @@ CreatePciIoDevice (
     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
+  if (PcdGetBool (PcdAriSupport)) {\r
+    //\r
+    // Check if the device is an ARI device.\r
+    //\r
+    Status = LocatePciExpressCapabilityRegBlock (\r
+               PciIoDevice,\r
+               EFI_PCIE_CAPABILITY_ID_ARI,\r
+               &PciIoDevice->AriCapabilityOffset,\r
+               NULL\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // We need to enable ARI feature before calculate BusReservation,\r
+      // because FirstVFOffset and VFStride may change after that.\r
+      //\r
+      EFI_PCI_IO_PROTOCOL  *ParentPciIo;\r
+      UINT32               Data32;\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
+      // Check if its parent supports ARI forwarding.\r
+      //\r
+      ParentPciIo = &Bridge->PciIo;\r
+      ParentPciIo->Pci.Read (\r
+                          ParentPciIo,\r
+                          EfiPciIoWidthUint32,\r
+                          Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,\r
+                          1,\r
+                          &Data32\r
+                          );\r
+      if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {\r
+        //\r
+        // ARI forward support in bridge, so enable it.\r
+        //\r
+        ParentPciIo->Pci.Read (\r
+                            ParentPciIo,\r
+                            EfiPciIoWidthUint32,\r
+                            Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,\r
+                            1,\r
+                            &Data32\r
+                            );\r
+        if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {\r
+          Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
+          ParentPciIo->Pci.Write (\r
+                              ParentPciIo,\r
+                              EfiPciIoWidthUint32,\r
+                              Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,\r
+                              1,\r
+                              &Data32\r
+                              );\r
+          DEBUG ((\r
+            EFI_D_INFO,\r
+            " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",\r
+            Bridge->BusNumber,\r
+            Bridge->DeviceNumber,\r
+            Bridge->FunctionNumber\r
+            ));\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
+      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));\r
+    }\r
   }\r
 \r
   //\r
-  // Calculate SystemPageSize\r
+  // Initialization for SR-IOV\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
+  if (PcdGetBool (PcdSrIovSupport)) {\r
+    Status = LocatePciExpressCapabilityRegBlock (\r
+               PciIoDevice,\r
+               EFI_PCIE_CAPABILITY_ID_SRIOV,\r
+               &PciIoDevice->SrIovCapabilityOffset,\r
+               NULL\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      UINT32    SupportedPageSize;\r
+      UINT16    VFStride;\r
+      UINT16    FirstVFOffset;\r
+      UINT16    Data16;\r
+      UINT32    PFRid;\r
+      UINT32    LastVF;\r
 \r
-    PciIoDevice->SystemPageSize = (FixedPcdGet32(PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
-    ASSERT (PciIoDevice->SystemPageSize != 0);\r
+      //\r
+      // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.\r
+      //\r
+      if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {\r
+        PciIo->Pci.Read (\r
+                     PciIo,\r
+                     EfiPciIoWidthUint16,\r
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,\r
+                     1,\r
+                     &Data16\r
+                     );\r
+        Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
+        PciIo->Pci.Write (\r
+                     PciIo,\r
+                     EfiPciIoWidthUint16,\r
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,\r
+                     1,\r
+                     &Data16\r
+                     );\r
+      }\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 SystemPageSize\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
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint32,\r
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
+                   1,\r
+                   &SupportedPageSize\r
+                   );\r
+      PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);\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
+      //\r
+      // Adjust SystemPageSize for Alignment usage later\r
+      //\r
+      PciIoDevice->SystemPageSize <<= 12;\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
+      // Calculate BusReservation for PCI IOV\r
+      //\r
 \r
-    //\r
-    // Calculate LastVF\r
-    //\r
-    PFRid = EFI_PCI_RID(Bus, Device, Func);\r
-    LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\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
+      PciIo->Pci.Read (\r
+                   PciIo,\r
+                   EfiPciIoWidthUint16,\r
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
+                   1,\r
+                   &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
+      //\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
+      // Calculate ReservedBusNum for this PF\r
+      //\r
+      PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
+\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",\r
+        SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset\r
+        ));\r
+      DEBUG ((\r
+        EFI_D_INFO,\r
+        "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",\r
+        PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset\r
+        ));\r
+    }\r
   }\r
 \r
+  if (PcdGetBool (PcdMrIovSupport)) {\r
+    Status = LocatePciExpressCapabilityRegBlock (\r
+               PciIoDevice,\r
+               EFI_PCIE_CAPABILITY_ID_MRIOV,\r
+               &PciIoDevice->MrIovCapabilityOffset,\r
+               NULL\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));\r
+    }\r
+  }\r
 \r
   //\r
   // Initialize the reserved resource list\r
@@ -2197,7 +2437,7 @@ PciEnumeratorLight (
     }\r
 \r
     //\r
-    // Record the root bridgeio protocol\r
+    // Record the root bridge-io protocol\r
     //\r
     RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
 \r
@@ -2230,7 +2470,7 @@ PciEnumeratorLight (
     } else {\r
 \r
       //\r
-      // If unsuccessly, destroy the entire node\r
+      // If unsuccessfully, destroy the entire node\r
       //\r
       DestroyRootBridge (RootBridgeDev);\r
     }\r
@@ -2482,6 +2722,13 @@ ResetAllPpbBusNumber (
                  Func\r
                  );\r
 \r
+      if (EFI_ERROR (Status) && Func == 0) {\r
+        //\r
+        // go to next device if there is no Function 0\r
+        //\r
+        break;\r
+      }\r
+\r
       if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
 \r
         Register  = 0;\r