37#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31
38#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
39#define DTB_PCI_HOST_RANGE_ALIASED BIT29
40#define DTB_PCI_HOST_RANGE_MMIO32 BIT25
41#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)
42#define DTB_PCI_HOST_RANGE_IO BIT24
43#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
54 Status =
gDS->AddMemorySpace (
60 if (EFI_ERROR (Status)) {
63 "%a: failed to add GCD memory space for region [0x%Lx+0x%Lx)\n",
71 Status =
gDS->SetMemorySpaceAttributes (Base, Size, EFI_MEMORY_UC);
72 if (EFI_ERROR (Status)) {
75 "%a: failed to set memory space attributes for region [0x%Lx+0x%Lx)\n",
90 OUT UINT64 *Mmio32Base,
91 OUT UINT64 *Mmio32Size,
92 OUT UINT64 *Mmio64Base,
93 OUT UINT64 *Mmio64Size,
100 UINT64 ConfigBase, ConfigSize;
105 UINT64 IoTranslation;
106 UINT64 Mmio32Translation;
107 UINT64 Mmio64Translation;
116 *Mmio64Base = MAX_UINT64;
130 Status =
gBS->LocateProtocol (
131 &gFdtClientProtocolGuid,
137 Status = FdtClient->FindCompatibleNode (
139 "pci-host-ecam-generic",
142 if (EFI_ERROR (Status)) {
145 "%a: No 'pci-host-ecam-generic' compatible DT node found\n",
148 return EFI_NOT_FOUND;
158 Status = FdtClient->FindNextCompatibleNode (
160 "pci-host-ecam-generic",
164 ASSERT (Status == EFI_NOT_FOUND);
167 Status = FdtClient->GetNodeProperty (FdtClient, Node,
"reg", &Prop, &Len);
168 if (EFI_ERROR (Status) || (Len != 2 *
sizeof (UINT64))) {
171 "%a: 'reg' property not found or invalid\n",
174 return EFI_PROTOCOL_ERROR;
186 Status = FdtClient->GetNodeProperty (
193 if (EFI_ERROR (Status) || (Len != 2 *
sizeof (UINT32))) {
196 "%a: 'bus-range' not found or invalid\n",
199 return EFI_PROTOCOL_ERROR;
209 if ((*BusMax < *BusMin) || (*BusMax - *BusMin == MAX_UINT32) ||
210 (
DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1))
214 "%a: invalid 'bus-range' and/or 'reg'\n",
217 return EFI_PROTOCOL_ERROR;
223 Status = FdtClient->GetNodeProperty (FdtClient, Node,
"ranges", &Prop, &Len);
224 if (EFI_ERROR (Status) || (Len == 0) ||
227 DEBUG ((DEBUG_ERROR,
"%a: 'ranges' not found or invalid\n", __func__));
228 return EFI_PROTOCOL_ERROR;
237 switch (
SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {
238 case DTB_PCI_HOST_RANGE_IO:
241 IoTranslation =
SwapBytes64 (Record->CpuBase) - *IoBase;
243 ASSERT (
PcdGet64 (PcdPciIoTranslation) == IoTranslation);
246 case DTB_PCI_HOST_RANGE_MMIO32:
249 Mmio32Translation =
SwapBytes64 (Record->CpuBase) - *Mmio32Base;
251 if ((*Mmio32Base > MAX_UINT32) || (*Mmio32Size > MAX_UINT32) ||
252 (*Mmio32Base + *Mmio32Size > SIZE_4GB))
254 DEBUG ((DEBUG_ERROR,
"%a: MMIO32 space invalid\n", __func__));
255 return EFI_PROTOCOL_ERROR;
258 ASSERT (
PcdGet64 (PcdPciMmio32Translation) == Mmio32Translation);
260 if (Mmio32Translation != 0) {
263 "%a: unsupported nonzero MMIO32 translation "
268 return EFI_UNSUPPORTED;
273 case DTB_PCI_HOST_RANGE_MMIO64:
276 Mmio64Translation =
SwapBytes64 (Record->CpuBase) - *Mmio64Base;
278 ASSERT (
PcdGet64 (PcdPciMmio64Translation) == Mmio64Translation);
280 if (Mmio64Translation != 0) {
283 "%a: unsupported nonzero MMIO64 translation "
288 return EFI_UNSUPPORTED;
295 if (*Mmio32Size == 0) {
296 DEBUG ((DEBUG_ERROR,
"%a: MMIO32 space empty\n", __func__));
297 return EFI_PROTOCOL_ERROR;
304 ASSERT (
PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);
308 "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
309 "Io[0x%Lx+0x%Lx)@0x%Lx Mem32[0x%Lx+0x%Lx)@0x0 Mem64[0x%Lx+0x%Lx)@0x0\n",
325 Status = MapGcdMmioSpace (ConfigBase, ConfigSize);
327 if (EFI_ERROR (Status)) {
337 Status = MapGcdMmioSpace (*IoBase + IoTranslation, *IoSize);
359 UINT64 IoBase, IoSize;
360 UINT64 Mmio32Base, Mmio32Size;
361 UINT64 Mmio64Base, Mmio64Size;
362 UINT32 BusMin, BusMax;
365 UINT64 AllocationAttributes;
372 if (
PcdGet64 (PcdPciExpressBaseAddress) == 0) {
373 DEBUG ((DEBUG_INFO,
"%a: PCI host bridge not present\n", __func__));
379 Status = ProcessPciHost (
389 if (EFI_ERROR (Status)) {
392 "%a: failed to discover PCI host bridge: %r\n",
402 ZeroMem (&MemAbove4G,
sizeof (MemAbove4G));
403 ZeroMem (&PMem,
sizeof (PMem));
404 ZeroMem (&PMemAbove4G,
sizeof (PMemAbove4G));
406 Attributes = EFI_PCI_ATTRIBUTE_ISA_IO_16 |
407 EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
408 EFI_PCI_ATTRIBUTE_VGA_IO_16 |
409 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
415 Io.Limit = IoBase + IoSize - 1;
417 Io.Base = MAX_UINT64;
421 Mem.Base = Mmio32Base;
422 Mem.Limit = Mmio32Base + Mmio32Size - 1;
424 if ((
sizeof (
UINTN) ==
sizeof (UINT64)) && (Mmio64Size != 0)) {
425 MemAbove4G.Base = Mmio64Base;
426 MemAbove4G.Limit = Mmio64Base + Mmio64Size - 1;
435 MemAbove4G.Base = MAX_UINT64;
436 MemAbove4G.Limit = 0;
442 PMem.Base = MAX_UINT64;
444 PMemAbove4G.Base = MAX_UINT64;
445 PMemAbove4G.Limit = 0;
450 AllocationAttributes,
VOID EFIAPI PciHostBridgeUtilityFreeRootBridges(IN PCI_ROOT_BRIDGE *Bridges, IN UINTN Count)
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)
VOID EFIAPI PciHostBridgeUtilityResourceConflict(IN VOID *Configuration)
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
PCI_ROOT_BRIDGE *EFIAPI PciHostBridgeGetRootBridges(UINTN *Count)
VOID EFIAPI PciHostBridgeFreeRootBridges(PCI_ROOT_BRIDGE *Bridges, UINTN Count)
VOID EFIAPI PciHostBridgeResourceConflict(EFI_HANDLE HostBridgeHandle, VOID *Configuration)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define DEBUG_CODE(Expression)
#define PcdGet64(TokenName)
#define EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
#define EFI_PCI_HOST_BRIDGE_MEM64_DECODE
@ EfiGcdMemoryTypeMemoryMappedIo