# UINT64 Mmio64CpuBase; // mapping target in 64-bit cpu-physical space\r
#\r
# gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation = IoCpuBase - PcdPciIoBase;\r
- # PcdPciMmio32Translation = Mmio32CpuBase - (UINT64)PcdPciMmio32Base;\r
- # PcdPciMmio64Translation = Mmio64CpuBase - PcdPciMmio64Base;\r
+ # gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation = Mmio32CpuBase - (UINT64)PcdPciMmio32Base;\r
+ # gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation = Mmio64CpuBase - PcdPciMmio64Base;\r
#\r
# because (a) the target address space (ie. the cpu-physical space) is\r
# 64-bit, and (b) the translation values are meant as offsets for *modular*\r
# TranslatedIoAddress = UntranslatedIoAddress +\r
# gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation;\r
# TranslatedMmio32Address = (UINT64)UntranslatedMmio32Address +\r
- # PcdPciMmio32Translation;\r
+ # gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation;\r
# TranslatedMmio64Address = UntranslatedMmio64Address +\r
- # PcdPciMmio64Translation;\r
+ # gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation;\r
#\r
# The modular arithmetic performed in UINT64 ensures that the translation\r
# works correctly regardless of the relation between IoCpuBase and\r
gArmTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x00000051\r
gArmTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT32|0x00000053\r
gArmTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT32|0x00000054\r
- gArmTokenSpaceGuid.PcdPciMmio32Translation|0x0|UINT64|0x00000055\r
gArmTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x00000056\r
gArmTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x00000057\r
- gArmTokenSpaceGuid.PcdPciMmio64Translation|0x0|UINT64|0x00000058\r
\r
#\r
# Inclusive range of allowed PCI buses.\r
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf\r
PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf\r
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf\r
- PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
+ PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
PciHostBridgeUtilityLib|ArmVirtPkg/Library/ArmVirtPciHostBridgeUtilityLib/ArmVirtPciHostBridgeUtilityLib.inf\r
\r
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf\r
\r
PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf\r
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf\r
- PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
+ PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
PciHostBridgeUtilityLib|ArmVirtPkg/Library/ArmVirtPciHostBridgeUtilityLib/ArmVirtPciHostBridgeUtilityLib.inf\r
\r
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf\r
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf\r
PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf\r
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf\r
- PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
+ PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf\r
\r
!if $(TPM2_ENABLE) == TRUE\r
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf\r
PciPcdProducerLib|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf\r
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf\r
- PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
+ PciHostBridgeLib|OvmfPkg/Fdt/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf\r
PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf\r
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf\r
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf\r
+++ /dev/null
-/** @file\r
- PCI Host Bridge Library instance for pci-ecam-generic DT nodes\r
-\r
- Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-#include <PiDxe.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/DxeServicesTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/PciHostBridgeLib.h>\r
-#include <Library/PciHostBridgeUtilityLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-\r
-#include <Protocol/FdtClient.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-#include <Protocol/PciHostBridgeResourceAllocation.h>\r
-\r
-//\r
-// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
-// records like this.\r
-//\r
-#pragma pack (1)\r
-typedef struct {\r
- UINT32 Type;\r
- UINT64 ChildBase;\r
- UINT64 CpuBase;\r
- UINT64 Size;\r
-} DTB_PCI_HOST_RANGE_RECORD;\r
-#pragma pack ()\r
-\r
-#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r
-#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
-#define DTB_PCI_HOST_RANGE_ALIASED BIT29\r
-#define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r
-#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r
-#define DTB_PCI_HOST_RANGE_IO BIT24\r
-#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
-\r
-STATIC\r
-EFI_STATUS\r
-MapGcdMmioSpace (\r
- IN UINT64 Base,\r
- IN UINT64 Size\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo, Base, Size,\r
- EFI_MEMORY_UC);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR,\r
- "%a: failed to add GCD memory space for region [0x%Lx+0x%Lx)\n",\r
- __FUNCTION__, Base, Size));\r
- return Status;\r
- }\r
-\r
- Status = gDS->SetMemorySpaceAttributes (Base, Size, EFI_MEMORY_UC);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR,\r
- "%a: failed to set memory space attributes for region [0x%Lx+0x%Lx)\n",\r
- __FUNCTION__, Base, Size));\r
- }\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-ProcessPciHost (\r
- OUT UINT64 *IoBase,\r
- OUT UINT64 *IoSize,\r
- OUT UINT64 *Mmio32Base,\r
- OUT UINT64 *Mmio32Size,\r
- OUT UINT64 *Mmio64Base,\r
- OUT UINT64 *Mmio64Size,\r
- OUT UINT32 *BusMin,\r
- OUT UINT32 *BusMax\r
- )\r
-{\r
- FDT_CLIENT_PROTOCOL *FdtClient;\r
- INT32 Node;\r
- UINT64 ConfigBase, ConfigSize;\r
- CONST VOID *Prop;\r
- UINT32 Len;\r
- UINT32 RecordIdx;\r
- EFI_STATUS Status;\r
- UINT64 IoTranslation;\r
- UINT64 Mmio32Translation;\r
- UINT64 Mmio64Translation;\r
-\r
- //\r
- // The following output arguments are initialized only in\r
- // order to suppress '-Werror=maybe-uninitialized' warnings\r
- // *incorrectly* emitted by some gcc versions.\r
- //\r
- *IoBase = 0;\r
- *Mmio32Base = 0;\r
- *Mmio64Base = MAX_UINT64;\r
- *BusMin = 0;\r
- *BusMax = 0;\r
-\r
- //\r
- // *IoSize, *Mmio##Size and IoTranslation are initialized to zero because the\r
- // logic below requires it. However, since they are also affected by the issue\r
- // reported above, they are initialized early.\r
- //\r
- *IoSize = 0;\r
- *Mmio32Size = 0;\r
- *Mmio64Size = 0;\r
- IoTranslation = 0;\r
-\r
- Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
- (VOID **)&FdtClient);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r
- &Node);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_INFO,\r
- "%a: No 'pci-host-ecam-generic' compatible DT node found\n",\r
- __FUNCTION__));\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- DEBUG_CODE (\r
- INT32 Tmp;\r
-\r
- //\r
- // A DT can legally describe multiple PCI host bridges, but we are not\r
- // equipped to deal with that. So assert that there is only one.\r
- //\r
- Status = FdtClient->FindNextCompatibleNode (FdtClient,\r
- "pci-host-ecam-generic", Node, &Tmp);\r
- ASSERT (Status == EFI_NOT_FOUND);\r
- );\r
-\r
- Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);\r
- if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {\r
- DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",\r
- __FUNCTION__));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
-\r
- //\r
- // Fetch the ECAM window.\r
- //\r
- ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);\r
- ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);\r
-\r
- //\r
- // Fetch the bus range (note: inclusive).\r
- //\r
- Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,\r
- &Len);\r
- if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {\r
- DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",\r
- __FUNCTION__));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
- *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);\r
- *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);\r
-\r
- //\r
- // Sanity check: the config space must accommodate all 4K register bytes of\r
- // all 8 functions of all 32 devices of all buses.\r
- //\r
- if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||\r
- DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {\r
- DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",\r
- __FUNCTION__));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
-\r
- //\r
- // Iterate over "ranges".\r
- //\r
- Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
- if (EFI_ERROR (Status) || Len == 0 ||\r
- Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
- DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
-\r
- for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
- ++RecordIdx) {\r
- CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
-\r
- Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
- switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {\r
- case DTB_PCI_HOST_RANGE_IO:\r
- *IoBase = SwapBytes64 (Record->ChildBase);\r
- *IoSize = SwapBytes64 (Record->Size);\r
- IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;\r
-\r
- ASSERT (PcdGet64 (PcdPciIoTranslation) == IoTranslation);\r
- break;\r
-\r
- case DTB_PCI_HOST_RANGE_MMIO32:\r
- *Mmio32Base = SwapBytes64 (Record->ChildBase);\r
- *Mmio32Size = SwapBytes64 (Record->Size);\r
- Mmio32Translation = SwapBytes64 (Record->CpuBase) - *Mmio32Base;\r
-\r
- if (*Mmio32Base > MAX_UINT32 || *Mmio32Size > MAX_UINT32 ||\r
- *Mmio32Base + *Mmio32Size > SIZE_4GB) {\r
- DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
-\r
- ASSERT (PcdGet64 (PcdPciMmio32Translation) == Mmio32Translation);\r
-\r
- if (Mmio32Translation != 0) {\r
- DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "\r
- "0x%Lx\n", __FUNCTION__, Mmio32Translation));\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- break;\r
-\r
- case DTB_PCI_HOST_RANGE_MMIO64:\r
- *Mmio64Base = SwapBytes64 (Record->ChildBase);\r
- *Mmio64Size = SwapBytes64 (Record->Size);\r
- Mmio64Translation = SwapBytes64 (Record->CpuBase) - *Mmio64Base;\r
-\r
- ASSERT (PcdGet64 (PcdPciMmio64Translation) == Mmio64Translation);\r
-\r
- if (Mmio64Translation != 0) {\r
- DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO64 translation "\r
- "0x%Lx\n", __FUNCTION__, Mmio64Translation));\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- break;\r
- }\r
- }\r
- if (*IoSize == 0 || *Mmio32Size == 0) {\r
- DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,\r
- (*IoSize == 0) ? "IO" : "MMIO32"));\r
- return EFI_PROTOCOL_ERROR;\r
- }\r
-\r
- //\r
- // The dynamic PCD PcdPciExpressBaseAddress should have already been set,\r
- // and should match the value we found in the DT node.\r
- //\r
- ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);\r
-\r
- DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "\r
- "Io[0x%Lx+0x%Lx)@0x%Lx Mem32[0x%Lx+0x%Lx)@0x0 Mem64[0x%Lx+0x%Lx)@0x0\n",\r
- __FUNCTION__, ConfigBase, ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize,\r
- IoTranslation, *Mmio32Base, *Mmio32Size, *Mmio64Base, *Mmio64Size));\r
-\r
- // Map the ECAM space in the GCD memory map\r
- Status = MapGcdMmioSpace (ConfigBase, ConfigSize);\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Map the MMIO window that provides I/O access - the PCI host bridge code\r
- // is not aware of this translation and so it will only map the I/O view\r
- // in the GCD I/O map.\r
- //\r
- Status = MapGcdMmioSpace (*IoBase + IoTranslation, *IoSize);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Return all the root bridge instances in an array.\r
-\r
- @param Count Return the count of root bridge instances.\r
-\r
- @return All the root bridge instances in an array.\r
- The array should be passed into PciHostBridgeFreeRootBridges()\r
- when it's not used.\r
-**/\r
-PCI_ROOT_BRIDGE *\r
-EFIAPI\r
-PciHostBridgeGetRootBridges (\r
- UINTN *Count\r
- )\r
-{\r
- UINT64 IoBase, IoSize;\r
- UINT64 Mmio32Base, Mmio32Size;\r
- UINT64 Mmio64Base, Mmio64Size;\r
- UINT32 BusMin, BusMax;\r
- EFI_STATUS Status;\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
- PCI_ROOT_BRIDGE_APERTURE PMem;\r
- PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;\r
-\r
- if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {\r
- DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));\r
-\r
- *Count = 0;\r
- return NULL;\r
- }\r
-\r
- Status = ProcessPciHost (&IoBase, &IoSize, &Mmio32Base, &Mmio32Size,\r
- &Mmio64Base, &Mmio64Size, &BusMin, &BusMax);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: failed to discover PCI host bridge: %r\n",\r
- __FUNCTION__, Status));\r
- *Count = 0;\r
- return NULL;\r
- }\r
-\r
- ZeroMem (&Io, sizeof (Io));\r
- ZeroMem (&Mem, sizeof (Mem));\r
- ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r
- ZeroMem (&PMem, sizeof (PMem));\r
- ZeroMem (&PMemAbove4G, sizeof (PMemAbove4G));\r
-\r
- Attributes = EFI_PCI_ATTRIBUTE_ISA_IO_16 |\r
- EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |\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
-\r
- Io.Base = IoBase;\r
- Io.Limit = IoBase + IoSize - 1;\r
- Mem.Base = Mmio32Base;\r
- Mem.Limit = Mmio32Base + Mmio32Size - 1;\r
-\r
- if (sizeof (UINTN) == sizeof (UINT64)) {\r
- MemAbove4G.Base = Mmio64Base;\r
- MemAbove4G.Limit = Mmio64Base + Mmio64Size - 1;\r
- if (Mmio64Size > 0) {\r
- AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;\r
- }\r
- } else {\r
- //\r
- // UEFI mandates a 1:1 virtual-to-physical mapping, so on a 32-bit\r
- // architecture such as ARM, we will not be able to access 64-bit MMIO\r
- // BARs unless they are allocated below 4 GB. So ignore the range above\r
- // 4 GB in this case.\r
- //\r
- MemAbove4G.Base = MAX_UINT64;\r
- MemAbove4G.Limit = 0;\r
- }\r
-\r
- //\r
- // No separate ranges for prefetchable and non-prefetchable BARs\r
- //\r
- PMem.Base = MAX_UINT64;\r
- PMem.Limit = 0;\r
- PMemAbove4G.Base = MAX_UINT64;\r
- PMemAbove4G.Limit = 0;\r
-\r
- return PciHostBridgeUtilityGetRootBridges (\r
- Count,\r
- Attributes,\r
- AllocationAttributes,\r
- TRUE,\r
- FALSE,\r
- BusMin,\r
- BusMax,\r
- &Io,\r
- &Mem,\r
- &MemAbove4G,\r
- &PMem,\r
- &PMemAbove4G\r
- );\r
-}\r
-\r
-/**\r
- Free the root bridge instances array returned from\r
- PciHostBridgeGetRootBridges().\r
-\r
- @param Bridges The root bridge instances array.\r
- @param Count The count of the array.\r
-**/\r
-VOID\r
-EFIAPI\r
-PciHostBridgeFreeRootBridges (\r
- PCI_ROOT_BRIDGE *Bridges,\r
- UINTN Count\r
- )\r
-{\r
- PciHostBridgeUtilityFreeRootBridges (Bridges, Count);\r
-}\r
-\r
-/**\r
- Inform the platform that the resource conflict happens.\r
-\r
- @param HostBridgeHandle Handle of the Host Bridge.\r
- @param Configuration Pointer to PCI I/O and PCI memory resource\r
- descriptors. The Configuration contains the resources\r
- for all the root bridges. The resource for each root\r
- bridge is terminated with END descriptor and an\r
- additional END is appended indicating the end of the\r
- entire resources. The resource descriptor field\r
- values follow the description in\r
- EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
- .SubmitResources().\r
-**/\r
-VOID\r
-EFIAPI\r
-PciHostBridgeResourceConflict (\r
- EFI_HANDLE HostBridgeHandle,\r
- VOID *Configuration\r
- )\r
-{\r
- PciHostBridgeUtilityResourceConflict (Configuration);\r
-}\r
+++ /dev/null
-## @file\r
-# PCI Host Bridge Library instance for pci-ecam-generic DT nodes\r
-#\r
-# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
-#\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = FdtPciHostBridgeLib\r
- FILE_GUID = 59fcb139-2558-4cf0-8d7c-ebac499da727\r
- MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
- LIBRARY_CLASS = PciHostBridgeLib\r
-\r
-#\r
-# The following information is for reference only and not required by the build\r
-# tools.\r
-#\r
-# VALID_ARCHITECTURES = AARCH64 ARM\r
-#\r
-\r
-[Sources]\r
- FdtPciHostBridgeLib.c\r
-\r
-[Packages]\r
- ArmPkg/ArmPkg.dec\r
- ArmVirtPkg/ArmVirtPkg.dec\r
- EmbeddedPkg/EmbeddedPkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- MdePkg/MdePkg.dec\r
- OvmfPkg/OvmfPkg.dec\r
-\r
-[LibraryClasses]\r
- BaseMemoryLib\r
- DebugLib\r
- DevicePathLib\r
- DxeServicesTableLib\r
- MemoryAllocationLib\r
- PciHostBridgeUtilityLib\r
- PciPcdProducerLib\r
-\r
-[FixedPcd]\r
- gArmTokenSpaceGuid.PcdPciMmio32Translation\r
- gArmTokenSpaceGuid.PcdPciMmio64Translation\r
-\r
-[Pcd]\r
- gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation\r
- gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
-\r
-[Depex]\r
- gFdtClientProtocolGuid\r
--- /dev/null
+/** @file\r
+ PCI Host Bridge Library instance for pci-ecam-generic DT nodes\r
+\r
+ Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include <PiDxe.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciHostBridgeLib.h>\r
+#include <Library/PciHostBridgeUtilityLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/PciHostBridgeResourceAllocation.h>\r
+\r
+//\r
+// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
+// records like this.\r
+//\r
+#pragma pack (1)\r
+typedef struct {\r
+ UINT32 Type;\r
+ UINT64 ChildBase;\r
+ UINT64 CpuBase;\r
+ UINT64 Size;\r
+} DTB_PCI_HOST_RANGE_RECORD;\r
+#pragma pack ()\r
+\r
+#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r
+#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
+#define DTB_PCI_HOST_RANGE_ALIASED BIT29\r
+#define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r
+#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r
+#define DTB_PCI_HOST_RANGE_IO BIT24\r
+#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
+\r
+STATIC\r
+EFI_STATUS\r
+MapGcdMmioSpace (\r
+ IN UINT64 Base,\r
+ IN UINT64 Size\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo, Base, Size,\r
+ EFI_MEMORY_UC);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR,\r
+ "%a: failed to add GCD memory space for region [0x%Lx+0x%Lx)\n",\r
+ __FUNCTION__, Base, Size));\r
+ return Status;\r
+ }\r
+\r
+ Status = gDS->SetMemorySpaceAttributes (Base, Size, EFI_MEMORY_UC);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR,\r
+ "%a: failed to set memory space attributes for region [0x%Lx+0x%Lx)\n",\r
+ __FUNCTION__, Base, Size));\r
+ }\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+ProcessPciHost (\r
+ OUT UINT64 *IoBase,\r
+ OUT UINT64 *IoSize,\r
+ OUT UINT64 *Mmio32Base,\r
+ OUT UINT64 *Mmio32Size,\r
+ OUT UINT64 *Mmio64Base,\r
+ OUT UINT64 *Mmio64Size,\r
+ OUT UINT32 *BusMin,\r
+ OUT UINT32 *BusMax\r
+ )\r
+{\r
+ FDT_CLIENT_PROTOCOL *FdtClient;\r
+ INT32 Node;\r
+ UINT64 ConfigBase, ConfigSize;\r
+ CONST VOID *Prop;\r
+ UINT32 Len;\r
+ UINT32 RecordIdx;\r
+ EFI_STATUS Status;\r
+ UINT64 IoTranslation;\r
+ UINT64 Mmio32Translation;\r
+ UINT64 Mmio64Translation;\r
+\r
+ //\r
+ // The following output arguments are initialized only in\r
+ // order to suppress '-Werror=maybe-uninitialized' warnings\r
+ // *incorrectly* emitted by some gcc versions.\r
+ //\r
+ *IoBase = 0;\r
+ *Mmio32Base = 0;\r
+ *Mmio64Base = MAX_UINT64;\r
+ *BusMin = 0;\r
+ *BusMax = 0;\r
+\r
+ //\r
+ // *IoSize, *Mmio##Size and IoTranslation are initialized to zero because the\r
+ // logic below requires it. However, since they are also affected by the issue\r
+ // reported above, they are initialized early.\r
+ //\r
+ *IoSize = 0;\r
+ *Mmio32Size = 0;\r
+ *Mmio64Size = 0;\r
+ IoTranslation = 0;\r
+\r
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
+ (VOID **)&FdtClient);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r
+ &Node);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO,\r
+ "%a: No 'pci-host-ecam-generic' compatible DT node found\n",\r
+ __FUNCTION__));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DEBUG_CODE (\r
+ INT32 Tmp;\r
+\r
+ //\r
+ // A DT can legally describe multiple PCI host bridges, but we are not\r
+ // equipped to deal with that. So assert that there is only one.\r
+ //\r
+ Status = FdtClient->FindNextCompatibleNode (FdtClient,\r
+ "pci-host-ecam-generic", Node, &Tmp);\r
+ ASSERT (Status == EFI_NOT_FOUND);\r
+ );\r
+\r
+ Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);\r
+ if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {\r
+ DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",\r
+ __FUNCTION__));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ //\r
+ // Fetch the ECAM window.\r
+ //\r
+ ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);\r
+ ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);\r
+\r
+ //\r
+ // Fetch the bus range (note: inclusive).\r
+ //\r
+ Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,\r
+ &Len);\r
+ if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {\r
+ DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",\r
+ __FUNCTION__));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+ *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);\r
+ *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);\r
+\r
+ //\r
+ // Sanity check: the config space must accommodate all 4K register bytes of\r
+ // all 8 functions of all 32 devices of all buses.\r
+ //\r
+ if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||\r
+ DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {\r
+ DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",\r
+ __FUNCTION__));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ //\r
+ // Iterate over "ranges".\r
+ //\r
+ Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
+ if (EFI_ERROR (Status) || Len == 0 ||\r
+ Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
+ DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
+ ++RecordIdx) {\r
+ CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
+\r
+ Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
+ switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {\r
+ case DTB_PCI_HOST_RANGE_IO:\r
+ *IoBase = SwapBytes64 (Record->ChildBase);\r
+ *IoSize = SwapBytes64 (Record->Size);\r
+ IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;\r
+\r
+ ASSERT (PcdGet64 (PcdPciIoTranslation) == IoTranslation);\r
+ break;\r
+\r
+ case DTB_PCI_HOST_RANGE_MMIO32:\r
+ *Mmio32Base = SwapBytes64 (Record->ChildBase);\r
+ *Mmio32Size = SwapBytes64 (Record->Size);\r
+ Mmio32Translation = SwapBytes64 (Record->CpuBase) - *Mmio32Base;\r
+\r
+ if (*Mmio32Base > MAX_UINT32 || *Mmio32Size > MAX_UINT32 ||\r
+ *Mmio32Base + *Mmio32Size > SIZE_4GB) {\r
+ DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ ASSERT (PcdGet64 (PcdPciMmio32Translation) == Mmio32Translation);\r
+\r
+ if (Mmio32Translation != 0) {\r
+ DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "\r
+ "0x%Lx\n", __FUNCTION__, Mmio32Translation));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ break;\r
+\r
+ case DTB_PCI_HOST_RANGE_MMIO64:\r
+ *Mmio64Base = SwapBytes64 (Record->ChildBase);\r
+ *Mmio64Size = SwapBytes64 (Record->Size);\r
+ Mmio64Translation = SwapBytes64 (Record->CpuBase) - *Mmio64Base;\r
+\r
+ ASSERT (PcdGet64 (PcdPciMmio64Translation) == Mmio64Translation);\r
+\r
+ if (Mmio64Translation != 0) {\r
+ DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO64 translation "\r
+ "0x%Lx\n", __FUNCTION__, Mmio64Translation));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ if (*IoSize == 0 || *Mmio32Size == 0) {\r
+ DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,\r
+ (*IoSize == 0) ? "IO" : "MMIO32"));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ //\r
+ // The dynamic PCD PcdPciExpressBaseAddress should have already been set,\r
+ // and should match the value we found in the DT node.\r
+ //\r
+ ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);\r
+\r
+ DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "\r
+ "Io[0x%Lx+0x%Lx)@0x%Lx Mem32[0x%Lx+0x%Lx)@0x0 Mem64[0x%Lx+0x%Lx)@0x0\n",\r
+ __FUNCTION__, ConfigBase, ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize,\r
+ IoTranslation, *Mmio32Base, *Mmio32Size, *Mmio64Base, *Mmio64Size));\r
+\r
+ // Map the ECAM space in the GCD memory map\r
+ Status = MapGcdMmioSpace (ConfigBase, ConfigSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Map the MMIO window that provides I/O access - the PCI host bridge code\r
+ // is not aware of this translation and so it will only map the I/O view\r
+ // in the GCD I/O map.\r
+ //\r
+ Status = MapGcdMmioSpace (*IoBase + IoTranslation, *IoSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Return all the root bridge instances in an array.\r
+\r
+ @param Count Return the count of root bridge instances.\r
+\r
+ @return All the root bridge instances in an array.\r
+ The array should be passed into PciHostBridgeFreeRootBridges()\r
+ when it's not used.\r
+**/\r
+PCI_ROOT_BRIDGE *\r
+EFIAPI\r
+PciHostBridgeGetRootBridges (\r
+ UINTN *Count\r
+ )\r
+{\r
+ UINT64 IoBase, IoSize;\r
+ UINT64 Mmio32Base, Mmio32Size;\r
+ UINT64 Mmio64Base, Mmio64Size;\r
+ UINT32 BusMin, BusMax;\r
+ EFI_STATUS Status;\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
+ PCI_ROOT_BRIDGE_APERTURE PMem;\r
+ PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;\r
+\r
+ if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {\r
+ DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));\r
+\r
+ *Count = 0;\r
+ return NULL;\r
+ }\r
+\r
+ Status = ProcessPciHost (&IoBase, &IoSize, &Mmio32Base, &Mmio32Size,\r
+ &Mmio64Base, &Mmio64Size, &BusMin, &BusMax);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a: failed to discover PCI host bridge: %r\n",\r
+ __FUNCTION__, Status));\r
+ *Count = 0;\r
+ return NULL;\r
+ }\r
+\r
+ ZeroMem (&Io, sizeof (Io));\r
+ ZeroMem (&Mem, sizeof (Mem));\r
+ ZeroMem (&MemAbove4G, sizeof (MemAbove4G));\r
+ ZeroMem (&PMem, sizeof (PMem));\r
+ ZeroMem (&PMemAbove4G, sizeof (PMemAbove4G));\r
+\r
+ Attributes = EFI_PCI_ATTRIBUTE_ISA_IO_16 |\r
+ EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |\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
+\r
+ Io.Base = IoBase;\r
+ Io.Limit = IoBase + IoSize - 1;\r
+ Mem.Base = Mmio32Base;\r
+ Mem.Limit = Mmio32Base + Mmio32Size - 1;\r
+\r
+ if (sizeof (UINTN) == sizeof (UINT64)) {\r
+ MemAbove4G.Base = Mmio64Base;\r
+ MemAbove4G.Limit = Mmio64Base + Mmio64Size - 1;\r
+ if (Mmio64Size > 0) {\r
+ AllocationAttributes |= EFI_PCI_HOST_BRIDGE_MEM64_DECODE;\r
+ }\r
+ } else {\r
+ //\r
+ // UEFI mandates a 1:1 virtual-to-physical mapping, so on a 32-bit\r
+ // architecture such as ARM, we will not be able to access 64-bit MMIO\r
+ // BARs unless they are allocated below 4 GB. So ignore the range above\r
+ // 4 GB in this case.\r
+ //\r
+ MemAbove4G.Base = MAX_UINT64;\r
+ MemAbove4G.Limit = 0;\r
+ }\r
+\r
+ //\r
+ // No separate ranges for prefetchable and non-prefetchable BARs\r
+ //\r
+ PMem.Base = MAX_UINT64;\r
+ PMem.Limit = 0;\r
+ PMemAbove4G.Base = MAX_UINT64;\r
+ PMemAbove4G.Limit = 0;\r
+\r
+ return PciHostBridgeUtilityGetRootBridges (\r
+ Count,\r
+ Attributes,\r
+ AllocationAttributes,\r
+ TRUE,\r
+ FALSE,\r
+ BusMin,\r
+ BusMax,\r
+ &Io,\r
+ &Mem,\r
+ &MemAbove4G,\r
+ &PMem,\r
+ &PMemAbove4G\r
+ );\r
+}\r
+\r
+/**\r
+ Free the root bridge instances array returned from\r
+ PciHostBridgeGetRootBridges().\r
+\r
+ @param Bridges The root bridge instances array.\r
+ @param Count The count of the array.\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHostBridgeFreeRootBridges (\r
+ PCI_ROOT_BRIDGE *Bridges,\r
+ UINTN Count\r
+ )\r
+{\r
+ PciHostBridgeUtilityFreeRootBridges (Bridges, Count);\r
+}\r
+\r
+/**\r
+ Inform the platform that the resource conflict happens.\r
+\r
+ @param HostBridgeHandle Handle of the Host Bridge.\r
+ @param Configuration Pointer to PCI I/O and PCI memory resource\r
+ descriptors. The Configuration contains the resources\r
+ for all the root bridges. The resource for each root\r
+ bridge is terminated with END descriptor and an\r
+ additional END is appended indicating the end of the\r
+ entire resources. The resource descriptor field\r
+ values follow the description in\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ .SubmitResources().\r
+**/\r
+VOID\r
+EFIAPI\r
+PciHostBridgeResourceConflict (\r
+ EFI_HANDLE HostBridgeHandle,\r
+ VOID *Configuration\r
+ )\r
+{\r
+ PciHostBridgeUtilityResourceConflict (Configuration);\r
+}\r
--- /dev/null
+## @file\r
+# PCI Host Bridge Library instance for pci-ecam-generic DT nodes\r
+#\r
+# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = FdtPciHostBridgeLib\r
+ FILE_GUID = 59fcb139-2558-4cf0-8d7c-ebac499da727\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = PciHostBridgeLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+# VALID_ARCHITECTURES = AARCH64 ARM\r
+#\r
+\r
+[Sources]\r
+ FdtPciHostBridgeLib.c\r
+\r
+[Packages]\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ MdePkg/MdePkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseMemoryLib\r
+ DebugLib\r
+ DevicePathLib\r
+ DxeServicesTableLib\r
+ MemoryAllocationLib\r
+ PciHostBridgeUtilityLib\r
+ PciPcdProducerLib\r
+\r
+[FixedPcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation\r
+ gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation\r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation\r
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress\r
+\r
+[Depex]\r
+ gFdtClientProtocolGuid\r