]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
ArmVirtPkg/VirtFdtDxe: set /chosen/linux,pci-probe-only to 1 in DTB
[mirror_edk2.git] / ArmVirtPkg / VirtFdtDxe / VirtFdtDxe.c
index c9a181a871b8cf2ca555553c649c383bdcc0ec74..437b2a8792160626d826970bde84d6c8da67db4d 100644 (file)
@@ -302,6 +302,9 @@ InitializeVirtFdtDxe (
   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
@@ -320,6 +323,7 @@ InitializeVirtFdtDxe (
   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
@@ -354,6 +358,7 @@ InitializeVirtFdtDxe (
       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
@@ -382,6 +387,19 @@ InitializeVirtFdtDxe (
 \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
@@ -441,6 +459,7 @@ InitializeVirtFdtDxe (
 \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
@@ -470,6 +489,7 @@ InitializeVirtFdtDxe (
 \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
@@ -562,5 +582,28 @@ InitializeVirtFdtDxe (
         "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