\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
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
}\r
};\r
\r
-\r
/**\r
Utility function to initialize a PCI_ROOT_BRIDGE structure.\r
\r
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
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
\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
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
\r
- @param[out] Count The number of root bridge instances.\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] Attributes Initial attributes.\r
+ @param[in] BusMin Minimum Bus number, inclusive.\r
\r
- @param[in] AllocAttributes Allocation attributes.\r
+ @param[in] BusMax Maximum Bus number, inclusive.\r
\r
- @param[in] Io IO aperture.\r
+ @param[in] Io IO aperture.\r
\r
- @param[in] Mem MMIO aperture.\r
+ @param[in] Mem MMIO aperture.\r
\r
- @param[in] MemAbove4G MMIO aperture above 4G.\r
+ @param[in] MemAbove4G MMIO aperture above 4G.\r
\r
- @param[in] PMem Prefetchable MMIO aperture.\r
+ @param[in] PMem Prefetchable MMIO aperture.\r
\r
- @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
\r
- @return All the root bridge instances in an array.\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
+ 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
+ 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 ((\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
//\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
+ 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
+ //\r
+ // Validate the number of extra root bridges. As BusMax is inclusive, the\r
+ // max bus count is (BusMax - BusMin + 1). From that, the "main" root bus\r
+ // is always a given, so the max count for the "extra" root bridges is one\r
+ // less, i.e. (BusMax - BusMin). If the QEMU hint exceeds that, we have\r
+ // invalid behavior.\r
+ //\r
+ if (ExtraRootBridges > BusMax - BusMin) {\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
DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
return NULL;\r
}\r
+\r
Initialized = 0;\r
\r
//\r
// The "main" root bus is always there.\r
//\r
- LastRootBridgeNumber = 0;\r
+ LastRootBridgeNumber = BusMin;\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
+ for (RootBridgeNumber = BusMin + 1;\r
+ RootBridgeNumber <= BusMax && Initialized < ExtraRootBridges;\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
// 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
+ 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
// 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
+ 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
return NULL;\r
}\r
\r
-\r
/**\r
Utility function to free root bridge instances array from\r
PciHostBridgeUtilityGetRootBridges().\r
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
FreePool (Bridges);\r
}\r
\r
-\r
/**\r
Utility function to inform the platform that the resource conflict happens.\r
\r
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