--- /dev/null
+/** @file\r
+ PCI Host Bridge utility functions for ArmVirt.\r
+\r
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <IndustryStandard/Acpi10.h>\r
+#include <IndustryStandard/Pci.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PciHostBridgeLib.h>\r
+#include <Library/PciHostBridgeUtilityLib.h>\r
+#include <Library/PciLib.h>\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
+#pragma pack ()\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+CHAR16 *mPciHostBridgeAcpiAddressSpaceTypeStr[] = {\r
+ L"Mem",\r
+ L"I/O",\r
+ L"Bus"\r
+};\r
+\r
+STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {\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
+ }\r
+ },\r
+ EISA_PNP_ID (0x0A03), // HID\r
+ 0 // UID\r
+ },\r
+\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ {\r
+ END_DEVICE_PATH_LENGTH,\r
+ 0\r
+ }\r
+ }\r
+};\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {\r
+ L"Mem", L"I/O", L"Bus"\r
+};\r
+\r
+STATIC PCI_ROOT_BRIDGE mRootBridge;\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 [in] Attributes Initial attributes.\r
+ @param [in] AllocationAttributes Allocation attributes.\r
+ @param [in] DmaAbove4G DMA above 4GB memory.\r
+ @param [in] NoExtendedConfigSpace No Extended Config Space.\r
+ @param [in] BusMin Minimum Bus number, inclusive.\r
+ @param [in] BusMax Maximum Bus number, inclusive.\r
+ @param [in] Io IO aperture.\r
+ @param [in] Mem MMIO aperture.\r
+ @param [in] MemAbove4G MMIO aperture above 4G.\r
+ @param [in] PMem Prefetchable MMIO aperture.\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
+ if ((Count == NULL) ||\r
+ (Io == NULL) ||\r
+ (Mem == NULL) ||\r
+ (MemAbove4G == NULL) ||\r
+ (PMem == NULL) ||\r
+ (PMemAbove4G == NULL)) {\r
+ return NULL;\r
+ }\r
+\r
+\r
+ *Count = 1;\r
+\r
+ mRootBridge.Segment = 0;\r
+ mRootBridge.Supports = Attributes;\r
+ mRootBridge.Attributes = Attributes;\r
+\r
+ mRootBridge.DmaAbove4G = DmaAbove4G;\r
+ mRootBridge.NoExtendedConfigSpace = NoExtendedConfigSpace;\r
+ mRootBridge.ResourceAssigned = FALSE;\r
+\r
+ mRootBridge.AllocationAttributes = AllocationAttributes;\r
+\r
+ mRootBridge.Bus.Base = BusMin;\r
+ mRootBridge.Bus.Limit = BusMax;\r
+ mRootBridge.Io.Base = Io->Base;\r
+ mRootBridge.Io.Limit = Io->Limit;\r
+ mRootBridge.Mem.Base = Mem->Base;\r
+ mRootBridge.Mem.Limit = Mem->Limit;\r
+ mRootBridge.MemAbove4G.Base = MemAbove4G->Base;\r
+ mRootBridge.MemAbove4G.Limit = MemAbove4G->Limit;\r
+ mRootBridge.PMem.Base = PMem->Base;\r
+ mRootBridge.PMem.Limit = PMem->Limit;\r
+ mRootBridge.PMemAbove4G.Base = PMemAbove4G->Base;\r
+ mRootBridge.PMemAbove4G.Limit = PMemAbove4G->Limit;\r
+\r
+ mRootBridge.DevicePath =\r
+ (EFI_DEVICE_PATH_PROTOCOL*)&mEfiPciRootBridgeDevicePath;\r
+\r
+ return &mRootBridge;\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
+ // Nothing to do here.\r
+}\r
+\r
+/**\r
+ Utility function to inform the platform that the resource conflict happens.\r
+\r
+ @param[in] Configuration Pointer to PCI I/O and PCI memory resource\r
+ descriptors. The Configuration contains the\r
+ resources for all the root bridges. The resource\r
+ for each root bridge is terminated with END\r
+ descriptor and an additional END is appended\r
+ indicating the end of the entire resources. The\r
+ resource descriptor field values follow the\r
+ description in\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ .SubmitResources().\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHostBridgeUtilityResourceConflict (\r
+ IN VOID *Configuration\r
+ )\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ UINTN RootBridgeIndex;\r
+ DEBUG ((DEBUG_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 ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));\r
+ for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
+ ASSERT (Descriptor->ResType <\r
+ ARRAY_SIZE (mPciHostBridgeAcpiAddressSpaceTypeStr)\r
+ );\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
+ mPciHostBridgeAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
+ Descriptor->AddrLen,\r
+ Descriptor->AddrRangeMax\r
+ ));\r
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\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
+ // 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
+}\r