public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "xianglai" <lixianglai@loongson.cn>
To: devel@edk2.groups.io
Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com,
	maobibo@loongson.cn
Subject: [edk2-platforms][PATCH V2 04/16] Platform/Loongson: Add QemuFwCfgLib.
Date: Fri, 16 Sep 2022 11:36:21 +0800	[thread overview]
Message-ID: <345a9df259f592aba9b1518b0bdce4eb03a0ad07.1663298005.git.lixianglai@loongson.cn> (raw)
In-Reply-To: <cover.1663298005.git.lixianglai@loongson.cn>

QemuFwCfgLib for PEI phase.
This library obtains the QemuFWCfg base address by
directly parsing the fdt, and reads and writes the data
in the QemuFWCfg by operating on the QemuFWCfg base address.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054

Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
 .../Include/IndustryStandard/QemuFwCfg.h      |  95 ++++
 .../Include/Library/QemuFwCfgLib.h            | 193 +++++++
 .../QemuFwCfgLib/QemuFwCfgLibInternal.h       |  64 +++
 .../Library/QemuFwCfgLib/QemuFwCfgPei.c       | 119 +++++
 .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.c    | 477 ++++++++++++++++++
 .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf  |  44 ++
 6 files changed, 992 insertions(+)
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg.h
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.c
 create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf

diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg.h b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg.h
new file mode 100644
index 0000000000..a028ca1124
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg.h
@@ -0,0 +1,95 @@
+/** @file
+  Macro and type definitions corresponding to the QEMU fw_cfg interface.
+
+  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - FW     - FireWare
+    - CFG    - Configure
+    - FNAME    - File Name
+    - CTL    - Contorl
+**/
+
+#ifndef QEMU_FW_CFG_H_
+#define QEMU_FW_CFG_H_
+
+#include <Base.h>
+
+//
+// The size, in bytes, of names of firmware configuration files, including at
+// least one terminating NUL byte.
+//
+#define QEMU_FW_CFG_FNAME_SIZE      56
+
+//
+// If the following bit is set in the UINT32 fw_cfg revision / feature bitmap
+// -- read from key 0x0001 with the basic IO Port or MMIO method --, then the
+// DMA interface is available.
+//
+#define FW_CFG_F_DMA BIT1
+
+//
+// Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).
+//
+#define FW_CFG_DMA_CTL_ERROR         BIT0
+#define FW_CFG_DMA_CTL_READ          BIT1
+#define FW_CFG_DMA_CTL_SKIP          BIT2
+#define FW_CFG_DMA_CTL_SELECT        BIT3
+#define FW_CFG_DMA_CTL_WRITE         BIT4
+
+//
+// The fw_cfg registers can be found at these IO Ports, on the IO-mapped
+// platforms (Ia32 and X64).
+//
+#define FW_CFG_IO_SELECTOR          0x510
+#define FW_CFG_IO_DATA              0x511
+#define FW_CFG_IO_DMA_ADDRESS       0x514
+
+//
+// Numerically defined keys.
+//
+typedef enum {
+  QemuFwCfgItemSignature            = 0x0000,
+  QemuFwCfgItemInterfaceVersion     = 0x0001,
+  QemuFwCfgItemSystemUuid           = 0x0002,
+  QemuFwCfgItemRamSize              = 0x0003,
+  QemuFwCfgItemGraphicsEnabled      = 0x0004,
+  QemuFwCfgItemSmpCpuCount          = 0x0005,
+  QemuFwCfgItemMachineId            = 0x0006,
+  QemuFwCfgItemKernelAddress        = 0x0007,
+  QemuFwCfgItemKernelSize           = 0x0008,
+  QemuFwCfgItemKernelCommandLine    = 0x0009,
+  QemuFwCfgItemInitrdAddress        = 0x000a,
+  QemuFwCfgItemInitrdSize           = 0x000b,
+  QemuFwCfgItemBootDevice           = 0x000c,
+  QemuFwCfgItemNumaData             = 0x000d,
+  QemuFwCfgItemBootMenu             = 0x000e,
+  QemuFwCfgItemMaximumCpuCount      = 0x000f,
+  QemuFwCfgItemKernelEntry          = 0x0010,
+  QemuFwCfgItemKernelData           = 0x0011,
+  QemuFwCfgItemInitrdData           = 0x0012,
+  QemuFwCfgItemCommandLineAddress   = 0x0013,
+  QemuFwCfgItemCommandLineSize      = 0x0014,
+  QemuFwCfgItemCommandLineData      = 0x0015,
+  QemuFwCfgItemKernelSetupAddress   = 0x0016,
+  QemuFwCfgItemKernelSetupSize      = 0x0017,
+  QemuFwCfgItemKernelSetupData      = 0x0018,
+  QemuFwCfgItemFileDir              = 0x0019,
+
+} FIRMWARE_CONFIG_ITEM;
+
+//
+// Communication structure for the DMA access method. All fields are encoded in
+// big endian.
+//
+#pragma pack (1)
+typedef struct {
+  UINT32 Control;
+  UINT32 Length;
+  UINT64 Address;
+} FW_CFG_DMA_ACCESS;
+#pragma pack ()
+
+#endif
diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h
new file mode 100644
index 0000000000..6b42cf3073
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h
@@ -0,0 +1,193 @@
+/** @file
+  QEMU/KVM Firmware Configuration access
+
+  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - FW or Fw    - Firmware
+    - Cfg         - Configure
+**/
+
+#ifndef QEMU_FW_CFG_LIB_
+#define QEMU_FW_CFG_LIB_
+
+#include <IndustryStandard/QemuFwCfg.h>
+
+typedef enum {
+  EfiAcpiAddressRangeMemory   = 1,
+  EfiAcpiAddressRangeReserved = 2,
+  EfiAcpiAddressRangeACPI     = 3,
+  EfiAcpiAddressRangeNVS      = 4
+} EFI_ACPI_MEMORY_TYPE;
+
+typedef struct {
+  UINT64  BaseAddr;
+  UINT64  Length;
+  UINT32  Type;
+  UINT32  Reserved;
+} LOONGARCH_MEMMAP_ENTRY;
+
+/**
+  Returns a boolean indicating if the firmware configuration interface
+  is available or not.
+
+  This function may change fw_cfg state.
+
+  @retval    TRUE   The interface is available
+  @retval    FALSE  The interface is not available
+
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgIsAvailable (
+  VOID
+  );
+
+
+/**
+  Selects a firmware configuration item for reading.
+
+  Following this call, any data read from this item will start from
+  the beginning of the configuration item's data.
+
+  @param[in] QemuFwCfgItem - Firmware Configuration item to read
+
+**/
+VOID
+EFIAPI
+QemuFwCfgSelectItem (
+  IN FIRMWARE_CONFIG_ITEM   QemuFwCfgItem
+  );
+
+
+/**
+  Reads firmware configuration bytes into a buffer
+
+  If called multiple times, then the data read will
+  continue at the offset of the firmware configuration
+  item where the previous read ended.
+
+  @param[in] Size - Size in bytes to read
+  @param[in] Buffer - Buffer to store data into
+
+**/
+VOID
+EFIAPI
+QemuFwCfgReadBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer  OPTIONAL
+  );
+
+
+/**
+  Writes firmware configuration bytes from a buffer
+
+  If called multiple times, then the data written will
+  continue at the offset of the firmware configuration
+  item where the previous write ended.
+
+  @param[in] Size - Size in bytes to write
+  @param[in] Buffer - Buffer to read data from
+
+**/
+VOID
+EFIAPI
+QemuFwCfgWriteBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  );
+
+
+/**
+  Skip bytes in the firmware configuration item.
+
+  Increase the offset of the firmware configuration item without transferring
+  bytes between the item and a caller-provided buffer. Subsequent read, write
+  or skip operations will commence at the increased offset.
+
+  @param[in] Size  Number of bytes to skip.
+**/
+VOID
+EFIAPI
+QemuFwCfgSkipBytes (
+  IN UINTN                  Size
+  );
+
+
+/**
+  Reads a UINT8 firmware configuration value
+
+  @retval    Value of Firmware Configuration item read
+
+**/
+UINT8
+EFIAPI
+QemuFwCfgRead8 (
+  VOID
+  );
+
+
+/**
+  Reads a UINT16 firmware configuration value
+
+  @retval    Value of Firmware Configuration item read
+
+**/
+UINT16
+EFIAPI
+QemuFwCfgRead16 (
+  VOID
+  );
+
+
+/**
+  Reads a UINT32 firmware configuration value
+
+  @retval    Value of Firmware Configuration item read
+
+**/
+UINT32
+EFIAPI
+QemuFwCfgRead32 (
+  VOID
+  );
+
+
+/**
+  Reads a UINT64 firmware configuration value
+
+  @retval    Value of Firmware Configuration item read
+
+**/
+UINT64
+EFIAPI
+QemuFwCfgRead64 (
+  VOID
+  );
+
+
+/**
+  Find the configuration item corresponding to the firmware configuration file.
+
+  @param[in]  Name - Name of file to look up.
+  @param[out] Item - Configuration item corresponding to the file, to be passed
+                     to QemuFwCfgSelectItem ().
+  @param[out] Size - Number of bytes in the file.
+
+  @retval    RETURN_SUCCESS       If file is found.
+             RETURN_NOT_FOUND     If file is not found.
+             RETURN_UNSUPPORTED   If firmware configuration is unavailable.
+
+**/
+RETURN_STATUS
+EFIAPI
+QemuFwCfgFindFile (
+  IN   CONST CHAR8           *Name,
+  OUT  FIRMWARE_CONFIG_ITEM  *Item,
+  OUT  UINTN                 *Size
+  );
+
+#endif
+
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
new file mode 100644
index 0000000000..33eeb927dd
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
@@ -0,0 +1,64 @@
+/** @file
+  fw_cfg library implementation.
+
+  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - FwCfg   - firmWare  Configure
+**/
+
+#ifndef QEMU_FW_CFG_LIB_INTERNAL_H_
+#define QEMU_FW_CFG_LIB_INTERNAL_H_
+
+/**
+  Returns a boolean indicating if the firmware configuration interface is
+  available for library-internal purposes.
+
+  This function never changes fw_cfg state.
+
+  @retval    TRUE   The interface is available internally.
+  @retval    FALSE  The interface is not available internally.
+**/
+BOOLEAN
+InternalQemuFwCfgIsAvailable (
+  VOID
+  );
+
+
+/**
+  Returns a boolean indicating whether QEMU provides the DMA-like access method
+  for fw_cfg.
+
+  @retval    TRUE   The DMA-like access method is available.
+  @retval    FALSE  The DMA-like access method is unavailable.
+**/
+BOOLEAN
+InternalQemuFwCfgDmaIsAvailable (
+  VOID
+  );
+
+/**
+  Transfer an array of bytes, or skip a number of bytes, using the DMA
+  interface.
+
+  @param[in]     Size     Size in bytes to transfer or skip.
+
+  @param[in,out] Buffer   Buffer to read data into or write data from. Ignored,
+                          and may be NULL, if Size is zero, or Control is
+                          FW_CFG_DMA_CTL_SKIP.
+
+  @param[in]     Control  One of the following:
+                          FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+                          FW_CFG_DMA_CTL_READ  - read from fw_cfg into Buffer.
+                          FW_CFG_DMA_CTL_SKIP  - skip bytes in fw_cfg.
+**/
+VOID
+InternalQemuFwCfgDmaBytes (
+  IN     UINT32   Size,
+  IN OUT VOID     *Buffer OPTIONAL,
+  IN     UINT32   Control
+  );
+
+#endif
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
new file mode 100644
index 0000000000..91995c90b5
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
@@ -0,0 +1,119 @@
+/** @file
+  fw_cfg library implementation.
+
+  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - FwCfg   - firmWare  Configure
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/QemuFwCfgLib.h>
+
+#include "QemuFwCfgLibInternal.h"
+
+/**
+  Returns a boolean indicating if the firmware configuration interface
+  is available or not.
+
+  This function may change fw_cfg state.
+
+  @retval    TRUE   The interface is available
+  @retval    FALSE  The interface is not available
+
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgIsAvailable (
+  VOID
+  )
+{
+  UINT32 Signature;
+  UINT32 Revision;
+
+  QemuFwCfgSelectItem (QemuFwCfgItemSignature);
+  Signature = QemuFwCfgRead32 ();
+  DEBUG ((DEBUG_INFO, "FW CFG Signature: 0x%x\n", Signature));
+  QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
+  Revision = QemuFwCfgRead32 ();
+  DEBUG ((DEBUG_INFO, "FW CFG Revision: 0x%x\n", Revision));
+  if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U'))
+    || (Revision < 1))
+  {
+    DEBUG ((DEBUG_INFO, "QemuFwCfg interface not supported.\n"));
+    return FALSE;
+  }
+
+  DEBUG ((DEBUG_INFO, "QemuFwCfg interface is supported.\n"));
+  return TRUE;
+}
+
+
+/**
+  Returns a boolean indicating if the firmware configuration interface is
+  available for library-internal purposes.
+
+  This function never changes fw_cfg state.
+
+  @retval    TRUE   The interface is available internally.
+  @retval    FALSE  The interface is not available internally.
+**/
+BOOLEAN
+InternalQemuFwCfgIsAvailable (
+  VOID
+  )
+{
+  //
+  // We always return TRUE, because the consumer of this library ought to have
+  // called QemuFwCfgIsAvailable before making other calls which would hit this
+  // path.
+  //
+  return TRUE;
+}
+
+/**
+  Returns a boolean indicating whether QEMU provides the DMA-like access method
+  for fw_cfg.
+
+  @retval    TRUE   The DMA-like access method is available.
+  @retval    FALSE  The DMA-like access method is unavailable.
+**/
+BOOLEAN
+InternalQemuFwCfgDmaIsAvailable (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+/**
+  Transfer an array of bytes, or skip a number of bytes, using the DMA
+  interface.
+
+  @param[in]     Size     Size in bytes to transfer or skip.
+
+  @param[in, out] Buffer   Buffer to read data into or write data from. Ignored,
+                          and may be NULL, if Size is zero, or Control is
+                          FW_CFG_DMA_CTL_SKIP.
+
+  @param[in]     Control  One of the following:
+                          FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+                          FW_CFG_DMA_CTL_READ  - read from fw_cfg into Buffer.
+                          FW_CFG_DMA_CTL_SKIP  - skip bytes in fw_cfg.
+**/
+VOID
+InternalQemuFwCfgDmaBytes (
+  IN     UINT32   Size,
+  IN OUT VOID     *Buffer OPTIONAL,
+  IN     UINT32   Control
+  )
+{
+  //
+  // We should never reach here
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.c
new file mode 100644
index 0000000000..2bbaa9ed35
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.c
@@ -0,0 +1,477 @@
+/** @file
+
+  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - FwCfg   - firmWare  Configure
+    - CTL   - Control
+**/
+
+#include "Uefi.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <libfdt.h>
+#include "QemuFwCfgLibInternal.h"
+
+STATIC UINTN mFwCfgSelectorAddress;
+STATIC UINTN mFwCfgDataAddress;
+/**
+  To get firmware configure selector address.
+
+  @param VOID
+
+  @retval  firmware configure selector address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgSelectorAddress (
+  VOID
+  )
+{
+  UINTN FwCfgSelectorAddress = mFwCfgSelectorAddress;
+  if (FwCfgSelectorAddress == 0) {
+    FwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);
+  }
+  return FwCfgSelectorAddress;
+}
+/**
+  To get firmware configure Data address.
+
+  @param VOID
+
+  @retval  firmware configure data address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDataAddress (
+  VOID
+  )
+{
+  UINTN FwCfgDataAddress = mFwCfgDataAddress;
+  if (FwCfgDataAddress == 0) {
+    FwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress);
+  }
+  return FwCfgDataAddress;
+}
+/**
+  Selects a firmware configuration item for reading.
+
+  Following this call, any data read from this item will start from
+  the beginning of the configuration item's data.
+
+  @param[in] QemuFwCfgItem - Firmware Configuration item to read
+
+**/
+VOID
+EFIAPI
+QemuFwCfgSelectItem (
+  IN FIRMWARE_CONFIG_ITEM   QemuFwCfgItem
+  )
+{
+  UINTN FwCfgSelectorAddress;
+  FwCfgSelectorAddress = QemuGetFwCfgSelectorAddress ();
+  MmioWrite16 (FwCfgSelectorAddress, SwapBytes16((UINT16) (UINTN)QemuFwCfgItem));
+}
+
+/**
+  Slow READ_BYTES_FUNCTION.
+
+  @param[in]  The size of the data to be read.
+  @param[in]  Buffer    The buffer that stores the readout data.
+**/
+VOID
+EFIAPI
+MmioReadBytes (
+  IN UINTN Size,
+  IN VOID  *Buffer OPTIONAL
+  )
+{
+  UINTN Left;
+  UINT8 *Ptr;
+  UINT8 *End;
+  UINTN FwCfgDataAddress;
+  Left = Size & 7;
+
+  Size -= Left;
+  Ptr = Buffer;
+  End = Ptr + Size;
+  FwCfgDataAddress = QemuGetFwCfgDataAddress ();
+  while (Ptr < End) {
+    *(UINT64 *)Ptr = MmioRead64 (FwCfgDataAddress);
+    Ptr += 8;
+  }
+  if (Left & 4) {
+    *(UINT32 *)Ptr = MmioRead32 (FwCfgDataAddress);
+    Ptr += 4;
+  }
+  if (Left & 2) {
+    *(UINT16 *)Ptr = MmioRead16 (FwCfgDataAddress);
+    Ptr += 2;
+  }
+  if (Left & 1) {
+    *Ptr = MmioRead8 (FwCfgDataAddress);
+  }
+}
+
+/**
+  Slow WRITE_BYTES_FUNCTION.
+
+  @param[in]  The size of the data to be write.
+  @param[in]  Buffer    The buffer that stores the writein data.
+**/
+VOID
+EFIAPI
+MmioWriteBytes (
+  IN UINTN Size,
+  IN VOID  *Buffer OPTIONAL
+  )
+{
+  UINTN Idx;
+  UINTN FwCfgDataAddress;
+  FwCfgDataAddress = QemuGetFwCfgDataAddress ();
+  for (Idx = 0; Idx < Size; ++Idx) {
+    MmioWrite8 (FwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);
+  }
+}
+
+/**
+  Reads firmware configuration bytes into a buffer
+
+  @param[in] Size - Size in bytes to read
+  @param[in] Buffer - Buffer to store data into  (OPTIONAL if Size is 0)
+
+**/
+VOID
+EFIAPI
+InternalQemuFwCfgReadBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer  OPTIONAL
+  )
+{
+  if ((InternalQemuFwCfgDmaIsAvailable ())
+    && (Size <= MAX_UINT32))
+  {
+    InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ);
+    return;
+  }
+  MmioReadBytes (Size, Buffer);
+}
+
+
+/**
+  Reads firmware configuration bytes into a buffer
+
+  If called multiple times, then the data read will
+  continue at the offset of the firmware configuration
+  item where the previous read ended.
+
+  @param[in] Size - Size in bytes to read
+  @param[in] Buffer - Buffer to store data into
+**/
+VOID
+EFIAPI
+QemuFwCfgReadBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  )
+{
+  if (InternalQemuFwCfgIsAvailable ()) {
+    InternalQemuFwCfgReadBytes (Size, Buffer);
+  } else {
+    ZeroMem (Buffer, Size);
+  }
+}
+
+/**
+  Write firmware configuration bytes from a buffer
+
+  If called multiple times, then the data written will
+  continue at the offset of the firmware configuration
+  item where the previous write ended.
+
+  @param[in] Size - Size in bytes to write
+  @param[in] Buffer - Buffer to read data from
+**/
+VOID
+EFIAPI
+QemuFwCfgWriteBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  )
+{
+  if (InternalQemuFwCfgIsAvailable ()) {
+    if ((InternalQemuFwCfgDmaIsAvailable ())
+      && (Size <= MAX_UINT32))
+    {
+      InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_WRITE);
+      return;
+    }
+    MmioWriteBytes (Size, Buffer);
+  }
+}
+
+
+/**
+  Skip bytes in the firmware configuration item.
+
+  Increase the offset of the firmware configuration item without transferring
+  bytes between the item and a caller-provided buffer. Subsequent read, write
+  or skip operations will commence at the increased offset.
+
+  @param[in] Size  Number of bytes to skip.
+**/
+VOID
+EFIAPI
+QemuFwCfgSkipBytes (
+  IN UINTN                  Size
+  )
+{
+  UINTN ChunkSize;
+  UINT8 SkipBuffer[256];
+
+  if (!InternalQemuFwCfgIsAvailable ()) {
+    return;
+  }
+
+  if ((InternalQemuFwCfgDmaIsAvailable ())
+    && (Size <= MAX_UINT32))
+  {
+    InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP);
+    return;
+  }
+
+  //
+  // Emulate the skip by reading data in chunks, and throwing it away. The
+  // implementation below is suitable even for phases where RAM or dynamic
+  // allocation is not available or appropriate. It also doesn't affect the
+  // static data footprint for client modules. Large skips are not expected,
+  // therefore this fallback is not performance critical. The size of
+  // SkipBuffer is thought not to exert a large pressure on the stack in any
+  // phase.
+  //
+  while (Size > 0) {
+    ChunkSize = MIN (Size, sizeof SkipBuffer);
+    MmioReadBytes (ChunkSize, SkipBuffer);
+    Size -= ChunkSize;
+  }
+}
+
+
+/**
+  Reads a UINT8 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT8
+EFIAPI
+QemuFwCfgRead8 (
+  VOID
+  )
+{
+  UINT8 Result;
+
+  QemuFwCfgReadBytes (sizeof (Result), &Result);
+
+  return Result;
+}
+
+
+/**
+  Reads a UINT16 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT16
+EFIAPI
+QemuFwCfgRead16 (
+  VOID
+  )
+{
+  UINT16 Result;
+
+  QemuFwCfgReadBytes (sizeof (Result), &Result);
+
+  return Result;
+}
+
+
+/**
+  Reads a UINT32 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT32
+EFIAPI
+QemuFwCfgRead32 (
+  VOID
+  )
+{
+  UINT32 Result;
+
+  QemuFwCfgReadBytes (sizeof (Result), &Result);
+
+  return Result;
+}
+
+
+/**
+  Reads a UINT64 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT64
+EFIAPI
+QemuFwCfgRead64 (
+  VOID
+  )
+{
+  UINT64 Result;
+
+  QemuFwCfgReadBytes (sizeof (Result), &Result);
+
+  return Result;
+}
+
+
+/**
+  Find the configuration item corresponding to the firmware configuration file.
+
+  @param[in]  Name - Name of file to look up.
+  @param[out] Item - Configuration item corresponding to the file, to be passed
+                     to QemuFwCfgSelectItem ().
+  @param[out] Size - Number of bytes in the file.
+
+  @return    RETURN_SUCCESS       If file is found.
+             RETURN_NOT_FOUND     If file is not found.
+             RETURN_UNSUPPORTED   If firmware configuration is unavailable.
+
+**/
+RETURN_STATUS
+EFIAPI
+QemuFwCfgFindFile (
+  IN   CONST CHAR8           *Name,
+  OUT  FIRMWARE_CONFIG_ITEM  *Item,
+  OUT  UINTN                 *Size
+  )
+{
+  UINT32 Count;
+  UINT32 Idx;
+
+  if (!InternalQemuFwCfgIsAvailable ()) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
+  Count = SwapBytes32 (QemuFwCfgRead32 ());
+
+  for (Idx = 0; Idx < Count; ++Idx) {
+    UINT32 FileSize;
+    UINT16 FileSelect;
+    CHAR8  FileName[QEMU_FW_CFG_FNAME_SIZE];
+
+    FileSize     = QemuFwCfgRead32 ();
+    FileSelect   = QemuFwCfgRead16 ();
+    QemuFwCfgRead16 (); // skip the field called "reserved"
+    InternalQemuFwCfgReadBytes (sizeof (FileName), FileName);
+
+    if (AsciiStrCmp (Name, FileName) == 0) {
+      *Item = SwapBytes16 (FileSelect);
+      *Size = SwapBytes32 (FileSize);
+      return RETURN_SUCCESS;
+    }
+  }
+
+  return RETURN_NOT_FOUND;
+}
+
+/**
+  firmware config initialize.
+
+  @param  VOID
+
+  @return    RETURN_SUCCESS  Initialization succeeded.
+**/
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitialize (
+  VOID
+  )
+{
+  VOID              *DeviceTreeBase;
+  INT32             Node;
+  INT32             Prev;
+  CONST CHAR8       *Type;
+  INT32             Len;
+  CONST UINT64      *RegProp;
+  UINT64            FwCfgSelectorAddress;
+  UINT64            FwCfgDataAddress;
+  UINT64            FwCfgDataSize;
+  RETURN_STATUS     PcdStatus;
+
+  DeviceTreeBase = (VOID *) (UINTN)PcdGet64 (PcdDeviceTreeBase);
+  ASSERT (DeviceTreeBase != NULL);
+  //
+  // Make sure we have a valid device tree blob
+  //
+  ASSERT (fdt_check_header (DeviceTreeBase) == 0);
+
+  for (Prev = 0;; Prev = Node) {
+    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+    if (Node < 0) {
+      break;
+    }
+
+    //
+    // Check for memory node
+    //
+    Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
+    if ((Type)
+      && (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0))
+    {
+      //
+      // Get the 'reg' property of this node. For now, we will assume
+      // two 8 byte quantities for base and size, respectively.
+      //
+      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+      if ((RegProp != 0)
+        && (Len == (2 * sizeof (UINT64))))
+      {
+        FwCfgDataAddress      = SwapBytes64 (RegProp[0]);
+        FwCfgDataSize         = 8;
+        FwCfgSelectorAddress  = FwCfgDataAddress + FwCfgDataSize;
+
+        mFwCfgSelectorAddress = FwCfgSelectorAddress;
+        mFwCfgDataAddress = FwCfgDataAddress;
+
+        PcdStatus = PcdSet64S (
+          PcdFwCfgSelectorAddress,
+          FwCfgSelectorAddress
+          );
+        ASSERT_RETURN_ERROR (PcdStatus);
+        PcdStatus = PcdSet64S (
+          PcdFwCfgDataAddress,
+          FwCfgDataAddress
+          );
+        ASSERT_RETURN_ERROR (PcdStatus);
+        break;
+      } else {
+        DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT QemuCfg node\n",
+          __FUNCTION__));
+        break;
+      }
+    }
+  }
+  return RETURN_SUCCESS;
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
new file mode 100644
index 0000000000..e6df7d9120
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
@@ -0,0 +1,44 @@
+## @file
+#  initialized fw_cfg library.
+#
+#  Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = QemuFwCfgSecLib
+  FILE_GUID                      = cdf9a9d5-7422-4dcb-b41d-607151ad320b
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM
+
+  CONSTRUCTOR                    = QemuFwCfgInitialize
+
+
+[Sources]
+  QemuFwCfgLibInternal.h
+  QemuFwCfgPeiLib.c
+  QemuFwCfgPei.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  Platform/Loongson/LoongArchQemuPkg/Loongson.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  MemoryAllocationLib
+  FdtLib
+  PcdLib
+
+[Pcd]
+  gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase
+  gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgSelectorAddress
+  gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgDataAddress
-- 
2.31.1


  parent reply	other threads:[~2022-09-16  3:36 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-16  3:36 [edk2-platforms][PATCH V2 00/16] Platform: Add Loongson support xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 01/16] Platform/Loongson: Add Serial Port library xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 02/16] Platform/Loongson: Support SEC And Add Readme.md xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 03/16] Platform/Loongson: Add PeiServicesTablePointerLib xianglai
