From cc33217ae783ba88ab64672774d90a998cd5cea4 Mon Sep 17 00:00:00 2001 From: Sami Mujawar Date: Tue, 20 Apr 2021 13:59:06 +0100 Subject: [PATCH 1/1] ArmVirtPkg: Add PCI host bridge utility lib for Kvmtool The PCI host bridge utility lib is used to retrieve information about the Root Bridges in a platform. Therefore, add an instance of PciHostBridgeUtilityLib as this is required to enable PCI support for Kvmtool firmware. Signed-off-by: Sami Mujawar --- .../KvmtoolPciHostBridgeUtilityLib.c | 220 +++++++++++++++++++++ .../KvmtoolPciHostBridgeUtilityLib.inf | 39 ++++ 2 files changed, 259 insertions(+) create mode 100644 ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.c create mode 100644 ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.inf diff --git a/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.c b/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.c new file mode 100644 index 000000000000..ee3af07340fc --- /dev/null +++ b/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.c @@ -0,0 +1,220 @@ +/** @file + PCI Host Bridge utility functions for Kvmtool. + + Copyright (c) 2021, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) + +/** A structure describing the ACPI and EFI device path for + the PCI Root Bridge device. +**/ +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; + +#pragma pack () + +/** An array of strings describing the ACPI address space type. +**/ +GLOBAL_REMOVE_IF_UNREFERENCED +STATIC CONST CHAR16 *mPciHostBridgeAcpiAddressSpaceTypeStr[] = { + L"Mem", + L"I/O", + L"Bus" +}; + +STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = { + { + // ACPI device path. + { + 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. + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +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] AllocAttributes 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 + ); + } +} diff --git a/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.inf b/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.inf new file mode 100644 index 000000000000..0e03fd6af8f0 --- /dev/null +++ b/ArmVirtPkg/Library/KvmtoolPciHostBridgeUtilityLib/KvmtoolPciHostBridgeUtilityLib.inf @@ -0,0 +1,39 @@ +## @file +# PciHostBridgeLib utility functions for Kvmtool. +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = KvmtoolPciHostBridgeUtilityLib + FILE_GUID = 22A8844E-2AE7-4BF1-91FA-6EFDE3FE540C + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciHostBridgeUtilityLib + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = AARCH64 ARM +# + +[Sources] + KvmtoolPciHostBridgeUtilityLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PciLib -- SAMI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}