);\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] 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 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
+\r
+/**\r
+ Utility function to free root bridge instances array from\r
+ PciHostBridgeUtilityGetRootBridges().\r
+\r
+ @param[in] Bridges The root bridge instances array.\r
+ @param[in] Count The count of the array.\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHostBridgeUtilityFreeRootBridges (\r
+ IN PCI_ROOT_BRIDGE *Bridges,\r
+ IN UINTN Count\r
+ );\r
+\r
+\r
/**\r
Utility function to inform the platform that the resource conflict happens.\r
\r
**/\r
#include <PiDxe.h>\r
\r
-#include <IndustryStandard/Pci.h>\r
-#include <IndustryStandard/Q35MchIch9.h>\r
-\r
#include <Protocol/PciHostBridgeResourceAllocation.h>\r
#include <Protocol/PciRootBridgeIo.h>\r
\r
#include <Library/PcdLib.h>\r
#include <Library/PciHostBridgeLib.h>\r
#include <Library/PciHostBridgeUtilityLib.h>\r
-#include <Library/PciLib.h>\r
-#include <Library/QemuFwCfgLib.h>\r
#include "PciHostBridge.h"\r
\r
\r
UINTN *Count\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
UINT64 Attributes;\r
UINT64 AllocationAttributes;\r
PCI_ROOT_BRIDGE_APERTURE Io;\r
Mem.Base = PcdGet64 (PcdPciMmio32Base);\r
Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);\r
\r
- *Count = 0;\r
-\r
- //\r
- // QEMU provides the number of extra root buses, shortening the exhaustive\r
- // 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
- ExtraRootBridges = 0;\r
- } else {\r
- QemuFwCfgSelectItem (FwCfgItem);\r
- QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);\r
-\r
- if (ExtraRootBridges > PCI_MAX_BUS) {\r
- DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "\r
- "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));\r
- return NULL;\r
- }\r
- DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",\r
- __FUNCTION__, ExtraRootBridges));\r
- }\r
-\r
- //\r
- // Allocate the "main" root bridge, and any extra root bridges.\r
- //\r
- Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);\r
- if (Bridges == NULL) {\r
- DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
- return NULL;\r
- }\r
- Initialized = 0;\r
-\r
- //\r
- // The "main" root bus is always there.\r
- //\r
- LastRootBridgeNumber = 0;\r
-\r
- //\r
- // Scan all other root buses. If function 0 of any device on a bus returns a\r
- // VendorId register value different from all-bits-one, then that bus is\r
- // alive.\r
- //\r
- for (RootBridgeNumber = 1;\r
- RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;\r
- ++RootBridgeNumber) {\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
- break;\r
- }\r
- }\r
- if (Device <= PCI_MAX_DEVICE) {\r
- //\r
- // Found the next root bus. We can now install the *previous* one,\r
- // because now we know how big a bus number range *that* one has, for any\r
- // subordinate buses that might exist behind PCI bridges hanging off it.\r
- //\r
- Status = PciHostBridgeUtilityInitRootBridge (\r
- Attributes,\r
- Attributes,\r
- AllocationAttributes,\r
- FALSE,\r
- PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,\r
- (UINT8) LastRootBridgeNumber,\r
- (UINT8) (RootBridgeNumber - 1),\r
- &Io,\r
- &Mem,\r
- &MemAbove4G,\r
- &mNonExistAperture,\r
- &mNonExistAperture,\r
- &Bridges[Initialized]\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto FreeBridges;\r
- }\r
- ++Initialized;\r
- LastRootBridgeNumber = RootBridgeNumber;\r
- }\r
- }\r
-\r
- //\r
- // Install the last root bus (which might be the only, ie. main, root bus, if\r
- // we've found no extra root buses).\r
- //\r
- Status = PciHostBridgeUtilityInitRootBridge (\r
- Attributes,\r
+ return PciHostBridgeUtilityGetRootBridges (\r
+ Count,\r
Attributes,\r
AllocationAttributes,\r
- FALSE,\r
- PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,\r
- (UINT8) LastRootBridgeNumber,\r
- PCI_MAX_BUS,\r
&Io,\r
&Mem,\r
&MemAbove4G,\r
&mNonExistAperture,\r
- &mNonExistAperture,\r
- &Bridges[Initialized]\r
+ &mNonExistAperture\r
);\r
- if (EFI_ERROR (Status)) {\r
- goto FreeBridges;\r
- }\r
- ++Initialized;\r
-\r
- *Count = Initialized;\r
- return Bridges;\r
-\r
-FreeBridges:\r
- while (Initialized > 0) {\r
- --Initialized;\r
- PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);\r
- }\r
-\r
- FreePool (Bridges);\r
- return NULL;\r
}\r
\r
\r
UINTN Count\r
)\r
{\r
- if (Bridges == NULL && Count == 0) {\r
- return;\r
- }\r
- ASSERT (Bridges != NULL && Count > 0);\r
-\r
- do {\r
- --Count;\r
- PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);\r
- } while (Count > 0);\r
-\r
- FreePool (Bridges);\r
+ PciHostBridgeUtilityFreeRootBridges (Bridges, Count);\r
}\r
\r
\r
PcdLib\r
PciHostBridgeUtilityLib\r
PciLib\r
- QemuFwCfgLib\r
\r
[Pcd]\r
gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase\r
**/\r
\r
#include <IndustryStandard/Acpi10.h>\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Q35MchIch9.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
#include <Library/PciHostBridgeUtilityLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
\r
\r
#pragma pack(1)\r
}\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] 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 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
+ //\r
+ // QEMU provides the number of extra root buses, shortening the exhaustive\r
+ // 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
+ ExtraRootBridges = 0;\r
+ } else {\r
+ QemuFwCfgSelectItem (FwCfgItem);\r
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);\r
+\r
+ if (ExtraRootBridges > PCI_MAX_BUS) {\r
+ DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "\r
+ "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));\r
+ return NULL;\r
+ }\r
+ DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",\r
+ __FUNCTION__, ExtraRootBridges));\r
+ }\r
+\r
+ //\r
+ // Allocate the "main" root bridge, and any extra root bridges.\r
+ //\r
+ Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);\r
+ if (Bridges == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
+ return NULL;\r
+ }\r
+ Initialized = 0;\r
+\r
+ //\r
+ // The "main" root bus is always there.\r
+ //\r
+ LastRootBridgeNumber = 0;\r
+\r
+ //\r
+ // Scan all other root buses. If function 0 of any device on a bus returns a\r
+ // VendorId register value different from all-bits-one, then that bus is\r
+ // alive.\r
+ //\r
+ for (RootBridgeNumber = 1;\r
+ RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;\r
+ ++RootBridgeNumber) {\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
+ break;\r
+ }\r
+ }\r
+ if (Device <= PCI_MAX_DEVICE) {\r
+ //\r
+ // Found the next root bus. We can now install the *previous* one,\r
+ // because now we know how big a bus number range *that* one has, for any\r
+ // subordinate buses that might exist behind PCI bridges hanging off it.\r
+ //\r
+ Status = PciHostBridgeUtilityInitRootBridge (\r
+ Attributes,\r
+ Attributes,\r
+ AllocationAttributes,\r
+ FALSE,\r
+ PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,\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
+ ++Initialized;\r
+ LastRootBridgeNumber = RootBridgeNumber;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Install the last root bus (which might be the only, ie. main, root bus, if\r
+ // we've found no extra root buses).\r
+ //\r
+ Status = PciHostBridgeUtilityInitRootBridge (\r
+ Attributes,\r
+ Attributes,\r
+ AllocationAttributes,\r
+ FALSE,\r
+ PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,\r
+ (UINT8) LastRootBridgeNumber,\r
+ PCI_MAX_BUS,\r
+ Io,\r
+ Mem,\r
+ MemAbove4G,\r
+ PMem,\r
+ PMemAbove4G,\r
+ &Bridges[Initialized]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeBridges;\r
+ }\r
+ ++Initialized;\r
+\r
+ *Count = Initialized;\r
+ return Bridges;\r
+\r
+FreeBridges:\r
+ while (Initialized > 0) {\r
+ --Initialized;\r
+ PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);\r
+ }\r
+\r
+ FreePool (Bridges);\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Utility function to free root bridge instances array from\r
+ PciHostBridgeUtilityGetRootBridges().\r
+\r
+ @param[in] Bridges The root bridge instances array.\r
+ @param[in] Count The count of the array.\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHostBridgeUtilityFreeRootBridges (\r
+ IN PCI_ROOT_BRIDGE *Bridges,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ if (Bridges == NULL && Count == 0) {\r
+ return;\r
+ }\r
+ ASSERT (Bridges != NULL && Count > 0);\r
+\r
+ do {\r
+ --Count;\r
+ PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);\r
+ } while (Count > 0);\r
+\r
+ FreePool (Bridges);\r
+}\r
+\r
+\r
/**\r
Utility function to inform the platform that the resource conflict happens.\r
\r
DebugLib\r
DevicePathLib\r
MemoryAllocationLib\r
+ PcdLib\r
+ PciLib\r
+ QemuFwCfgLib\r
+\r
+[Pcd]\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId\r