@@ -20,6 +20,10 @@
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <Library/QemuFwCfgLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <libfdt.h>
+
+#include <Protocol/FdtClient.h>
STATIC UINTN mFwCfgSelectorAddress;
STATIC UINTN mFwCfgDataAddress;
@@ -109,14 +113,70 @@ QemuFwCfgIsAvailable (
}
-RETURN_STATUS
+EFI_STATUS
EFIAPI
QemuFwCfgInitialize (
- VOID
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
)
{
- mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);
- mFwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress);
+ EFI_STATUS Status;
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ CONST VOID *Reg;
+ UINTN RegElemSize, RegSize;
+ UINT64 FwCfgSelectorSize;
+ UINT64 FwCfgDataSize;
+ UINT64 FwCfgDmaSize;
+
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient,
+ "qemu,fw-cfg-mmio",
+ &Reg,
+ &RegElemSize,
+ &RegSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (RegElemSize == sizeof (UINT64));
+ ASSERT (RegSize == 2 * sizeof (UINT64));
+
+ mFwCfgDataAddress = fdt64_to_cpu (((UINT64 *)Reg)[0]);
+ FwCfgDataSize = 8;
+ mFwCfgSelectorAddress = mFwCfgDataAddress + FwCfgDataSize;
+ FwCfgSelectorSize = 2;
+
+ //
+ // The following ASSERT()s express
+ //
+ // Address + Size - 1 <= MAX_UINTN
+ //
+ // for both registers, that is, that the last byte in each MMIO range is
+ // expressible as a MAX_UINTN. The form below is mathematically
+ // equivalent, and it also prevents any unsigned overflow before the
+ // comparison.
+ //
+ ASSERT (mFwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
+ ASSERT (mFwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
+
+ DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", mFwCfgSelectorAddress,
+ mFwCfgDataAddress));
+
+ if (fdt64_to_cpu (((UINT64 *)Reg)[1]) >= 0x18) {
+ mFwCfgDmaAddress = mFwCfgDataAddress + 0x10;
+ FwCfgDmaSize = 0x08;
+
+ //
+ // See explanation above.
+ //
+ ASSERT (mFwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
+
+ DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", mFwCfgDmaAddress));
+ }
if (InternalQemuFwCfgIsAvailable ()) {
UINT32 Signature;
@@ -128,13 +188,12 @@ QemuFwCfgInitialize (
// For DMA support, we require the DTB to advertise the register, and the
// feature bitmap (which we read without DMA) to confirm the feature.
//
- if (PcdGet64 (PcdFwCfgDmaAddress) != 0) {
+ if (mFwCfgDmaAddress != 0) {
UINT32 Features;
QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
Features = QemuFwCfgRead32 ();
if ((Features & BIT1) != 0) {
- mFwCfgDmaAddress = PcdGet64 (PcdFwCfgDmaAddress);
InternalQemuFwCfgReadBytes = DmaReadBytes;
}
}
@@ -143,7 +202,7 @@ QemuFwCfgInitialize (
mFwCfgDataAddress = 0;
}
}
- return RETURN_SUCCESS;
+ return EFI_SUCCESS;
}
@@ -20,7 +20,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = QemuFwCfgLib
FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF
- MODULE_TYPE = BASE
+ MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER
@@ -46,9 +46,9 @@ [LibraryClasses]
BaseMemoryLib
DebugLib
IoLib
- PcdLib
-[Pcd]
- gArmVirtTokenSpaceGuid.PcdFwCfgSelectorAddress
- gArmVirtTokenSpaceGuid.PcdFwCfgDataAddress
- gArmVirtTokenSpaceGuid.PcdFwCfgDmaAddress
+[Protocols]
+ gFdtClientProtocolGuid
+
+[Depex]
+ gFdtClientProtocolGuid
Make this library depend on the FDT client protocol to access the host supplied device tree directly rather than depending on VirtFdtDxe to set them using dynamic PCDs. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 73 ++++++++++++++++++-- ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf | 12 ++-- 2 files changed, 72 insertions(+), 13 deletions(-) -- 2.5.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel