WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
**/\r
\r
+#include <Uefi.h>\r
+\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/IoLib.h>\r
-#include <Library/PcdLib.h>\r
#include <Library/QemuFwCfgLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
\r
STATIC UINTN mFwCfgSelectorAddress;\r
STATIC UINTN mFwCfgDataAddress;\r
VOID\r
)\r
{\r
- mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);\r
- mFwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress);\r
+ EFI_STATUS Status;\r
+ FDT_CLIENT_PROTOCOL *FdtClient;\r
+ CONST UINT64 *Reg;\r
+ UINT32 RegElemSize, RegSize;\r
+ UINT64 FwCfgSelectorAddress;\r
+ UINT64 FwCfgSelectorSize;\r
+ UINT64 FwCfgDataAddress;\r
+ UINT64 FwCfgDataSize;\r
+ UINT64 FwCfgDmaAddress;\r
+ UINT64 FwCfgDmaSize;\r
+\r
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
+ (VOID **)&FdtClient);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient, "qemu,fw-cfg-mmio",\r
+ (CONST VOID **)&Reg, &RegElemSize, &RegSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN,\r
+ "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",\r
+ __FUNCTION__, Status));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT (RegElemSize == sizeof (UINT64));\r
+ ASSERT (RegSize == 2 * sizeof (UINT64));\r
+\r
+ FwCfgDataAddress = SwapBytes64 (Reg[0]);\r
+ FwCfgDataSize = 8;\r
+ FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;\r
+ FwCfgSelectorSize = 2;\r
+\r
+ //\r
+ // The following ASSERT()s express\r
+ //\r
+ // Address + Size - 1 <= MAX_UINTN\r
+ //\r
+ // for both registers, that is, that the last byte in each MMIO range is\r
+ // expressible as a MAX_UINTN. The form below is mathematically\r
+ // equivalent, and it also prevents any unsigned overflow before the\r
+ // comparison.\r
+ //\r
+ ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);\r
+ ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);\r
+\r
+ mFwCfgSelectorAddress = FwCfgSelectorAddress;\r
+ mFwCfgDataAddress = FwCfgDataAddress;\r
+\r
+ DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress,\r
+ FwCfgDataAddress));\r
+\r
+ if (SwapBytes64 (Reg[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
+ DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));\r
+ } else {\r
+ FwCfgDmaAddress = 0;\r
+ }\r
\r
if (InternalQemuFwCfgIsAvailable ()) {\r
UINT32 Signature;\r
// For DMA support, we require the DTB to advertise the register, and the\r
// feature bitmap (which we read without DMA) to confirm the feature.\r
//\r
- if (PcdGet64 (PcdFwCfgDmaAddress) != 0) {\r
+ if (FwCfgDmaAddress != 0) {\r
UINT32 Features;\r
\r
QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
Features = QemuFwCfgRead32 ();\r
if ((Features & BIT1) != 0) {\r
- mFwCfgDmaAddress = PcdGet64 (PcdFwCfgDmaAddress);\r
+ mFwCfgDmaAddress = FwCfgDmaAddress;\r
InternalQemuFwCfgReadBytes = DmaReadBytes;\r
}\r
}\r