[edk2-devel] [edk2-platforms][PATCH V5 04/15] Platform/Loongson: Add QemuFwCfgLib.

Chao Li lichao at loongson.cn
Fri Nov 11 09:36:39 UTC 2022


Reviewed-by: Chao Li <lichao at loongson.cn>

Thanks,
Chao
--------

On 11月 11 2022, at 5:12 下午, xianglai li <lixianglai at loongson.cn> wrote:
> 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
>
>
> Cc: Bibo Mao <maobibo at loongson.cn>
> Cc: Chao Li <lichao at loongson.cn>
> Cc: Leif Lindholm <quic_llindhol at quicinc.com>
> Cc: Liming Gao <gaoliming at byosoft.com.cn>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Signed-off-by: xianglai li <lixianglai at 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.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/Library/QemuFwCfgLib.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h
> new file mode 100644
> index 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.h
> new file mode 100644
> index 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.c
> new file mode 100644
> index 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.c
> new file mode 100644
> index 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.inf
> new file mode 100644
> index 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


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96289): https://edk2.groups.io/g/devel/message/96289
Mute This Topic: https://groups.io/mt/94955169/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/edk2-devel-archive/attachments/20221111/888eac29/attachment-0001.htm>


More information about the edk2-devel-archive mailing list