]> 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 620933779c458c95fb47e41cf6e80d4ef9f749fa..c7eafff5935545cfafb9b55ad8a7e744b131ce24 100644 (file)
@@ -1,14 +1,9 @@
 /** @file\r
   PCI emumeration support functions implementation for PCI Bus module.\r
 \r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 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
@@ -16,6 +11,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \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
@@ -82,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
@@ -119,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
@@ -155,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
@@ -186,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
@@ -315,6 +331,81 @@ 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
@@ -334,7 +425,7 @@ DumpPciBars (
 \r
     DEBUG ((\r
       EFI_D_INFO,\r
-      "   BAR[%d]: Type = %s; Alignment = 0x%x;\tLength = 0x%x;\tOffset = 0x%02x\n",\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
@@ -347,7 +438,7 @@ DumpPciBars (
 \r
     DEBUG ((\r
       EFI_D_INFO,\r
-      " VFBAR[%d]: Type = %s; Alignment = 0x%x;\tLength = 0x%x;\tOffset = 0x%02x\n",\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
@@ -392,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
@@ -459,6 +542,9 @@ GatherPpbInfo (
   UINT8                           Value;\r
   EFI_PCI_IO_PROTOCOL             *PciIo;\r
   UINT8                           Temp;\r
+  UINT32                          PMemBaseLimit;\r
+  UINT16                          PrefetchableMemoryBase;\r
+  UINT16                          PrefetchableMemoryLimit;\r
 \r
   PciIoDevice = CreatePciIoDevice (\r
                   Bridge,\r
@@ -472,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
@@ -520,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
@@ -552,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
@@ -582,7 +668,10 @@ GatherPpbInfo (
 \r
   GetResourcePaddingPpb (PciIoDevice);\r
 \r
-  DEBUG_CODE (DumpPciBars (PciIoDevice););\r
+  DEBUG_CODE (\r
+    DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);\r
+    DumpPciBars (PciIoDevice);\r
+  );\r
 \r
   return PciIoDevice;\r
 }\r
@@ -623,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
@@ -659,7 +740,7 @@ GatherP2CInfo (
 }\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
@@ -835,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
@@ -960,17 +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 (IS_PCI_LPC (&PciIoDevice->Pci)) {\r
         Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
-        Attributes |= (mReserveIsaAliases ? EFI_PCI_IO_ATTRIBUTE_ISA_IO : \\r
-                                            EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);\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
@@ -996,8 +1077,8 @@ PciSetDeviceAttribute (
 \r
       if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
         Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
-        Attributes |= (mReserveVgaAliases ? EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
-                                            EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
+        Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
+                                            (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
       }\r
     }\r
 \r
@@ -1118,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
@@ -1130,8 +1211,12 @@ DetermineDeviceAttribute (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-    PciIoDevice->Supports |= (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
-                              EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM);\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
@@ -1163,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
@@ -1189,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
@@ -1250,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
@@ -1258,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
@@ -1266,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
@@ -1274,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
@@ -1304,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
@@ -1330,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
@@ -1354,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
@@ -1370,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
@@ -1388,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
@@ -1415,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
@@ -1458,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
@@ -1575,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
@@ -1621,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
@@ -1630,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
@@ -1657,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
@@ -1683,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
@@ -1708,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
@@ -1788,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
@@ -1874,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
@@ -1964,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
@@ -2027,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
@@ -2064,7 +2179,7 @@ CreatePciIoDevice (
       //\r
       ParentPciIo = &Bridge->PciIo;\r
       ParentPciIo->Pci.Read (\r
-                          ParentPciIo, \r
+                          ParentPciIo,\r
                           EfiPciIoWidthUint32,\r
                           Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,\r
                           1,\r
@@ -2322,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
@@ -2355,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
@@ -2607,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