]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c
OvmfPkg/PciHostBridgeUtilityLib: Initialize RootBridges apertures with spec
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeUtilityLib / PciHostBridgeUtilityLib.c
index d2296f33085ee178d3a1f5c75f0c65d4ab6b298d..cad2bd6c9687730c7225d22ced19659b224a1276 100644 (file)
 \r
 #include <IndustryStandard/Acpi10.h>\r
 #include <IndustryStandard/Pci.h>\r
+#include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/DevicePathLib.h>\r
+#include <Library/HardwareInfoLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/PciHostBridgeUtilityLib.h>\r
 #include <Library/PciLib.h>\r
 #include <Library/QemuFwCfgLib.h>\r
-\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
 \r
 #pragma pack(1)\r
 typedef struct {\r
-  ACPI_HID_DEVICE_PATH     AcpiDevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
+  ACPI_HID_DEVICE_PATH        AcpiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL    EndDevicePath;\r
 } OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
 #pragma pack ()\r
 \r
-\r
 GLOBAL_REMOVE_IF_UNREFERENCED\r
-CHAR16 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {\r
+CHAR16  *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {\r
   L"Mem", L"I/O", L"Bus"\r
 };\r
 \r
-\r
 STATIC\r
 CONST\r
-OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {\r
+OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH  mRootBridgeDevicePathTemplate = {\r
   {\r
     {\r
       ACPI_DEVICE_PATH,\r
       ACPI_DP,\r
       {\r
-        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),\r
-        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)\r
+        (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),\r
+        (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
       }\r
     },\r
-    EISA_PNP_ID(0x0A03), // HID\r
-    0                    // UID\r
+    EISA_PNP_ID (0x0A03), // HID\r
+    0                     // UID\r
   },\r
 \r
   {\r
@@ -61,7 +61,6 @@ OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
   }\r
 };\r
 \r
-\r
 /**\r
   Utility function to initialize a PCI_ROOT_BRIDGE structure.\r
 \r
@@ -112,22 +111,22 @@ OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
 EFI_STATUS\r
 EFIAPI\r
 PciHostBridgeUtilityInitRootBridge (\r
-  IN  UINT64                   Supports,\r
-  IN  UINT64                   Attributes,\r
-  IN  UINT64                   AllocAttributes,\r
-  IN  BOOLEAN                  DmaAbove4G,\r
-  IN  BOOLEAN                  NoExtendedConfigSpace,\r
-  IN  UINT8                    RootBusNumber,\r
-  IN  UINT8                    MaxSubBusNumber,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *Io,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *Mem,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *PMem,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,\r
-  OUT PCI_ROOT_BRIDGE          *RootBus\r
+  IN  UINT64                    Supports,\r
+  IN  UINT64                    Attributes,\r
+  IN  UINT64                    AllocAttributes,\r
+  IN  BOOLEAN                   DmaAbove4G,\r
+  IN  BOOLEAN                   NoExtendedConfigSpace,\r
+  IN  UINT8                     RootBusNumber,\r
+  IN  UINT8                     MaxSubBusNumber,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Io,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Mem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *MemAbove4G,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMemAbove4G,\r
+  OUT PCI_ROOT_BRIDGE           *RootBus\r
   )\r
 {\r
-  OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;\r
+  OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH  *DevicePath;\r
 \r
   //\r
   // Be safe if other fields are added to PCI_ROOT_BRIDGE later.\r
@@ -142,8 +141,8 @@ PciHostBridgeUtilityInitRootBridge (
   RootBus->DmaAbove4G = DmaAbove4G;\r
 \r
   RootBus->AllocationAttributes = AllocAttributes;\r
-  RootBus->Bus.Base  = RootBusNumber;\r
-  RootBus->Bus.Limit = MaxSubBusNumber;\r
+  RootBus->Bus.Base             = RootBusNumber;\r
+  RootBus->Bus.Limit            = MaxSubBusNumber;\r
   CopyMem (&RootBus->Io, Io, sizeof (*Io));\r
   CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));\r
   CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));\r
@@ -152,22 +151,28 @@ PciHostBridgeUtilityInitRootBridge (
 \r
   RootBus->NoExtendedConfigSpace = NoExtendedConfigSpace;\r
 \r
-  DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,\r
-                 &mRootBridgeDevicePathTemplate);\r
+  DevicePath = AllocateCopyPool (\r
+                 sizeof mRootBridgeDevicePathTemplate,\r
+                 &mRootBridgeDevicePathTemplate\r
+                 );\r
   if (DevicePath == NULL) {\r
     DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   DevicePath->AcpiDevicePath.UID = RootBusNumber;\r
-  RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
+  RootBus->DevicePath            = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
 \r
-  DEBUG ((DEBUG_INFO,\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
     "%a: populated root bus %d, with room for %d subordinate bus(es)\n",\r
-    __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));\r
+    __FUNCTION__,\r
+    RootBusNumber,\r
+    MaxSubBusNumber - RootBusNumber\r
+    ));\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with\r
   PciHostBridgeUtilityInitRootBridge().\r
@@ -180,15 +185,16 @@ PciHostBridgeUtilityInitRootBridge (
 VOID\r
 EFIAPI\r
 PciHostBridgeUtilityUninitRootBridge (\r
-  IN PCI_ROOT_BRIDGE *RootBus\r
+  IN PCI_ROOT_BRIDGE  *RootBus\r
   )\r
 {\r
   FreePool (RootBus->DevicePath);\r
 }\r
 \r
-\r
 /**\r
-  Utility function to return all the root bridge instances in an array.\r
+  Utility function to scan PCI root bridges and create instances for those\r
+  that are found not empty. Populate their resources from the default\r
+  provided parameters and return all the root bridge instances in an array.\r
 \r
   @param[out] Count                  The number of root bridge instances.\r
 \r
@@ -216,37 +222,41 @@ PciHostBridgeUtilityUninitRootBridge (
 \r
   @return                            All the root bridge instances in an array.\r
 **/\r
+STATIC\r
 PCI_ROOT_BRIDGE *\r
-EFIAPI\r
-PciHostBridgeUtilityGetRootBridges (\r
-  OUT UINTN                    *Count,\r
-  IN  UINT64                   Attributes,\r
-  IN  UINT64                   AllocationAttributes,\r
-  IN  BOOLEAN                  DmaAbove4G,\r
-  IN  BOOLEAN                  NoExtendedConfigSpace,\r
-  IN  UINTN                    BusMin,\r
-  IN  UINTN                    BusMax,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *Io,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *Mem,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *PMem,\r
-  IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G\r
+PciHostBridgeUtilityGetRootBridgesBusScan (\r
+  OUT UINTN                     *Count,\r
+  IN  UINT64                    Attributes,\r
+  IN  UINT64                    AllocationAttributes,\r
+  IN  BOOLEAN                   DmaAbove4G,\r
+  IN  BOOLEAN                   NoExtendedConfigSpace,\r
+  IN  UINTN                     BusMin,\r
+  IN  UINTN                     BusMax,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Io,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Mem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *MemAbove4G,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMemAbove4G\r
   )\r
 {\r
-  EFI_STATUS           Status;\r
-  FIRMWARE_CONFIG_ITEM FwCfgItem;\r
-  UINTN                FwCfgSize;\r
-  UINT64               ExtraRootBridges;\r
-  PCI_ROOT_BRIDGE      *Bridges;\r
-  UINTN                Initialized;\r
-  UINTN                LastRootBridgeNumber;\r
-  UINTN                RootBridgeNumber;\r
-\r
-  *Count = 0;\r
-\r
-  if (BusMin > BusMax || BusMax > PCI_MAX_BUS) {\r
-    DEBUG ((DEBUG_ERROR, "%a: invalid bus range with BusMin %Lu and BusMax "\r
-      "%Lu\n", __FUNCTION__, (UINT64)BusMin, (UINT64)BusMax));\r
+  EFI_STATUS            Status;\r
+  FIRMWARE_CONFIG_ITEM  FwCfgItem;\r
+  UINTN                 FwCfgSize;\r
+  UINT64                ExtraRootBridges;\r
+  PCI_ROOT_BRIDGE       *Bridges;\r
+  UINTN                 Initialized;\r
+  UINTN                 LastRootBridgeNumber;\r
+  UINTN                 RootBridgeNumber;\r
+\r
+  if ((BusMin > BusMax) || (BusMax > PCI_MAX_BUS)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: invalid bus range with BusMin %Lu and BusMax "\r
+      "%Lu\n",\r
+      __FUNCTION__,\r
+      (UINT64)BusMin,\r
+      (UINT64)BusMax\r
+      ));\r
     return NULL;\r
   }\r
 \r
@@ -255,7 +265,7 @@ PciHostBridgeUtilityGetRootBridges (
   // search below. If there is no hint, the feature is missing.\r
   //\r
   Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);\r
-  if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) {\r
+  if (EFI_ERROR (Status) || (FwCfgSize != sizeof ExtraRootBridges)) {\r
     ExtraRootBridges = 0;\r
   } else {\r
     QemuFwCfgSelectItem (FwCfgItem);\r
@@ -269,12 +279,22 @@ PciHostBridgeUtilityGetRootBridges (
     // invalid behavior.\r
     //\r
     if (ExtraRootBridges > BusMax - BusMin) {\r
-      DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "\r
-        "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: invalid count of extra root buses (%Lu) "\r
+        "reported by QEMU\n",\r
+        __FUNCTION__,\r
+        ExtraRootBridges\r
+        ));\r
       return NULL;\r
     }\r
-    DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",\r
-      __FUNCTION__, ExtraRootBridges));\r
+\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: %Lu extra root buses reported by QEMU\n",\r
+      __FUNCTION__,\r
+      ExtraRootBridges\r
+      ));\r
   }\r
 \r
   //\r
