UINT64 FwCfgSelectorSize;\r
UINT64 FwCfgDataAddress;\r
UINT64 FwCfgDataSize;\r
+ UINT64 FwCfgDmaAddress;\r
+ UINT64 FwCfgDmaSize;\r
+ BOOLEAN HavePci;\r
\r
Hob = GetFirstGuidHob(&gFdtHobGuid);\r
if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
\r
RtcNode = -1;\r
+ HavePci = FALSE;\r
//\r
// Now enumerate the nodes and install peripherals that we are interested in,\r
// i.e., GIC, RTC and virtio MMIO nodes\r
ASSERT (Len == 2 * sizeof (UINT64));\r
Status = ProcessPciHost (DeviceTreeBase, Node, RegProp);\r
ASSERT_EFI_ERROR (Status);\r
+ HavePci = TRUE;\r
break;\r
\r
case PropertyTypeFwCfg:\r
\r
DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress,\r
FwCfgDataAddress));\r
+\r
+ if (fdt64_to_cpu (((UINT64 *)RegProp)[1]) >= 0x18) {\r
+ FwCfgDmaAddress = FwCfgDataAddress + 0x10;\r
+ FwCfgDmaSize = 0x08;\r
+\r
+ //\r
+ // See explanation above.\r
+ //\r
+ ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);\r
+\r
+ PcdSet64 (PcdFwCfgDmaAddress, FwCfgDmaAddress);\r
+ DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));\r
+ }\r
break;\r
\r
case PropertyTypeVirtio:\r
\r
PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);\r
PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);\r
+ PcdSet32 (PcdArmGicRevision, 2);\r
\r
DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase));\r
break;\r
\r
PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);\r
PcdSet32 (PcdGicRedistributorsBase, (UINT32)RedistBase);\r
+ PcdSet32 (PcdArmGicRevision, 3);\r
\r
DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",\r
DistBase, RedistBase));\r
"disabled") != 0) {\r
DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));\r
}\r
+\r
+ if (HavePci) {\r
+ //\r
+ // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI\r
+ // setup we will perform in the firmware is honored by the Linux OS,\r
+ // rather than torn down and done from scratch. This is generally a more\r
+ // sensible approach, and aligns with what ACPI based OSes do in general.\r
+ //\r
+ // In case we are exposing an emulated VGA PCI device to the guest, which\r
+ // may subsequently get exposed via the Graphics Output protocol and\r
+ // driven as an efifb by Linux, we need this setting to prevent the\r
+ // framebuffer from becoming unresponsive.\r
+ //\r
+ Node = fdt_path_offset (DeviceTreeBase, "/chosen");\r
+ if (Node < 0) {\r
+ Node = fdt_add_subnode (DeviceTreeBase, 0, "/chosen");\r
+ }\r
+ if (Node < 0 ||\r
+ fdt_setprop_u32 (DeviceTreeBase, Node, "linux,pci-probe-only", 1) < 0) {\r
+ DEBUG ((EFI_D_WARN, "Failed to set /chosen/linux,pci-probe-only property\n"));\r
+ }\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r