Thanks,
Chao
--------
QemuFwCfgLib for PEI phase.This library obtains the QemuFWCfg base address bydirectly parsing the fdt, and reads and writes the datain the QemuFWCfg by operating on the QemuFWCfg base address.REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054Cc: Bibo Mao <maobibo@loongson.cn>Cc: Chao Li <lichao@loongson.cn>Cc: Leif Lindholm <quic_llindhol@quicinc.com>Cc: Liming Gao <gaoliming@byosoft.com.cn>Cc: Michael D Kinney <michael.d.kinney@intel.com>Signed-off-by: xianglai li <lixianglai@loongson.cn>---.../Include/Library/QemuFwCfgLib.h | 174 +++++++.../QemuFwCfgLib/QemuFwCfgLibInternal.h | 63 +++.../Library/QemuFwCfgLib/QemuFwCfgPei.c | 117 +++++.../Library/QemuFwCfgLib/QemuFwCfgPeiLib.c | 463 ++++++++++++++++++.../Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf | 46 ++5 files changed, 863 insertions(+)create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.hcreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.hcreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.ccreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.ccreate mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.infdiff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.hnew file mode 100644index 0000000000..11da4d0b8a--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h@@ -0,0 +1,174 @@+/** @file+ QEMU/KVM Firmware Configuration access++ Copyright (c) 2022 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 // QEMU_FW_CFG_LIB_diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.hnew file mode 100644index 0000000000..229c080961--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h@@ -0,0 +1,63 @@+/** @file+ fw_cfg library implementation.++ Copyright (c) 2022 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 // QEMU_FW_CFG_LIB_INTERNAL_H_diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.cnew file mode 100644index 0000000000..b170c953f3--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c@@ -0,0 +1,117 @@+/** @file+ fw_cfg library implementation.++ Copyright (c) 2022 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.cnew file mode 100644index 0000000000..5593856b82--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.c@@ -0,0 +1,463 @@+/** @file++ Copyright (c) 2022 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.infnew file mode 100644index 0000000000..8609d615e7--- /dev/null+++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf@@ -0,0 +1,46 @@+## @file+# initialized fw_cfg library.+#+# Copyright (c) 2022 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++#+# VALID_ARCHITECTURES = LOONGARCH64+#++[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