Copyright (C) 2016, Red Hat, Inc.\r
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-#include <PiDxe.h>\r
-\r
-#include <IndustryStandard/Pci.h>\r
-\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/PciHostBridgeLib.h>\r
-#include <Library/PciLib.h>\r
-#include <Library/QemuFwCfgLib.h>\r
-\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED\r
-CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {\r
- L"Mem", L"I/O", L"Bus"\r
-};\r
-\r
-\r
-/**\r
- Initialize a PCI_ROOT_BRIDGE structure.\r
-\r
- param[in] RootBusNumber The bus number to store in RootBus.\r
-\r
- param[in] MaxSubBusNumber The inclusive maximum bus number that can be\r
- assigned to any subordinate bus found behind any\r
- PCI bridge hanging off this root bus.\r
-\r
- The caller is repsonsible for ensuring that\r
- RootBusNumber <= MaxSubBusNumber. If\r
- RootBusNumber equals MaxSubBusNumber, then the\r
- root bus has no room for subordinate buses.\r
-\r
- param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the\r
- caller) that should be filled in by this\r
- function.\r
-\r
- @retval EFI_SUCCESS Initialization successful. A device path\r
- consisting of an ACPI device path node, with\r
- UID = RootBusNumber, has been allocated and\r
- linked into RootBus.\r
-\r
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-InitRootBridge (\r
- IN UINT8 RootBusNumber,\r
- IN UINT8 MaxSubBusNumber,\r
- OUT PCI_ROOT_BRIDGE *RootBus\r
- )\r
-{\r
- //\r
- // Be safe if other fields are added to PCI_ROOT_BRIDGE later.\r
- //\r
- ZeroMem (RootBus, sizeof *RootBus);\r
-\r
- RootBus->Segment = 0;\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
-}\r
-\r
-\r
-/**\r
- Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().\r
-\r
- param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and\r
- initialized with InitRootBridge(), that should be\r
- uninitialized. This function doesn't free RootBus.\r
**/\r
-STATIC\r
-VOID\r
-UninitRootBridge (\r
- IN PCI_ROOT_BRIDGE *RootBus\r
- )\r
-{\r
-}\r
+#include <IndustryStandard/Pci.h> // PCI_MAX_BUS\r
+#include <IndustryStandard/Q35MchIch9.h> // INTEL_Q35_MCH_DEVIC...\r
+#include <Library/BaseMemoryLib.h> // ZeroMem()\r
+#include <Library/PcdLib.h> // PcdGet64()\r
+#include <Library/PciHostBridgeLib.h> // PCI_ROOT_BRIDGE_APE...\r
+#include <Library/PciHostBridgeUtilityLib.h> // PciHostBridgeUtilit...\r
+#include <Protocol/PciHostBridgeResourceAllocation.h> // EFI_PCI_HOST_BRIDGE...\r
+#include <Protocol/PciRootBridgeIo.h> // EFI_PCI_ATTRIBUTE_I...\r
\r
+STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };\r
\r
/**\r
Return all the root bridge instances in an array.\r
PCI_ROOT_BRIDGE *\r
EFIAPI\r
PciHostBridgeGetRootBridges (\r
- UINTN *Count\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
-\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
+ UINT64 Attributes;\r
+ UINT64 AllocationAttributes;\r
+ PCI_ROOT_BRIDGE_APERTURE Io;\r
+ PCI_ROOT_BRIDGE_APERTURE Mem;\r
+ PCI_ROOT_BRIDGE_APERTURE MemAbove4G;\r
+\r
+ ZeroMem (&Io, sizeof (Io));\r
+ ZeroMem (&Mem, sizeof (Mem));\r
+ ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r
+\r
+ Attributes = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |\r
+ EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |\r
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 |\r
+ EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |\r
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY |\r
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 |\r
+ EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;\r
+\r
+ AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM;\r
+ if (PcdGet64 (PcdPciMmio64Size) > 0) {\r
+ AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;\r
+ MemAbove4G.Base = PcdGet64 (PcdPciMmio64Base);\r
+ MemAbove4G.Limit = PcdGet64 (PcdPciMmio64Base) +\r
+ PcdGet64 (PcdPciMmio64Size) - 1;\r
} else {\r
- QemuFwCfgSelectItem (FwCfgItem);\r
- QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);\r
-\r
- if (ExtraRootBridges > PCI_MAX_BUS) {\r
- DEBUG ((EFI_D_ERROR, "%a: invalid count of extra root buses (%Lu) "\r
- "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));\r
- return NULL;\r
- }\r
- DEBUG ((EFI_D_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 ((EFI_D_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 = InitRootBridge ((UINT8)LastRootBridgeNumber,\r
- (UINT8)(RootBridgeNumber - 1), &Bridges[Initialized]);\r
- if (EFI_ERROR (Status)) {\r
- goto FreeBridges;\r
- }\r
- ++Initialized;\r
- LastRootBridgeNumber = RootBridgeNumber;\r
- }\r
+ CopyMem (&MemAbove4G, &mNonExistAperture, sizeof (mNonExistAperture));\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 = InitRootBridge ((UINT8)LastRootBridgeNumber, PCI_MAX_BUS,\r
- &Bridges[Initialized]);\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
- UninitRootBridge (&Bridges[Initialized]);\r
- }\r
-\r
- FreePool (Bridges);\r
- return NULL;\r
+ Io.Base = PcdGet64 (PcdPciIoBase);\r
+ Io.Limit = PcdGet64 (PcdPciIoBase) + (PcdGet64 (PcdPciIoSize) - 1);\r
+ Mem.Base = PcdGet64 (PcdPciMmio32Base);\r
+ Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);\r
+\r
+ return PciHostBridgeUtilityGetRootBridges (\r
+ Count,\r
+ Attributes,\r
+ AllocationAttributes,\r
+ FALSE,\r
+ PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,\r
+ 0,\r
+ PCI_MAX_BUS,\r
+ &Io,\r
+ &Mem,\r
+ &MemAbove4G,\r
+ &mNonExistAperture,\r
+ &mNonExistAperture\r
+ );\r
}\r
\r
-\r
/**\r
Free the root bridge instances array returned from\r
PciHostBridgeGetRootBridges().\r
VOID\r
EFIAPI\r
PciHostBridgeFreeRootBridges (\r
- PCI_ROOT_BRIDGE *Bridges,\r
- UINTN Count\r
+ PCI_ROOT_BRIDGE *Bridges,\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
- UninitRootBridge (&Bridges[Count]);\r
- } while (Count > 0);\r
-\r
- FreePool (Bridges);\r
+ PciHostBridgeUtilityFreeRootBridges (Bridges, Count);\r
}\r
\r
-\r
/**\r
Inform the platform that the resource conflict happens.\r
\r
VOID\r
EFIAPI\r
PciHostBridgeResourceConflict (\r
- EFI_HANDLE HostBridgeHandle,\r
- VOID *Configuration\r
+ EFI_HANDLE HostBridgeHandle,\r
+ VOID *Configuration\r
)\r
{\r
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
- UINTN RootBridgeIndex;\r
- DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));\r
-\r
- RootBridgeIndex = 0;\r
- Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
- while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
- DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));\r
- for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
- ASSERT (Descriptor->ResType <\r
- (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /\r
- sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])\r
- )\r
- );\r
- DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
- mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
- Descriptor->AddrLen, Descriptor->AddrRangeMax\r
- ));\r
- if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
- DEBUG ((EFI_D_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
- }\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
- }\r
+ PciHostBridgeUtilityResourceConflict (Configuration);\r
}\r