]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtPkg/QemuFwCfgLib: Relocate QemuFwCfgLib to OvmfPkg
authorAbner Chang <abner.chang@hpe.com>
Mon, 11 Oct 2021 13:33:59 +0000 (21:33 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 14 Oct 2021 06:25:52 +0000 (06:25 +0000)
Relocate QemuFwCfgLib to OvmfPkg/Library/QemuFwCfgLib and rename
it to QemuFwCfgLibMmio, this library is leverage by both ARM and
RISC-V archs.

Signed-off-by: Abner Chang <abner.chang@hpe.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Daniel Schaefer <daniel.schaefer@hpe.com>
Cc: Sunil V L <sunilvl@ventanamicro.com>
Reviewed-by: Daniel Schaefer <daniel.schaefer@hpe.com>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <jiewen.yao@intel.com>
ArmVirtPkg/ArmVirtQemu.dsc
ArmVirtPkg/ArmVirtQemuKernel.dsc
ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c [deleted file]
ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf [deleted file]
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c [new file with mode: 0644]
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf [new file with mode: 0644]

index 86417f879758d60cda68891ec8dc7a6f5c0ac8ff..3cca073009f0745bc3a17e47acae055376fb84ab 100644 (file)
@@ -59,7 +59,7 @@
   # Virtio Support\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf\r
-  QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf\r
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf\r
   QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf\r
   QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf\r
index 3fad481e29cf051700c3db741ffda30669ccd848..a42e53b0b1317b26015fa7852a9e477d3726081d 100644 (file)
@@ -57,7 +57,7 @@
   # Virtio Support\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf\r
-  QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf\r
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf\r
   QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf\r
   QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf\r
diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
deleted file mode 100644 (file)
index e2ac410..0000000
+++ /dev/null
@@ -1,633 +0,0 @@
-/** @file\r
-\r
-  Stateful and implicitly initialized fw_cfg library implementation.\r
-\r
-  Copyright (C) 2013 - 2014, Red Hat, Inc.\r
-  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\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/QemuFwCfgLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-\r
-#include <Protocol/FdtClient.h>\r
-\r
-STATIC UINTN mFwCfgSelectorAddress;\r
-STATIC UINTN mFwCfgDataAddress;\r
-STATIC UINTN mFwCfgDmaAddress;\r
-\r
-/**\r
-  Reads firmware configuration bytes into a buffer\r
-\r
-  @param[in] Size    Size in bytes to read\r
-  @param[in] Buffer  Buffer to store data into  (OPTIONAL if Size is 0)\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI READ_BYTES_FUNCTION) (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  );\r
-\r
-/**\r
-  Writes bytes from a buffer to firmware configuration\r
-\r
-  @param[in] Size    Size in bytes to write\r
-  @param[in] Buffer  Buffer to transfer data from (OPTIONAL if Size is 0)\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI WRITE_BYTES_FUNCTION) (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  );\r
-\r
-/**\r
-  Skips bytes in firmware configuration\r
-\r
-  @param[in] Size  Size in bytes to skip\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI SKIP_BYTES_FUNCTION) (\r
-  IN UINTN Size\r
-  );\r
-\r
-//\r
-// Forward declaration of the two implementations we have.\r
-//\r
-STATIC READ_BYTES_FUNCTION MmioReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION MmioWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION MmioSkipBytes;\r
-STATIC READ_BYTES_FUNCTION DmaReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION DmaWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION DmaSkipBytes;\r
-\r
-//\r
-// These correspond to the implementation we detect at runtime.\r
-//\r
-STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;\r
-\r
-\r
-/**\r
-  Returns a boolean indicating if the firmware configuration interface\r
-  is available or not.\r
-\r
-  This function may change fw_cfg state.\r
-\r
-  @retval TRUE   The interface is available\r
-  @retval FALSE  The interface is not available\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-QemuFwCfgIsAvailable (\r
-  VOID\r
-  )\r
-{\r
-  return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);\r
-}\r
-\r
-\r
-RETURN_STATUS\r
-EFIAPI\r
-QemuFwCfgInitialize (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  FDT_CLIENT_PROTOCOL           *FdtClient;\r
-  CONST UINT64                  *Reg;\r
-  UINT32                        RegSize;\r
-  UINTN                         AddressCells, SizeCells;\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, &AddressCells, &SizeCells,\r
-                         &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 (AddressCells == 2);\r
-  ASSERT (SizeCells == 2);\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 (QemuFwCfgIsAvailable ()) {\r
-    UINT32 Signature;\r
-\r
-    QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
-    Signature = QemuFwCfgRead32 ();\r
-    if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {\r
-      //\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 (FwCfgDmaAddress != 0) {\r
-        UINT32 Features;\r
-\r
-        QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
-        Features = QemuFwCfgRead32 ();\r
-        if ((Features & FW_CFG_F_DMA) != 0) {\r
-          mFwCfgDmaAddress = FwCfgDmaAddress;\r
-          InternalQemuFwCfgReadBytes = DmaReadBytes;\r
-          InternalQemuFwCfgWriteBytes = DmaWriteBytes;\r
-          InternalQemuFwCfgSkipBytes = DmaSkipBytes;\r
-        }\r
-      }\r
-    } else {\r
-      mFwCfgSelectorAddress = 0;\r
-      mFwCfgDataAddress     = 0;\r
-    }\r
-  }\r
-  return RETURN_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Selects a firmware configuration item for reading.\r
-\r
-  Following this call, any data read from this item will start from the\r
-  beginning of the configuration item's data.\r
-\r
-  @param[in] QemuFwCfgItem  Firmware Configuration item to read\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgSelectItem (\r
-  IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem\r
-  )\r
-{\r
-  if (QemuFwCfgIsAvailable ()) {\r
-    MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Slow READ_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioReadBytes (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  )\r
-{\r
-  UINTN Left;\r
-  UINT8 *Ptr;\r
-  UINT8 *End;\r
-\r
-#ifdef MDE_CPU_AARCH64\r
-  Left = Size & 7;\r
-#else\r
-  Left = Size & 3;\r
-#endif\r
-\r
-  Size -= Left;\r
-  Ptr = Buffer;\r
-  End = Ptr + Size;\r
-\r
-#ifdef MDE_CPU_AARCH64\r
-  while (Ptr < End) {\r
-    *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);\r
-    Ptr += 8;\r
-  }\r
-  if (Left & 4) {\r
-    *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
-    Ptr += 4;\r
-  }\r
-#else\r
-  while (Ptr < End) {\r
-    *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
-    Ptr += 4;\r
-  }\r
-#endif\r
-\r
-  if (Left & 2) {\r
-    *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);\r
-    Ptr += 2;\r
-  }\r
-  if (Left & 1) {\r
-    *Ptr = MmioRead8 (mFwCfgDataAddress);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Transfer an array of bytes, or skip a number of bytes, using the DMA\r
-  interface.\r
-\r
-  @param[in]     Size     Size in bytes to transfer or skip.\r
-\r
-  @param[in,out] Buffer   Buffer to read data into or write data from. Ignored,\r
-                          and may be NULL, if Size is zero, or Control is\r
-                          FW_CFG_DMA_CTL_SKIP.\r
-\r
-  @param[in]     Control  One of the following:\r
-                          FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.\r
-                          FW_CFG_DMA_CTL_READ  - read from fw_cfg into Buffer.\r
-                          FW_CFG_DMA_CTL_SKIP  - skip bytes in fw_cfg.\r
-**/\r
-STATIC\r
-VOID\r
-DmaTransferBytes (\r
-  IN     UINTN  Size,\r
-  IN OUT VOID   *Buffer OPTIONAL,\r
-  IN     UINT32 Control\r
-  )\r
-{\r
-  volatile FW_CFG_DMA_ACCESS Access;\r
-  UINT32                     Status;\r
-\r
-  ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||\r
-    Control == FW_CFG_DMA_CTL_SKIP);\r
-\r
-  if (Size == 0) {\r
-    return;\r
-  }\r
-\r
-  ASSERT (Size <= MAX_UINT32);\r
-\r
-  Access.Control = SwapBytes32 (Control);\r
-  Access.Length  = SwapBytes32 ((UINT32)Size);\r
-  Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);\r
-\r
-  //\r
-  // We shouldn't start the transfer before setting up Access.\r
-  //\r
-  MemoryFence ();\r
-\r
-  //\r
-  // This will fire off the transfer.\r
-  //\r
-#ifdef MDE_CPU_AARCH64\r
-  MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));\r
-#else\r
-  MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));\r
-#endif\r
-\r
-  //\r
-  // We shouldn't look at Access.Control before starting the transfer.\r
-  //\r
-  MemoryFence ();\r
-\r
-  do {\r
-    Status = SwapBytes32 (Access.Control);\r
-    ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
-  } while (Status != 0);\r
-\r
-  //\r
-  // The caller will want to access the transferred data.\r
-  //\r
-  MemoryFence ();\r
-}\r
-\r
-\r
-/**\r
-  Fast READ_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaReadBytes (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  )\r
-{\r
-  DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_READ);\r
-}\r
-\r
-\r
-/**\r
-  Reads firmware configuration bytes into a buffer\r
-\r
-  If called multiple times, then the data read will continue at the offset of\r
-  the firmware configuration item where the previous read ended.\r
-\r
-  @param[in] Size    Size in bytes to read\r
-  @param[in] Buffer  Buffer to store data into\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgReadBytes (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer\r
-  )\r
-{\r
-  if (QemuFwCfgIsAvailable ()) {\r
-    InternalQemuFwCfgReadBytes (Size, Buffer);\r
-  } else {\r
-    ZeroMem (Buffer, Size);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Slow WRITE_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioWriteBytes (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  )\r
-{\r
-  UINTN Idx;\r
-\r
-  for (Idx = 0; Idx < Size; ++Idx) {\r
-    MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Fast WRITE_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaWriteBytes (\r
-  IN UINTN Size,\r
-  IN VOID  *Buffer OPTIONAL\r
-  )\r
-{\r
-  DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_WRITE);\r
-}\r
-\r
-\r
-/**\r
-  Write firmware configuration bytes from a buffer\r
-\r
-  If called multiple times, then the data written will continue at the offset\r
-  of the firmware configuration item where the previous write ended.\r
-\r
-  @param[in] Size    Size in bytes to write\r
-  @param[in] Buffer  Buffer to read data from\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgWriteBytes (\r
-  IN UINTN                  Size,\r
-  IN VOID                   *Buffer\r
-  )\r
-{\r
-  if (QemuFwCfgIsAvailable ()) {\r
-    InternalQemuFwCfgWriteBytes (Size, Buffer);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Slow SKIP_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioSkipBytes (\r
-  IN UINTN Size\r
-  )\r
-{\r
-  UINTN ChunkSize;\r
-  UINT8 SkipBuffer[256];\r
-\r
-  //\r
-  // Emulate the skip by reading data in chunks, and throwing it away. The\r
-  // implementation below doesn't affect the static data footprint for client\r
-  // modules. Large skips are not expected, therefore this fallback is not\r
-  // performance critical. The size of SkipBuffer is thought not to exert a\r
-  // large pressure on the stack.\r
-  //\r
-  while (Size > 0) {\r
-    ChunkSize = MIN (Size, sizeof SkipBuffer);\r
-    MmioReadBytes (ChunkSize, SkipBuffer);\r
-    Size -= ChunkSize;\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Fast SKIP_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaSkipBytes (\r
-  IN UINTN Size\r
-  )\r
-{\r
-  DmaTransferBytes (Size, NULL, FW_CFG_DMA_CTL_SKIP);\r
-}\r
-\r
-\r
-/**\r
-  Skip bytes in the firmware configuration item.\r
-\r
-  Increase the offset of the firmware configuration item without transferring\r
-  bytes between the item and a caller-provided buffer. Subsequent read, write\r
-  or skip operations will commence at the increased offset.\r
-\r
-  @param[in] Size  Number of bytes to skip.\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgSkipBytes (\r
-  IN UINTN Size\r
-  )\r
-{\r
-  if (QemuFwCfgIsAvailable ()) {\r
-    InternalQemuFwCfgSkipBytes (Size);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Reads a UINT8 firmware configuration value\r
-\r
-  @return  Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT8\r
-EFIAPI\r
-QemuFwCfgRead8 (\r
-  VOID\r
-  )\r
-{\r
-  UINT8 Result;\r
-\r
-  QemuFwCfgReadBytes (sizeof Result, &Result);\r
-  return Result;\r
-}\r
-\r
-\r
-/**\r
-  Reads a UINT16 firmware configuration value\r
-\r
-  @return  Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT16\r
-EFIAPI\r
-QemuFwCfgRead16 (\r
-  VOID\r
-  )\r
-{\r
-  UINT16 Result;\r
-\r
-  QemuFwCfgReadBytes (sizeof Result, &Result);\r
-  return Result;\r
-}\r
-\r
-\r
-/**\r
-  Reads a UINT32 firmware configuration value\r
-\r
-  @return  Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-QemuFwCfgRead32 (\r
-  VOID\r
-  )\r
-{\r
-  UINT32 Result;\r
-\r
-  QemuFwCfgReadBytes (sizeof Result, &Result);\r
-  return Result;\r
-}\r
-\r
-\r
-/**\r
-  Reads a UINT64 firmware configuration value\r
-\r
-  @return  Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-QemuFwCfgRead64 (\r
-  VOID\r
-  )\r
-{\r
-  UINT64 Result;\r
-\r
-  QemuFwCfgReadBytes (sizeof Result, &Result);\r
-  return Result;\r
-}\r
-\r
-\r
-/**\r
-  Find the configuration item corresponding to the firmware configuration file.\r
-\r
-  @param[in]  Name  Name of file to look up.\r
-  @param[out] Item  Configuration item corresponding to the file, to be passed\r
-                    to QemuFwCfgSelectItem ().\r
-  @param[out] Size  Number of bytes in the file.\r
-\r
-  @retval RETURN_SUCCESS      If file is found.\r
-  @retval RETURN_NOT_FOUND    If file is not found.\r
-  @retval RETURN_UNSUPPORTED  If firmware configuration is unavailable.\r
-\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-QemuFwCfgFindFile (\r
-  IN   CONST CHAR8           *Name,\r
-  OUT  FIRMWARE_CONFIG_ITEM  *Item,\r
-  OUT  UINTN                 *Size\r
-  )\r
-{\r
-  UINT32 Count;\r
-  UINT32 Idx;\r
-\r
-  if (!QemuFwCfgIsAvailable ()) {\r
-    return RETURN_UNSUPPORTED;\r
-  }\r
-\r
-  QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
-  Count = SwapBytes32 (QemuFwCfgRead32 ());\r
-\r
-  for (Idx = 0; Idx < Count; ++Idx) {\r
-    UINT32 FileSize;\r
-    UINT16 FileSelect;\r
-    CHAR8  FName[QEMU_FW_CFG_FNAME_SIZE];\r
-\r
-    FileSize   = QemuFwCfgRead32 ();\r
-    FileSelect = QemuFwCfgRead16 ();\r
-    QemuFwCfgRead16 (); // skip the field called "reserved"\r
-    InternalQemuFwCfgReadBytes (sizeof (FName), FName);\r
-\r
-    if (AsciiStrCmp (Name, FName) == 0) {\r
-      *Item = (FIRMWARE_CONFIG_ITEM) SwapBytes16 (FileSelect);\r
-      *Size = SwapBytes32 (FileSize);\r
-      return RETURN_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return RETURN_NOT_FOUND;\r
-}\r
diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
deleted file mode 100644 (file)
index f3cc827..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-## @file\r
-#\r
-#  Stateful, implicitly initialized fw_cfg library.\r
-#\r
-#  Copyright (C) 2013 - 2014, Red Hat, Inc.\r
-#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-#\r
-#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
-  INF_VERSION                    = 0x00010005\r
-  BASE_NAME                      = QemuFwCfgLib\r
-  FILE_GUID                      = B271F41F-B841-48A9-BA8D-545B4BC2E2BF\r
-  MODULE_TYPE                    = BASE\r
-  VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = QemuFwCfgLib|DXE_DRIVER UEFI_DRIVER\r
-\r
-  CONSTRUCTOR                    = QemuFwCfgInitialize\r
-\r
-#\r
-# The following information is for reference only and not required by the build\r
-# tools.\r
-#\r
-#  VALID_ARCHITECTURES           = ARM AARCH64\r
-#\r
-\r
-[Sources]\r
-  QemuFwCfgLib.c\r
-\r
-[Packages]\r
-  MdePkg/MdePkg.dec\r
-  OvmfPkg/OvmfPkg.dec\r
-  EmbeddedPkg/EmbeddedPkg.dec\r
-  ArmVirtPkg/ArmVirtPkg.dec\r
-\r
-[LibraryClasses]\r
-  BaseLib\r
-  BaseMemoryLib\r
-  DebugLib\r
-  IoLib\r
-  UefiBootServicesTableLib\r
-\r
-[Protocols]\r
-  gFdtClientProtocolGuid                                ## CONSUMES\r
-\r
-[Depex]\r
-  gFdtClientProtocolGuid\r
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c
new file mode 100644 (file)
index 0000000..e2ac410
--- /dev/null
@@ -0,0 +1,633 @@
+/** @file\r
+\r
+  Stateful and implicitly initialized fw_cfg library implementation.\r
+\r
+  Copyright (C) 2013 - 2014, Red Hat, Inc.\r
+  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\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/QemuFwCfgLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
+\r
+STATIC UINTN mFwCfgSelectorAddress;\r
+STATIC UINTN mFwCfgDataAddress;\r
+STATIC UINTN mFwCfgDmaAddress;\r
+\r
+/**\r
+  Reads firmware configuration bytes into a buffer\r
+\r
+  @param[in] Size    Size in bytes to read\r
+  @param[in] Buffer  Buffer to store data into  (OPTIONAL if Size is 0)\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI READ_BYTES_FUNCTION) (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  );\r
+\r
+/**\r
+  Writes bytes from a buffer to firmware configuration\r
+\r
+  @param[in] Size    Size in bytes to write\r
+  @param[in] Buffer  Buffer to transfer data from (OPTIONAL if Size is 0)\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI WRITE_BYTES_FUNCTION) (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  );\r
+\r
+/**\r
+  Skips bytes in firmware configuration\r
+\r
+  @param[in] Size  Size in bytes to skip\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI SKIP_BYTES_FUNCTION) (\r
+  IN UINTN Size\r
+  );\r
+\r
+//\r
+// Forward declaration of the two implementations we have.\r
+//\r
+STATIC READ_BYTES_FUNCTION MmioReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION MmioWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION MmioSkipBytes;\r
+STATIC READ_BYTES_FUNCTION DmaReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION DmaWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION DmaSkipBytes;\r
+\r
+//\r
+// These correspond to the implementation we detect at runtime.\r
+//\r
+STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;\r
+\r
+\r
+/**\r
+  Returns a boolean indicating if the firmware configuration interface\r
+  is available or not.\r
+\r
+  This function may change fw_cfg state.\r
+\r
+  @retval TRUE   The interface is available\r
+  @retval FALSE  The interface is not available\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QemuFwCfgIsAvailable (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);\r
+}\r
+\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+QemuFwCfgInitialize (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  FDT_CLIENT_PROTOCOL           *FdtClient;\r
+  CONST UINT64                  *Reg;\r
+  UINT32                        RegSize;\r
+  UINTN                         AddressCells, SizeCells;\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, &AddressCells, &SizeCells,\r
+                         &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 (AddressCells == 2);\r
+  ASSERT (SizeCells == 2);\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 (QemuFwCfgIsAvailable ()) {\r
+    UINT32 Signature;\r
+\r
+    QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
+    Signature = QemuFwCfgRead32 ();\r
+    if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {\r
+      //\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 (FwCfgDmaAddress != 0) {\r
+        UINT32 Features;\r
+\r
+        QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
+        Features = QemuFwCfgRead32 ();\r
+        if ((Features & FW_CFG_F_DMA) != 0) {\r
+          mFwCfgDmaAddress = FwCfgDmaAddress;\r
+          InternalQemuFwCfgReadBytes = DmaReadBytes;\r
+          InternalQemuFwCfgWriteBytes = DmaWriteBytes;\r
+          InternalQemuFwCfgSkipBytes = DmaSkipBytes;\r
+        }\r
+      }\r
+    } else {\r
+      mFwCfgSelectorAddress = 0;\r
+      mFwCfgDataAddress     = 0;\r
+    }\r
+  }\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Selects a firmware configuration item for reading.\r
+\r
+  Following this call, any data read from this item will start from the\r
+  beginning of the configuration item's data.\r
+\r
+  @param[in] QemuFwCfgItem  Firmware Configuration item to read\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgSelectItem (\r
+  IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem\r
+  )\r
+{\r
+  if (QemuFwCfgIsAvailable ()) {\r
+    MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Slow READ_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioReadBytes (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  )\r
+{\r
+  UINTN Left;\r
+  UINT8 *Ptr;\r
+  UINT8 *End;\r
+\r
+#ifdef MDE_CPU_AARCH64\r
+  Left = Size & 7;\r
+#else\r
+  Left = Size & 3;\r
+#endif\r
+\r
+  Size -= Left;\r
+  Ptr = Buffer;\r
+  End = Ptr + Size;\r
+\r
+#ifdef MDE_CPU_AARCH64\r
+  while (Ptr < End) {\r
+    *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);\r
+    Ptr += 8;\r
+  }\r
+  if (Left & 4) {\r
+    *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
+    Ptr += 4;\r
+  }\r
+#else\r
+  while (Ptr < End) {\r
+    *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
+    Ptr += 4;\r
+  }\r
+#endif\r
+\r
+  if (Left & 2) {\r
+    *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);\r
+    Ptr += 2;\r
+  }\r
+  if (Left & 1) {\r
+    *Ptr = MmioRead8 (mFwCfgDataAddress);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Transfer an array of bytes, or skip a number of bytes, using the DMA\r
+  interface.\r
+\r
+  @param[in]     Size     Size in bytes to transfer or skip.\r
+\r
+  @param[in,out] Buffer   Buffer to read data into or write data from. Ignored,\r
+                          and may be NULL, if Size is zero, or Control is\r
+                          FW_CFG_DMA_CTL_SKIP.\r
+\r
+  @param[in]     Control  One of the following:\r
+                          FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.\r
+                          FW_CFG_DMA_CTL_READ  - read from fw_cfg into Buffer.\r
+                          FW_CFG_DMA_CTL_SKIP  - skip bytes in fw_cfg.\r
+**/\r
+STATIC\r
+VOID\r
+DmaTransferBytes (\r
+  IN     UINTN  Size,\r
+  IN OUT VOID   *Buffer OPTIONAL,\r
+  IN     UINT32 Control\r
+  )\r
+{\r
+  volatile FW_CFG_DMA_ACCESS Access;\r
+  UINT32                     Status;\r
+\r
+  ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||\r
+    Control == FW_CFG_DMA_CTL_SKIP);\r
+\r
+  if (Size == 0) {\r
+    return;\r
+  }\r
+\r
+  ASSERT (Size <= MAX_UINT32);\r
+\r
+  Access.Control = SwapBytes32 (Control);\r
+  Access.Length  = SwapBytes32 ((UINT32)Size);\r
+  Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);\r
+\r
+  //\r
+  // We shouldn't start the transfer before setting up Access.\r
+  //\r
+  MemoryFence ();\r
+\r
+  //\r
+  // This will fire off the transfer.\r
+  //\r
+#ifdef MDE_CPU_AARCH64\r
+  MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));\r
+#else\r
+  MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));\r
+#endif\r
+\r
+  //\r
+  // We shouldn't look at Access.Control before starting the transfer.\r
+  //\r
+  MemoryFence ();\r
+\r
+  do {\r
+    Status = SwapBytes32 (Access.Control);\r
+    ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
+  } while (Status != 0);\r
+\r
+  //\r
+  // The caller will want to access the transferred data.\r
+  //\r
+  MemoryFence ();\r
+}\r
+\r
+\r
+/**\r
+  Fast READ_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaReadBytes (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  )\r
+{\r
+  DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_READ);\r
+}\r
+\r
+\r
+/**\r
+  Reads firmware configuration bytes into a buffer\r
+\r
+  If called multiple times, then the data read will continue at the offset of\r
+  the firmware configuration item where the previous read ended.\r
+\r
+  @param[in] Size    Size in bytes to read\r
+  @param[in] Buffer  Buffer to store data into\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgReadBytes (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer\r
+  )\r
+{\r
+  if (QemuFwCfgIsAvailable ()) {\r
+    InternalQemuFwCfgReadBytes (Size, Buffer);\r
+  } else {\r
+    ZeroMem (Buffer, Size);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Slow WRITE_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioWriteBytes (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  )\r
+{\r
+  UINTN Idx;\r
+\r
+  for (Idx = 0; Idx < Size; ++Idx) {\r
+    MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Fast WRITE_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaWriteBytes (\r
+  IN UINTN Size,\r
+  IN VOID  *Buffer OPTIONAL\r
+  )\r
+{\r
+  DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_WRITE);\r
+}\r
+\r
+\r
+/**\r
+  Write firmware configuration bytes from a buffer\r
+\r
+  If called multiple times, then the data written will continue at the offset\r
+  of the firmware configuration item where the previous write ended.\r
+\r
+  @param[in] Size    Size in bytes to write\r
+  @param[in] Buffer  Buffer to read data from\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgWriteBytes (\r
+  IN UINTN                  Size,\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  if (QemuFwCfgIsAvailable ()) {\r
+    InternalQemuFwCfgWriteBytes (Size, Buffer);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Slow SKIP_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioSkipBytes (\r
+  IN UINTN Size\r
+  )\r
+{\r
+  UINTN ChunkSize;\r
+  UINT8 SkipBuffer[256];\r
+\r
+  //\r
+  // Emulate the skip by reading data in chunks, and throwing it away. The\r
+  // implementation below doesn't affect the static data footprint for client\r
+  // modules. Large skips are not expected, therefore this fallback is not\r
+  // performance critical. The size of SkipBuffer is thought not to exert a\r
+  // large pressure on the stack.\r
+  //\r
+  while (Size > 0) {\r
+    ChunkSize = MIN (Size, sizeof SkipBuffer);\r
+    MmioReadBytes (ChunkSize, SkipBuffer);\r
+    Size -= ChunkSize;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Fast SKIP_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaSkipBytes (\r
+  IN UINTN Size\r
+  )\r
+{\r
+  DmaTransferBytes (Size, NULL, FW_CFG_DMA_CTL_SKIP);\r
+}\r
+\r
+\r
+/**\r
+  Skip bytes in the firmware configuration item.\r
+\r
+  Increase the offset of the firmware configuration item without transferring\r
+  bytes between the item and a caller-provided buffer. Subsequent read, write\r
+  or skip operations will commence at the increased offset.\r
+\r
+  @param[in] Size  Number of bytes to skip.\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgSkipBytes (\r
+  IN UINTN Size\r
+  )\r
+{\r
+  if (QemuFwCfgIsAvailable ()) {\r
+    InternalQemuFwCfgSkipBytes (Size);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Reads a UINT8 firmware configuration value\r
+\r
+  @return  Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+QemuFwCfgRead8 (\r
+  VOID\r
+  )\r
+{\r
+  UINT8 Result;\r
+\r
+  QemuFwCfgReadBytes (sizeof Result, &Result);\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Reads a UINT16 firmware configuration value\r
+\r
+  @return  Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+QemuFwCfgRead16 (\r
+  VOID\r
+  )\r
+{\r
+  UINT16 Result;\r
+\r
+  QemuFwCfgReadBytes (sizeof Result, &Result);\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Reads a UINT32 firmware configuration value\r
+\r
+  @return  Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+QemuFwCfgRead32 (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 Result;\r
+\r
+  QemuFwCfgReadBytes (sizeof Result, &Result);\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Reads a UINT64 firmware configuration value\r
+\r
+  @return  Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+QemuFwCfgRead64 (\r
+  VOID\r
+  )\r
+{\r
+  UINT64 Result;\r
+\r
+  QemuFwCfgReadBytes (sizeof Result, &Result);\r
+  return Result;\r
+}\r
+\r
+\r
+/**\r
+  Find the configuration item corresponding to the firmware configuration file.\r
+\r
+  @param[in]  Name  Name of file to look up.\r
+  @param[out] Item  Configuration item corresponding to the file, to be passed\r
+                    to QemuFwCfgSelectItem ().\r
+  @param[out] Size  Number of bytes in the file.\r
+\r
+  @retval RETURN_SUCCESS      If file is found.\r
+  @retval RETURN_NOT_FOUND    If file is not found.\r
+  @retval RETURN_UNSUPPORTED  If firmware configuration is unavailable.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+QemuFwCfgFindFile (\r
+  IN   CONST CHAR8           *Name,\r
+  OUT  FIRMWARE_CONFIG_ITEM  *Item,\r
+  OUT  UINTN                 *Size\r
+  )\r
+{\r
+  UINT32 Count;\r
+  UINT32 Idx;\r
+\r
+  if (!QemuFwCfgIsAvailable ()) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
+  Count = SwapBytes32 (QemuFwCfgRead32 ());\r
+\r
+  for (Idx = 0; Idx < Count; ++Idx) {\r
+    UINT32 FileSize;\r
+    UINT16 FileSelect;\r
+    CHAR8  FName[QEMU_FW_CFG_FNAME_SIZE];\r
+\r
+    FileSize   = QemuFwCfgRead32 ();\r
+    FileSelect = QemuFwCfgRead16 ();\r
+    QemuFwCfgRead16 (); // skip the field called "reserved"\r
+    InternalQemuFwCfgReadBytes (sizeof (FName), FName);\r
+\r
+    if (AsciiStrCmp (Name, FName) == 0) {\r
+      *Item = (FIRMWARE_CONFIG_ITEM) SwapBytes16 (FileSelect);\r
+      *Size = SwapBytes32 (FileSize);\r
+      return RETURN_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return RETURN_NOT_FOUND;\r
+}\r
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
new file mode 100644 (file)
index 0000000..6753151
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+#\r
+#  Stateful, implicitly initialized fw_cfg library.\r
+#\r
+#  Copyright (C) 2013 - 2014, Red Hat, Inc.\r
+#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = QemuFwCfgLib\r
+  FILE_GUID                      = B271F41F-B841-48A9-BA8D-545B4BC2E2BF\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = QemuFwCfgLib|DXE_DRIVER UEFI_DRIVER\r
+\r
+  CONSTRUCTOR                    = QemuFwCfgInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+#  VALID_ARCHITECTURES           = ARM AARCH64\r
+#\r
+\r
+[Sources]\r
+  QemuFwCfgLibMmio.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  IoLib\r
+  UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+  gFdtClientProtocolGuid                                ## CONSUMES\r
+\r
+[Depex]\r
+  gFdtClientProtocolGuid\r