2022-09-16  3:36 ` xianglai [this message]
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 05/16] Platform/Loongson: Add MmuLib xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 06/16] Platform/Loongson: Add StableTimerLib xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 07/16] Platform/Loongson: Support PEI phase xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 08/16] Platform/Loongson: Add CPU DXE driver xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 09/16] Platform/Loongson: Add PciCpuIoDxe driver xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 10/16] Platform/Loongson: Add timer Dxe driver xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 11/16] Platform/Loongson: Add RealTime Clock lib xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 12/16] Platform/Loongson: Add Platform Boot Manager Lib xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 13/16] Platform/Loongson: Add Reset System Lib xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 14/16] Platform/Loongson: Support Dxe xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 15/16] Platform/Loongson: Add QemuFlashFvbServicesRuntimeDxe driver xianglai
2022-09-16  3:36 ` [edk2-platforms][PATCH V2 16/16] Platform/Loongson: Support for saving variables to flash xianglai
  -- strict thread matches above, loose matches on Subject: below --
2022-03-25  2:16 [edk2-platforms][PATCH V2 00/16] Platform: Add Loongson support xianglai
2022-03-25  2:16 ` [edk2-platforms][PATCH V2 04/16] Platform/Loongson: Add QemuFwCfgLib xianglai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=345a9df259f592aba9b1518b0bdce4eb03a0ad07.1663298005.git.lixianglai@loongson.cn \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox