ProcessPciHost (\r
OUT UINT64 *IoBase,\r
OUT UINT64 *IoSize,\r
- OUT UINT64 *MmioBase,\r
- OUT UINT64 *MmioSize,\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
UINT32 RecordIdx;\r
EFI_STATUS Status;\r
UINT64 IoTranslation;\r
- UINT64 MmioTranslation;\r
+ UINT64 Mmio32Translation;\r
+ UINT64 Mmio64Translation;\r
\r
//\r
// The following output arguments are initialized only in\r
// *incorrectly* emitted by some gcc versions.\r
//\r
*IoBase = 0;\r
- *MmioBase = 0;\r
+ *Mmio32Base = 0;\r
+ *Mmio64Base = MAX_UINT64;\r
*BusMin = 0;\r
*BusMax = 0;\r
\r
//\r
- // *IoSize, *MmioSize and IoTranslation are initialized to zero because the\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
- *MmioSize = 0;\r
+ *Mmio32Size = 0;\r
+ *Mmio64Size = 0;\r
IoTranslation = 0;\r
\r
Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
break;\r
\r
case DTB_PCI_HOST_RANGE_MMIO32:\r
- *MmioBase = SwapBytes64 (Record->ChildBase);\r
- *MmioSize = SwapBytes64 (Record->Size);\r
- MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;\r
+ *Mmio32Base = SwapBytes64 (Record->ChildBase);\r
+ *Mmio32Size = SwapBytes64 (Record->Size);\r
+ Mmio32Translation = SwapBytes64 (Record->CpuBase) - *Mmio32Base;\r
\r
- if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||\r
- *MmioBase + *MmioSize > SIZE_4GB) {\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) == MmioTranslation);\r
+ ASSERT (PcdGet64 (PcdPciMmio32Translation) == Mmio32Translation);\r
\r
- if (MmioTranslation != 0) {\r
+ if (Mmio32Translation != 0) {\r
DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "\r
- "0x%Lx\n", __FUNCTION__, MmioTranslation));\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 || *MmioSize == 0) {\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
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 Mem[0x%Lx+0x%Lx)@0x0\n", __FUNCTION__, ConfigBase,\r
- ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, IoTranslation, *MmioBase,\r
- *MmioSize));\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
return EFI_SUCCESS;\r
}\r
\r
{\r
UINT64 IoBase, IoSize;\r
UINT64 Mmio32Base, Mmio32Size;\r
+ UINT64 Mmio64Base, Mmio64Size;\r
UINT32 BusMin, BusMax;\r
EFI_STATUS Status;\r
\r
return NULL;\r
}\r
\r
- Status = ProcessPciHost (&IoBase, &IoSize, &Mmio32Base, &Mmio32Size, &BusMin,\r
- &BusMax);\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
mRootBridge.Io.Limit = IoBase + IoSize - 1;\r
mRootBridge.Mem.Base = Mmio32Base;\r
mRootBridge.Mem.Limit = Mmio32Base + Mmio32Size - 1;\r
- mRootBridge.MemAbove4G.Base = MAX_UINT64;\r
- mRootBridge.MemAbove4G.Limit = 0;\r
+\r
+ if (sizeof (UINTN) == sizeof (UINT64)) {\r
+ mRootBridge.MemAbove4G.Base = Mmio64Base;\r
+ mRootBridge.MemAbove4G.Limit = Mmio64Base + Mmio64Size - 1;\r
+ if (Mmio64Size > 0) {\r
+ mRootBridge.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
+ mRootBridge.MemAbove4G.Base = MAX_UINT64;\r
+ mRootBridge.MemAbove4G.Limit = 0;\r
+ }\r
\r
//\r
// No separate ranges for prefetchable and non-prefetchable BARs\r