@@ -285,6 +305,7 @@ PciHostBridgeUtilityGetRootBridges (
     DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
     return NULL;\r
   }\r
+\r
   Initialized = 0;\r
 \r
   //\r
@@ -299,15 +320,24 @@ PciHostBridgeUtilityGetRootBridges (
   //\r
   for (RootBridgeNumber = BusMin + 1;\r
        RootBridgeNumber <= BusMax && Initialized < ExtraRootBridges;\r
-       ++RootBridgeNumber) {\r
-    UINTN Device;\r
+       ++RootBridgeNumber)\r
+  {\r
+    UINTN  Device;\r
 \r
     for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {\r
-      if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,\r
-                       PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {\r
+      if (PciRead16 (\r
+            PCI_LIB_ADDRESS (\r
+              RootBridgeNumber,\r
+              Device,\r
+              0,\r
+              PCI_VENDOR_ID_OFFSET\r
+              )\r
+            ) != MAX_UINT16)\r
+      {\r
         break;\r
       }\r
     }\r
+\r
     if (Device <= PCI_MAX_DEVICE) {\r
       //\r
       // Found the next root bus. We can now install the *previous* one,\r
@@ -315,23 +345,24 @@ PciHostBridgeUtilityGetRootBridges (
       // subordinate buses that might exist behind PCI bridges hanging off it.\r
       //\r
       Status = PciHostBridgeUtilityInitRootBridge (\r
-        Attributes,\r
-        Attributes,\r
-        AllocationAttributes,\r
-        DmaAbove4G,\r
-        NoExtendedConfigSpace,\r
-        (UINT8) LastRootBridgeNumber,\r
-        (UINT8) (RootBridgeNumber - 1),\r
-        Io,\r
-        Mem,\r
-        MemAbove4G,\r
-        PMem,\r
-        PMemAbove4G,\r
-        &Bridges[Initialized]\r
-        );\r
+                 Attributes,\r
+                 Attributes,\r
+                 AllocationAttributes,\r
+                 DmaAbove4G,\r
+                 NoExtendedConfigSpace,\r
+                 (UINT8)LastRootBridgeNumber,\r
+                 (UINT8)(RootBridgeNumber - 1),\r
+                 Io,\r
+                 Mem,\r
+                 MemAbove4G,\r
+                 PMem,\r
+                 PMemAbove4G,\r
+                 &Bridges[Initialized]\r
+                 );\r
       if (EFI_ERROR (Status)) {\r
         goto FreeBridges;\r
       }\r
+\r
       ++Initialized;\r
       LastRootBridgeNumber = RootBridgeNumber;\r
     }\r
@@ -342,23 +373,24 @@ PciHostBridgeUtilityGetRootBridges (
   // we've found no extra root buses).\r
   //\r
   Status = PciHostBridgeUtilityInitRootBridge (\r
-    Attributes,\r
-    Attributes,\r
-    AllocationAttributes,\r
-    DmaAbove4G,\r
-    NoExtendedConfigSpace,\r
-    (UINT8) LastRootBridgeNumber,\r
-    (UINT8) BusMax,\r
-    Io,\r
-    Mem,\r
-    MemAbove4G,\r
-    PMem,\r
-    PMemAbove4G,\r
-    &Bridges[Initialized]\r
-    );\r
+             Attributes,\r
+             Attributes,\r
+             AllocationAttributes,\r
+             DmaAbove4G,\r
+             NoExtendedConfigSpace,\r
+             (UINT8)LastRootBridgeNumber,\r
+             (UINT8)BusMax,\r
+             Io,\r
+             Mem,\r
+             MemAbove4G,\r
+             PMem,\r
+             PMemAbove4G,\r
+             &Bridges[Initialized]\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     goto FreeBridges;\r
   }\r
+\r
   ++Initialized;\r
 \r
   *Count = Initialized;\r
@@ -374,6 +406,324 @@ FreeBridges:
   return NULL;\r
 }\r
 \r
+/**\r
+  Utility function to read root bridges information from host-provided fw-cfg\r
+  file and return them in an array.\r
+\r
+  @param[out] Count   The number of root bridge instances.\r
+\r
+  @return             All the root bridge instances in an array parsed from\r
+                      host-provided fw-cfg file (hardware-info).\r
+**/\r
+STATIC\r
+PCI_ROOT_BRIDGE *\r
+PciHostBridgeUtilityGetRootBridgesHostProvided (\r
+  OUT UINTN  *Count\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  FIRMWARE_CONFIG_ITEM      FwCfgItem;\r
+  UINTN                     FwCfgSize;\r
+  PCI_ROOT_BRIDGE           *Bridges;\r
+  UINTN                     Initialized;\r
+  UINTN                     LastRootBridgeNumber;\r
+  UINTN                     RootBridgeNumber;\r
+  UINTN                     PciHostBridgeCount;\r
+  UINT8                     *HardwareInfoBlob;\r
+  LIST_ENTRY                HwInfoList;\r
+  LIST_ENTRY                *HwLink;\r
+  HARDWARE_INFO             *HwInfo;\r
+  UINT64                    Attributes;\r
+  UINT64                    AllocationAttributes;\r
+  BOOLEAN                   DmaAbove4G;\r
+  BOOLEAN                   NoExtendedConfigSpace;\r
+  BOOLEAN                   CombineMemPMem;\r
+  PCI_ROOT_BRIDGE_APERTURE  Io;\r
+  PCI_ROOT_BRIDGE_APERTURE  Mem;\r
+  PCI_ROOT_BRIDGE_APERTURE  MemAbove4G;\r
+  PCI_ROOT_BRIDGE_APERTURE  PMem;\r
+  PCI_ROOT_BRIDGE_APERTURE  PMemAbove4G;\r
+\r
+  //\r
+  // Initialize the Hardware Info list head to start with an empty but valid\r
+  // list head.\r
+  //\r
+  InitializeListHead (&HwInfoList);\r
+  HardwareInfoBlob   =  NULL;\r
+  Initialized        = 0;\r
+  Bridges            = NULL;\r
+  PciHostBridgeCount = 0;\r
+\r
+  //\r
+  // Hypervisor can provide the specifications (resources) for one or more\r
+  // PCI host bridges. Such information comes through fw-cfg as part of\r
+  // the hardware-info file.\r
+  //\r
+  Status = QemuFwCfgFindFile ("etc/hardware-info", &FwCfgItem, &FwCfgSize);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  HardwareInfoBlob = AllocatePool (FwCfgSize);\r
+\r
+  if (HardwareInfoBlob == NULL) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: Failed to allocate memory for hardware resources info\n",\r
+      __FUNCTION__\r
+      ));\r
+    return NULL;\r
+  }\r
+\r
+  QemuFwCfgSelectItem (FwCfgItem);\r
+  QemuFwCfgReadBytes (FwCfgSize, HardwareInfoBlob);\r
+\r
+  //\r
+  // Create the list of hardware info devices filtering for PCI host\r
+  // bridges\r
+  //\r
+  Status = CreateHardwareInfoList (\r
+             HardwareInfoBlob,\r
+             FwCfgSize,\r
+             HardwareInfoTypeHostBridge,\r
+             &HwInfoList\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: Failed to create hardware info list to retrieve host "\r
+      "bridges information from fw-cfg\n",\r
+      __FUNCTION__\r
+      ));\r
+\r
+    goto FreeBridges;\r
+  }\r
+\r
+  PciHostBridgeCount = GetHardwareInfoCountByType (\r
+                         &HwInfoList,\r
+                         HardwareInfoTypeHostBridge,\r
+                         sizeof (HOST_BRIDGE_INFO)\r
+                         );\r
+\r
+  if (PciHostBridgeCount == 0) {\r
+    goto FreeBridges;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: Host provided description for %Lu root bridges\n",\r
+    __FUNCTION__,\r
+    PciHostBridgeCount\r
+    ));\r
+\r
+  //\r
+  // Allocate the root bridges\r
+  //\r
+  Bridges = AllocatePool (((UINTN)PciHostBridgeCount) * sizeof *Bridges);\r
+  if (Bridges == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
+    goto FreeBridges;\r
+  }\r
+\r
+  //\r
+  // If Host Bridges' specification was obtained from fw-cfg, the list\r
+  // contains information to populate all root bridges in the system\r
+  // including resources and attributes.\r
+  //\r
+  HwLink = GetFirstHardwareInfoByType (\r
+             &HwInfoList,\r
+             HardwareInfoTypeHostBridge,\r
+             sizeof (HOST_BRIDGE_INFO)\r
+             );\r
+\r
+  while (!EndOfHardwareInfoList (&HwInfoList, HwLink)) {\r
+    HwInfo = HARDWARE_INFO_FROM_LINK (HwLink);\r
+\r
+    Status = HardwareInfoPciHostBridgeGet (\r
+               HwInfo->Data.PciHostBridge,\r
+               (UINTN)HwInfo->Header.Size,\r
+               &RootBridgeNumber,\r
+               &LastRootBridgeNumber,\r
+               &Attributes,\r
+               &DmaAbove4G,\r
+               &NoExtendedConfigSpace,\r
+               &CombineMemPMem,\r
+               &Io,\r
+               &Mem,\r
+               &MemAbove4G,\r
+               &PMem,\r
+               &PMemAbove4G,\r
+               NULL\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto FreeBridges;\r
+    }\r
+\r
+    if ((RootBridgeNumber > LastRootBridgeNumber) || (LastRootBridgeNumber > PCI_MAX_BUS)) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: invalid bus range with BusMin %Lu and BusMax "\r
+        "%Lu\n",\r
+        __FUNCTION__,\r
+        (UINT64)RootBridgeNumber,\r
+        (UINT64)LastRootBridgeNumber\r
+        ));\r
+      goto FreeBridges;\r
+    }\r
+\r
+    AllocationAttributes = 0;\r
+    if (CombineMemPMem) {\r
+      AllocationAttributes |= EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;\r
+    }\r
+\r
+    if ((MemAbove4G.Limit > MemAbove4G.Base) ||\r
+        (PMemAbove4G.Limit > PMemAbove4G.Base))\r
+    {\r
+      AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;\r
+    }\r
+\r
+    Status = PciHostBridgeUtilityInitRootBridge (\r
+               Attributes,\r
+               Attributes,\r
+               AllocationAttributes,\r
+               DmaAbove4G,\r
+               NoExtendedConfigSpace,\r
+               (UINT8)RootBridgeNumber,\r
+               (UINT8)LastRootBridgeNumber,\r
+               &Io,\r
+               &Mem,\r
+               &MemAbove4G,\r
+               &PMem,\r
+               &PMemAbove4G,\r
+               &Bridges[Initialized]\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto FreeBridges;\r
+    }\r
+\r
+    ++Initialized;\r
+\r
+    HwLink = GetNextHardwareInfoByType (\r
+               &HwInfoList,\r
+               HwLink,\r
+               HardwareInfoTypeHostBridge,\r
+               sizeof (HOST_BRIDGE_INFO)\r
+               );\r
+  }\r
+\r
+  *Count = Initialized;\r
+\r
+  //\r
+  // If resources were allocated for host bridges info, release them\r
+  //\r
+  if (HardwareInfoBlob) {\r
+    FreePool (HardwareInfoBlob);\r
+  }\r
+\r
+  FreeHardwareInfoList (&HwInfoList);\r
+  return Bridges;\r
+\r
+FreeBridges:\r
+  while (Initialized > 0) {\r
+    --Initialized;\r
+    PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);\r
+  }\r
+\r
+  if (Bridges) {\r
+    FreePool (Bridges);\r
+  }\r
+\r
+  if (HardwareInfoBlob) {\r
+    FreePool (HardwareInfoBlob);\r
+  }\r
+\r
+  FreeHardwareInfoList (&HwInfoList);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Utility function to return all the root bridge instances in an array.\r
+\r
+  @param[out] Count                  The number of root bridge instances.\r
+\r
+  @param[in]  Attributes             Initial attributes.\r
+\r
+  @param[in]  AllocAttributes        Allocation attributes.\r
+\r
+  @param[in]  DmaAbove4G             DMA above 4GB memory.\r
+\r
+  @param[in]  NoExtendedConfigSpace  No Extended Config Space.\r
+\r
+  @param[in]  BusMin                 Minimum Bus number, inclusive.\r
+\r
+  @param[in]  BusMax                 Maximum Bus number, inclusive.\r
+\r
+  @param[in]  Io                     IO aperture.\r
+\r
+  @param[in]  Mem                    MMIO aperture.\r
+\r
+  @param[in]  MemAbove4G             MMIO aperture above 4G.\r
+\r
+  @param[in]  PMem                   Prefetchable MMIO aperture.\r
+\r
+  @param[in]  PMemAbove4G            Prefetchable MMIO aperture above 4G.\r
+\r
+  @return                            All the root bridge instances in an array.\r
+**/\r
+PCI_ROOT_BRIDGE *\r
+EFIAPI\r
+PciHostBridgeUtilityGetRootBridges (\r
+  OUT UINTN                     *Count,\r
+  IN  UINT64                    Attributes,\r
+  IN  UINT64                    AllocationAttributes,\r
+  IN  BOOLEAN                   DmaAbove4G,\r
+  IN  BOOLEAN                   NoExtendedConfigSpace,\r
+  IN  UINTN                     BusMin,\r
+  IN  UINTN                     BusMax,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Io,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *Mem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *MemAbove4G,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMem,\r
+  IN  PCI_ROOT_BRIDGE_APERTURE  *PMemAbove4G\r
+  )\r
+{\r
+  PCI_ROOT_BRIDGE  *Bridges;\r
+\r
+  *Count = 0;\r
+\r
+  //\r
+  // First attempt to get the host provided descriptions of the Root Bridges\r
+  // if available.\r
+  //\r
+  Bridges = PciHostBridgeUtilityGetRootBridgesHostProvided (Count);\r
+\r
+  //\r
+  // If host did not provide Root Bridge information, scan the buses and\r
+  // auto populate them with default resources.\r
+  //\r
+  if (Bridges == NULL) {\r
+    Bridges = PciHostBridgeUtilityGetRootBridgesBusScan (\r
+                Count,\r
+                Attributes,\r
+                AllocationAttributes,\r
+                DmaAbove4G,\r
+                NoExtendedConfigSpace,\r
+                BusMin,\r
+                BusMax,\r
+                Io,\r
+                Mem,\r
+                MemAbove4G,\r
+                PMem,\r
+                PMemAbove4G\r
+                );\r
+  }\r
+\r
+  return Bridges;\r
+}\r
 \r
 /**\r
   Utility function to free root bridge instances array from\r
@@ -385,13 +735,14 @@ FreeBridges:
 VOID\r
 EFIAPI\r
 PciHostBridgeUtilityFreeRootBridges (\r
-  IN PCI_ROOT_BRIDGE *Bridges,\r
-  IN UINTN           Count\r
+  IN PCI_ROOT_BRIDGE  *Bridges,\r
+  IN UINTN            Count\r
   )\r
 {\r
-  if (Bridges == NULL && Count == 0) {\r
+  if ((Bridges == NULL) && (Count == 0)) {\r
     return;\r
   }\r
+\r
   ASSERT (Bridges != NULL && Count > 0);\r
 \r
   do {\r
@@ -402,7 +753,6 @@ PciHostBridgeUtilityFreeRootBridges (
   FreePool (Bridges);\r
 }\r
 \r
-\r
 /**\r
   Utility function to inform the platform that the resource conflict happens.\r
 \r
@@ -423,38 +773,46 @@ PciHostBridgeUtilityResourceConflict (
   IN VOID  *Configuration\r
   )\r
 {\r
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
-  UINTN                             RootBridgeIndex;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptor;\r
+  UINTN                              RootBridgeIndex;\r
+\r
   DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));\r
 \r
   RootBridgeIndex = 0;\r
-  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+  Descriptor      = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;\r
   while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
     DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));\r
-    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
-      ASSERT (Descriptor->ResType <\r
-              ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)\r
-              );\r
-      DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
-              mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
-              Descriptor->AddrLen, Descriptor->AddrRangeMax\r
-              ));\r
+    for ( ; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+      ASSERT (\r
+        Descriptor->ResType <\r
+        ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)\r
+        );\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
+        mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
+        Descriptor->AddrLen,\r
+        Descriptor->AddrRangeMax\r
+        ));\r
       if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
-        DEBUG ((DEBUG_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",\r
-                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
-                ((Descriptor->SpecificFlag &\r
-                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE\r
-                  ) != 0) ? L" (Prefetchable)" : L""\r
-                ));\r
+        DEBUG ((\r
+          DEBUG_ERROR,\r
+          "     Granularity/SpecificFlag = %ld / %02x%s\n",\r
+          Descriptor->AddrSpaceGranularity,\r
+          Descriptor->SpecificFlag,\r
+          ((Descriptor->SpecificFlag &\r
+            EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE\r
+            ) != 0) ? L" (Prefetchable)" : L""\r
+          ));\r
       }\r
     }\r
+\r
     //\r
     // Skip the END descriptor for root bridge\r
     //\r
     ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);\r
     Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(\r
-                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1\r
-                   );\r
+                                                       (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1\r
+                                                       );\r
   }\r
 }\r
-\r