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