From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web12.17429.1666603732620891543 for ; Mon, 24 Oct 2022 02:28:53 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8AxStjTWlZjfxUCAA--.6380S3; Mon, 24 Oct 2022 17:28:51 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxoOIqWlZj9EoEAA--.16434S6; Mon, 24 Oct 2022 17:26:06 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, kraxel@redhat.com, ardb@kernel.org, maobibo@loongson.cn Subject: [edk2-platforms][PATCH V4 04/14] Platform/Loongson: Add QemuFwCfgLib. Date: Mon, 24 Oct 2022 17:25:52 +0800 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxoOIqWlZj9EoEAA--.16434S6 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWfuryfCw1xtF13XFyfZrWUJwb_yoW5Gr1xZo W8XF97Aw15Kw4rW34IkFn3W3y8JFW0gr4FqFWrAF4jq3Z8tF4Y9FW7ta4UWFn3Aw1rt34k A3yrX3yfZFZ2vrs5n29KB7ZKAUJUUUUr529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUym1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aV CY1x0267AKxVWxJr0_GcWln4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l 57IF6xkI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x8ErcxFaV Av8VWrMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwCF04k20xvY0x0EwIxG rwCF04k20xvE74AGY7Cv6cx26rWl4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxYO2xFxVAFwI 0_Jrv_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF 1VAY17CE14v26r126r1DMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Ar0_tr1lIx AIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4l IxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIda VFxhVjvjDU0xZFpf9x0zRByIUUUUUU= Content-Transfer-Encoding: quoted-printable 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=3D4054 Signed-off-by: xianglai li --- .../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/IndustryStan= dard/QemuFwCfg.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu= FwCfgLib.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/Qe= muFwCfg.h b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/Qem= uFwCfg.h new file mode 100644 index 0000000000..a028ca1124 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/IndustryStandard/QemuFwCfg= .h @@ -0,0 +1,95 @@ +/** @file=0D + Macro and type definitions corresponding to the QEMU fw_cfg interface.=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FW - FireWare=0D + - CFG - Configure=0D + - FNAME - File Name=0D + - CTL - Contorl=0D +**/=0D +=0D +#ifndef QEMU_FW_CFG_H_=0D +#define QEMU_FW_CFG_H_=0D +=0D +#include =0D +=0D +//=0D +// The size, in bytes, of names of firmware configuration files, including= at=0D +// least one terminating NUL byte.=0D +//=0D +#define QEMU_FW_CFG_FNAME_SIZE 56=0D +=0D +//=0D +// If the following bit is set in the UINT32 fw_cfg revision / feature bit= map=0D +// -- read from key 0x0001 with the basic IO Port or MMIO method --, then = the=0D +// DMA interface is available.=0D +//=0D +#define FW_CFG_F_DMA BIT1=0D +=0D +//=0D +// Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).=0D +//=0D +#define FW_CFG_DMA_CTL_ERROR BIT0=0D +#define FW_CFG_DMA_CTL_READ BIT1=0D +#define FW_CFG_DMA_CTL_SKIP BIT2=0D +#define FW_CFG_DMA_CTL_SELECT BIT3=0D +#define FW_CFG_DMA_CTL_WRITE BIT4=0D +=0D +//=0D +// The fw_cfg registers can be found at these IO Ports, on the IO-mapped=0D +// platforms (Ia32 and X64).=0D +//=0D +#define FW_CFG_IO_SELECTOR 0x510=0D +#define FW_CFG_IO_DATA 0x511=0D +#define FW_CFG_IO_DMA_ADDRESS 0x514=0D +=0D +//=0D +// Numerically defined keys.=0D +//=0D +typedef enum {=0D + QemuFwCfgItemSignature =3D 0x0000,=0D + QemuFwCfgItemInterfaceVersion =3D 0x0001,=0D + QemuFwCfgItemSystemUuid =3D 0x0002,=0D + QemuFwCfgItemRamSize =3D 0x0003,=0D + QemuFwCfgItemGraphicsEnabled =3D 0x0004,=0D + QemuFwCfgItemSmpCpuCount =3D 0x0005,=0D + QemuFwCfgItemMachineId =3D 0x0006,=0D + QemuFwCfgItemKernelAddress =3D 0x0007,=0D + QemuFwCfgItemKernelSize =3D 0x0008,=0D + QemuFwCfgItemKernelCommandLine =3D 0x0009,=0D + QemuFwCfgItemInitrdAddress =3D 0x000a,=0D + QemuFwCfgItemInitrdSize =3D 0x000b,=0D + QemuFwCfgItemBootDevice =3D 0x000c,=0D + QemuFwCfgItemNumaData =3D 0x000d,=0D + QemuFwCfgItemBootMenu =3D 0x000e,=0D + QemuFwCfgItemMaximumCpuCount =3D 0x000f,=0D + QemuFwCfgItemKernelEntry =3D 0x0010,=0D + QemuFwCfgItemKernelData =3D 0x0011,=0D + QemuFwCfgItemInitrdData =3D 0x0012,=0D + QemuFwCfgItemCommandLineAddress =3D 0x0013,=0D + QemuFwCfgItemCommandLineSize =3D 0x0014,=0D + QemuFwCfgItemCommandLineData =3D 0x0015,=0D + QemuFwCfgItemKernelSetupAddress =3D 0x0016,=0D + QemuFwCfgItemKernelSetupSize =3D 0x0017,=0D + QemuFwCfgItemKernelSetupData =3D 0x0018,=0D + QemuFwCfgItemFileDir =3D 0x0019,=0D +=0D +} FIRMWARE_CONFIG_ITEM;=0D +=0D +//=0D +// Communication structure for the DMA access method. All fields are encod= ed in=0D +// big endian.=0D +//=0D +#pragma pack (1)=0D +typedef struct {=0D + UINT32 Control;=0D + UINT32 Length;=0D + UINT64 Address;=0D +} FW_CFG_DMA_ACCESS;=0D +#pragma pack ()=0D +=0D +#endif=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLi= b.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=0D + QEMU/KVM Firmware Configuration access=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FW or Fw - Firmware=0D + - Cfg - Configure=0D +**/=0D +=0D +#ifndef QEMU_FW_CFG_LIB_=0D +#define QEMU_FW_CFG_LIB_=0D +=0D +#include =0D +=0D +typedef enum {=0D + EfiAcpiAddressRangeMemory =3D 1,=0D + EfiAcpiAddressRangeReserved =3D 2,=0D + EfiAcpiAddressRangeACPI =3D 3,=0D + EfiAcpiAddressRangeNVS =3D 4=0D +} EFI_ACPI_MEMORY_TYPE;=0D +=0D +typedef struct {=0D + UINT64 BaseAddr;=0D + UINT64 Length;=0D + UINT32 Type;=0D + UINT32 Reserved;=0D +} LOONGARCH_MEMMAP_ENTRY;=0D +=0D +/**=0D + Returns a boolean indicating if the firmware configuration interface=0D + is available or not.=0D +=0D + This function may change fw_cfg state.=0D +=0D + @retval TRUE The interface is available=0D + @retval FALSE The interface is not available=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +QemuFwCfgIsAvailable (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Selects a firmware configuration item for reading.=0D +=0D + Following this call, any data read from this item will start from=0D + the beginning of the configuration item's data.=0D +=0D + @param[in] QemuFwCfgItem - Firmware Configuration item to read=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgSelectItem (=0D + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem=0D + );=0D +=0D +=0D +/**=0D + Reads firmware configuration bytes into a buffer=0D +=0D + If called multiple times, then the data read will=0D + continue at the offset of the firmware configuration=0D + item where the previous read ended.=0D +=0D + @param[in] Size - Size in bytes to read=0D + @param[in] Buffer - Buffer to store data into=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgReadBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer OPTIONAL=0D + );=0D +=0D +=0D +/**=0D + Writes firmware configuration bytes from a buffer=0D +=0D + If called multiple times, then the data written will=0D + continue at the offset of the firmware configuration=0D + item where the previous write ended.=0D +=0D + @param[in] Size - Size in bytes to write=0D + @param[in] Buffer - Buffer to read data from=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgWriteBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer=0D + );=0D +=0D +=0D +/**=0D + Skip bytes in the firmware configuration item.=0D +=0D + Increase the offset of the firmware configuration item without transferr= ing=0D + bytes between the item and a caller-provided buffer. Subsequent read, wr= ite=0D + or skip operations will commence at the increased offset.=0D +=0D + @param[in] Size Number of bytes to skip.=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgSkipBytes (=0D + IN UINTN Size=0D + );=0D +=0D +=0D +/**=0D + Reads a UINT8 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +QemuFwCfgRead8 (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Reads a UINT16 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT16=0D +EFIAPI=0D +QemuFwCfgRead16 (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Reads a UINT32 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT32=0D +EFIAPI=0D +QemuFwCfgRead32 (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Reads a UINT64 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT64=0D +EFIAPI=0D +QemuFwCfgRead64 (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Find the configuration item corresponding to the firmware configuration = file.=0D +=0D + @param[in] Name - Name of file to look up.=0D + @param[out] Item - Configuration item corresponding to the file, to be p= assed=0D + to QemuFwCfgSelectItem ().=0D + @param[out] Size - Number of bytes in the file.=0D +=0D + @retval RETURN_SUCCESS If file is found.=0D + RETURN_NOT_FOUND If file is not found.=0D + RETURN_UNSUPPORTED If firmware configuration is unavailable= .=0D +=0D +**/=0D +RETURN_STATUS=0D +EFIAPI=0D +QemuFwCfgFindFile (=0D + IN CONST CHAR8 *Name,=0D + OUT FIRMWARE_CONFIG_ITEM *Item,=0D + OUT UINTN *Size=0D + );=0D +=0D +#endif=0D +=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/= QemuFwCfgLibInternal.h new file mode 100644 index 0000000000..33eeb927dd --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibI= nternal.h @@ -0,0 +1,64 @@ +/** @file=0D + fw_cfg library implementation.=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FwCfg - firmWare Configure=0D +**/=0D +=0D +#ifndef QEMU_FW_CFG_LIB_INTERNAL_H_=0D +#define QEMU_FW_CFG_LIB_INTERNAL_H_=0D +=0D +/**=0D + Returns a boolean indicating if the firmware configuration interface is= =0D + available for library-internal purposes.=0D +=0D + This function never changes fw_cfg state.=0D +=0D + @retval TRUE The interface is available internally.=0D + @retval FALSE The interface is not available internally.=0D +**/=0D +BOOLEAN=0D +InternalQemuFwCfgIsAvailable (=0D + VOID=0D + );=0D +=0D +=0D +/**=0D + Returns a boolean indicating whether QEMU provides the DMA-like access m= ethod=0D + for fw_cfg.=0D +=0D + @retval TRUE The DMA-like access method is available.=0D + @retval FALSE The DMA-like access method is unavailable.=0D +**/=0D +BOOLEAN=0D +InternalQemuFwCfgDmaIsAvailable (=0D + VOID=0D + );=0D +=0D +/**=0D + Transfer an array of bytes, or skip a number of bytes, using the DMA=0D + interface.=0D +=0D + @param[in] Size Size in bytes to transfer or skip.=0D +=0D + @param[in,out] Buffer Buffer to read data into or write data from. Ign= ored,=0D + and may be NULL, if Size is zero, or Control is= =0D + FW_CFG_DMA_CTL_SKIP.=0D +=0D + @param[in] Control One of the following:=0D + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buff= er.=0D + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buf= fer.=0D + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.=0D +**/=0D +VOID=0D +InternalQemuFwCfgDmaBytes (=0D + IN UINT32 Size,=0D + IN OUT VOID *Buffer OPTIONAL,=0D + IN UINT32 Control=0D + );=0D +=0D +#endif=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCf= gPei.c new file mode 100644 index 0000000000..91995c90b5 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c @@ -0,0 +1,119 @@ +/** @file=0D + fw_cfg library implementation.=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FwCfg - firmWare Configure=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +=0D +#include "QemuFwCfgLibInternal.h"=0D +=0D +/**=0D + Returns a boolean indicating if the firmware configuration interface=0D + is available or not.=0D +=0D + This function may change fw_cfg state.=0D +=0D + @retval TRUE The interface is available=0D + @retval FALSE The interface is not available=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +QemuFwCfgIsAvailable (=0D + VOID=0D + )=0D +{=0D + UINT32 Signature;=0D + UINT32 Revision;=0D +=0D + QemuFwCfgSelectItem (QemuFwCfgItemSignature);=0D + Signature =3D QemuFwCfgRead32 ();=0D + DEBUG ((DEBUG_INFO, "FW CFG Signature: 0x%x\n", Signature));=0D + QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);=0D + Revision =3D QemuFwCfgRead32 ();=0D + DEBUG ((DEBUG_INFO, "FW CFG Revision: 0x%x\n", Revision));=0D + if ((Signature !=3D SIGNATURE_32 ('Q', 'E', 'M', 'U'))=0D + || (Revision < 1))=0D + {=0D + DEBUG ((DEBUG_INFO, "QemuFwCfg interface not supported.\n"));=0D + return FALSE;=0D + }=0D +=0D + DEBUG ((DEBUG_INFO, "QemuFwCfg interface is supported.\n"));=0D + return TRUE;=0D +}=0D +=0D +=0D +/**=0D + Returns a boolean indicating if the firmware configuration interface is= =0D + available for library-internal purposes.=0D +=0D + This function never changes fw_cfg state.=0D +=0D + @retval TRUE The interface is available internally.=0D + @retval FALSE The interface is not available internally.=0D +**/=0D +BOOLEAN=0D +InternalQemuFwCfgIsAvailable (=0D + VOID=0D + )=0D +{=0D + //=0D + // We always return TRUE, because the consumer of this library ought to = have=0D + // called QemuFwCfgIsAvailable before making other calls which would hit= this=0D + // path.=0D + //=0D + return TRUE;=0D +}=0D +=0D +/**=0D + Returns a boolean indicating whether QEMU provides the DMA-like access m= ethod=0D + for fw_cfg.=0D +=0D + @retval TRUE The DMA-like access method is available.=0D + @retval FALSE The DMA-like access method is unavailable.=0D +**/=0D +BOOLEAN=0D +InternalQemuFwCfgDmaIsAvailable (=0D + VOID=0D + )=0D +{=0D + return FALSE;=0D +}=0D +=0D +/**=0D + Transfer an array of bytes, or skip a number of bytes, using the DMA=0D + interface.=0D +=0D + @param[in] Size Size in bytes to transfer or skip.=0D +=0D + @param[in, out] Buffer Buffer to read data into or write data from. Ig= nored,=0D + and may be NULL, if Size is zero, or Control is= =0D + FW_CFG_DMA_CTL_SKIP.=0D +=0D + @param[in] Control One of the following:=0D + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buff= er.=0D + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buf= fer.=0D + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.=0D +**/=0D +VOID=0D +InternalQemuFwCfgDmaBytes (=0D + IN UINT32 Size,=0D + IN OUT VOID *Buffer OPTIONAL,=0D + IN UINT32 Control=0D + )=0D +{=0D + //=0D + // We should never reach here=0D + //=0D + ASSERT (FALSE);=0D + CpuDeadLoop ();=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPeiLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuF= wCfgPeiLib.c new file mode 100644 index 0000000000..2bbaa9ed35 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.c @@ -0,0 +1,477 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FwCfg - firmWare Configure=0D + - CTL - Control=0D +**/=0D +=0D +#include "Uefi.h"=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "QemuFwCfgLibInternal.h"=0D +=0D +STATIC UINTN mFwCfgSelectorAddress;=0D +STATIC UINTN mFwCfgDataAddress;=0D +/**=0D + To get firmware configure selector address.=0D +=0D + @param VOID=0D +=0D + @retval firmware configure selector address=0D +**/=0D +UINTN=0D +EFIAPI=0D +QemuGetFwCfgSelectorAddress (=0D + VOID=0D + )=0D +{=0D + UINTN FwCfgSelectorAddress =3D mFwCfgSelectorAddress;=0D + if (FwCfgSelectorAddress =3D=3D 0) {=0D + FwCfgSelectorAddress =3D (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);=0D + }=0D + return FwCfgSelectorAddress;=0D +}=0D +/**=0D + To get firmware configure Data address.=0D +=0D + @param VOID=0D +=0D + @retval firmware configure data address=0D +**/=0D +UINTN=0D +EFIAPI=0D +QemuGetFwCfgDataAddress (=0D + VOID=0D + )=0D +{=0D + UINTN FwCfgDataAddress =3D mFwCfgDataAddress;=0D + if (FwCfgDataAddress =3D=3D 0) {=0D + FwCfgDataAddress =3D (UINTN)PcdGet64 (PcdFwCfgDataAddress);=0D + }=0D + return FwCfgDataAddress;=0D +}=0D +/**=0D + Selects a firmware configuration item for reading.=0D +=0D + Following this call, any data read from this item will start from=0D + the beginning of the configuration item's data.=0D +=0D + @param[in] QemuFwCfgItem - Firmware Configuration item to read=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgSelectItem (=0D + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem=0D + )=0D +{=0D + UINTN FwCfgSelectorAddress;=0D + FwCfgSelectorAddress =3D QemuGetFwCfgSelectorAddress ();=0D + MmioWrite16 (FwCfgSelectorAddress, SwapBytes16((UINT16) (UINTN)QemuFwCfg= Item));=0D +}=0D +=0D +/**=0D + Slow READ_BYTES_FUNCTION.=0D +=0D + @param[in] The size of the data to be read.=0D + @param[in] Buffer The buffer that stores the readout data.=0D +**/=0D +VOID=0D +EFIAPI=0D +MmioReadBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer OPTIONAL=0D + )=0D +{=0D + UINTN Left;=0D + UINT8 *Ptr;=0D + UINT8 *End;=0D + UINTN FwCfgDataAddress;=0D + Left =3D Size & 7;=0D +=0D + Size -=3D Left;=0D + Ptr =3D Buffer;=0D + End =3D Ptr + Size;=0D + FwCfgDataAddress =3D QemuGetFwCfgDataAddress ();=0D + while (Ptr < End) {=0D + *(UINT64 *)Ptr =3D MmioRead64 (FwCfgDataAddress);=0D + Ptr +=3D 8;=0D + }=0D + if (Left & 4) {=0D + *(UINT32 *)Ptr =3D MmioRead32 (FwCfgDataAddress);=0D + Ptr +=3D 4;=0D + }=0D + if (Left & 2) {=0D + *(UINT16 *)Ptr =3D MmioRead16 (FwCfgDataAddress);=0D + Ptr +=3D 2;=0D + }=0D + if (Left & 1) {=0D + *Ptr =3D MmioRead8 (FwCfgDataAddress);=0D + }=0D +}=0D +=0D +/**=0D + Slow WRITE_BYTES_FUNCTION.=0D +=0D + @param[in] The size of the data to be write.=0D + @param[in] Buffer The buffer that stores the writein data.=0D +**/=0D +VOID=0D +EFIAPI=0D +MmioWriteBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer OPTIONAL=0D + )=0D +{=0D + UINTN Idx;=0D + UINTN FwCfgDataAddress;=0D + FwCfgDataAddress =3D QemuGetFwCfgDataAddress ();=0D + for (Idx =3D 0; Idx < Size; ++Idx) {=0D + MmioWrite8 (FwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);=0D + }=0D +}=0D +=0D +/**=0D + Reads firmware configuration bytes into a buffer=0D +=0D + @param[in] Size - Size in bytes to read=0D + @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0)=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +InternalQemuFwCfgReadBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer OPTIONAL=0D + )=0D +{=0D + if ((InternalQemuFwCfgDmaIsAvailable ())=0D + && (Size <=3D MAX_UINT32))=0D + {=0D + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ);= =0D + return;=0D + }=0D + MmioReadBytes (Size, Buffer);=0D +}=0D +=0D +=0D +/**=0D + Reads firmware configuration bytes into a buffer=0D +=0D + If called multiple times, then the data read will=0D + continue at the offset of the firmware configuration=0D + item where the previous read ended.=0D +=0D + @param[in] Size - Size in bytes to read=0D + @param[in] Buffer - Buffer to store data into=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgReadBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer=0D + )=0D +{=0D + if (InternalQemuFwCfgIsAvailable ()) {=0D + InternalQemuFwCfgReadBytes (Size, Buffer);=0D + } else {=0D + ZeroMem (Buffer, Size);=0D + }=0D +}=0D +=0D +/**=0D + Write firmware configuration bytes from a buffer=0D +=0D + If called multiple times, then the data written will=0D + continue at the offset of the firmware configuration=0D + item where the previous write ended.=0D +=0D + @param[in] Size - Size in bytes to write=0D + @param[in] Buffer - Buffer to read data from=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgWriteBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer=0D + )=0D +{=0D + if (InternalQemuFwCfgIsAvailable ()) {=0D + if ((InternalQemuFwCfgDmaIsAvailable ())=0D + && (Size <=3D MAX_UINT32))=0D + {=0D + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_WRIT= E);=0D + return;=0D + }=0D + MmioWriteBytes (Size, Buffer);=0D + }=0D +}=0D +=0D +=0D +/**=0D + Skip bytes in the firmware configuration item.=0D +=0D + Increase the offset of the firmware configuration item without transferr= ing=0D + bytes between the item and a caller-provided buffer. Subsequent read, wr= ite=0D + or skip operations will commence at the increased offset.=0D +=0D + @param[in] Size Number of bytes to skip.=0D +**/=0D +VOID=0D +EFIAPI=0D +QemuFwCfgSkipBytes (=0D + IN UINTN Size=0D + )=0D +{=0D + UINTN ChunkSize;=0D + UINT8 SkipBuffer[256];=0D +=0D + if (!InternalQemuFwCfgIsAvailable ()) {=0D + return;=0D + }=0D +=0D + if ((InternalQemuFwCfgDmaIsAvailable ())=0D + && (Size <=3D MAX_UINT32))=0D + {=0D + InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP);=0D + return;=0D + }=0D +=0D + //=0D + // Emulate the skip by reading data in chunks, and throwing it away. The= =0D + // implementation below is suitable even for phases where RAM or dynamic= =0D + // allocation is not available or appropriate. It also doesn't affect th= e=0D + // static data footprint for client modules. Large skips are not expecte= d,=0D + // therefore this fallback is not performance critical. The size of=0D + // SkipBuffer is thought not to exert a large pressure on the stack in a= ny=0D + // phase.=0D + //=0D + while (Size > 0) {=0D + ChunkSize =3D MIN (Size, sizeof SkipBuffer);=0D + MmioReadBytes (ChunkSize, SkipBuffer);=0D + Size -=3D ChunkSize;=0D + }=0D +}=0D +=0D +=0D +/**=0D + Reads a UINT8 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +QemuFwCfgRead8 (=0D + VOID=0D + )=0D +{=0D + UINT8 Result;=0D +=0D + QemuFwCfgReadBytes (sizeof (Result), &Result);=0D +=0D + return Result;=0D +}=0D +=0D +=0D +/**=0D + Reads a UINT16 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT16=0D +EFIAPI=0D +QemuFwCfgRead16 (=0D + VOID=0D + )=0D +{=0D + UINT16 Result;=0D +=0D + QemuFwCfgReadBytes (sizeof (Result), &Result);=0D +=0D + return Result;=0D +}=0D +=0D +=0D +/**=0D + Reads a UINT32 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT32=0D +EFIAPI=0D +QemuFwCfgRead32 (=0D + VOID=0D + )=0D +{=0D + UINT32 Result;=0D +=0D + QemuFwCfgReadBytes (sizeof (Result), &Result);=0D +=0D + return Result;=0D +}=0D +=0D +=0D +/**=0D + Reads a UINT64 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=0D +=0D +**/=0D +UINT64=0D +EFIAPI=0D +QemuFwCfgRead64 (=0D + VOID=0D + )=0D +{=0D + UINT64 Result;=0D +=0D + QemuFwCfgReadBytes (sizeof (Result), &Result);=0D +=0D + return Result;=0D +}=0D +=0D +=0D +/**=0D + Find the configuration item corresponding to the firmware configuration = file.=0D +=0D + @param[in] Name - Name of file to look up.=0D + @param[out] Item - Configuration item corresponding to the file, to be p= assed=0D + to QemuFwCfgSelectItem ().=0D + @param[out] Size - Number of bytes in the file.=0D +=0D + @return RETURN_SUCCESS If file is found.=0D + RETURN_NOT_FOUND If file is not found.=0D + RETURN_UNSUPPORTED If firmware configuration is unavailable= .=0D +=0D +**/=0D +RETURN_STATUS=0D +EFIAPI=0D +QemuFwCfgFindFile (=0D + IN CONST CHAR8 *Name,=0D + OUT FIRMWARE_CONFIG_ITEM *Item,=0D + OUT UINTN *Size=0D + )=0D +{=0D + UINT32 Count;=0D + UINT32 Idx;=0D +=0D + if (!InternalQemuFwCfgIsAvailable ()) {=0D + return RETURN_UNSUPPORTED;=0D + }=0D +=0D + QemuFwCfgSelectItem (QemuFwCfgItemFileDir);=0D + Count =3D SwapBytes32 (QemuFwCfgRead32 ());=0D +=0D + for (Idx =3D 0; Idx < Count; ++Idx) {=0D + UINT32 FileSize;=0D + UINT16 FileSelect;=0D + CHAR8 FileName[QEMU_FW_CFG_FNAME_SIZE];=0D +=0D + FileSize =3D QemuFwCfgRead32 ();=0D + FileSelect =3D QemuFwCfgRead16 ();=0D + QemuFwCfgRead16 (); // skip the field called "reserved"=0D + InternalQemuFwCfgReadBytes (sizeof (FileName), FileName);=0D +=0D + if (AsciiStrCmp (Name, FileName) =3D=3D 0) {=0D + *Item =3D SwapBytes16 (FileSelect);=0D + *Size =3D SwapBytes32 (FileSize);=0D + return RETURN_SUCCESS;=0D + }=0D + }=0D +=0D + return RETURN_NOT_FOUND;=0D +}=0D +=0D +/**=0D + firmware config initialize.=0D +=0D + @param VOID=0D +=0D + @return RETURN_SUCCESS Initialization succeeded.=0D +**/=0D +RETURN_STATUS=0D +EFIAPI=0D +QemuFwCfgInitialize (=0D + VOID=0D + )=0D +{=0D + VOID *DeviceTreeBase;=0D + INT32 Node;=0D + INT32 Prev;=0D + CONST CHAR8 *Type;=0D + INT32 Len;=0D + CONST UINT64 *RegProp;=0D + UINT64 FwCfgSelectorAddress;=0D + UINT64 FwCfgDataAddress;=0D + UINT64 FwCfgDataSize;=0D + RETURN_STATUS PcdStatus;=0D +=0D + DeviceTreeBase =3D (VOID *) (UINTN)PcdGet64 (PcdDeviceTreeBase);=0D + ASSERT (DeviceTreeBase !=3D NULL);=0D + //=0D + // Make sure we have a valid device tree blob=0D + //=0D + ASSERT (fdt_check_header (DeviceTreeBase) =3D=3D 0);=0D +=0D + for (Prev =3D 0;; Prev =3D Node) {=0D + Node =3D fdt_next_node (DeviceTreeBase, Prev, NULL);=0D + if (Node < 0) {=0D + break;=0D + }=0D +=0D + //=0D + // Check for memory node=0D + //=0D + Type =3D fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);=0D + if ((Type)=0D + && (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) =3D=3D 0))=0D + {=0D + //=0D + // Get the 'reg' property of this node. For now, we will assume=0D + // two 8 byte quantities for base and size, respectively.=0D + //=0D + RegProp =3D fdt_getprop (DeviceTreeBase, Node, "reg", &Len);=0D + if ((RegProp !=3D 0)=0D + && (Len =3D=3D (2 * sizeof (UINT64))))=0D + {=0D + FwCfgDataAddress =3D SwapBytes64 (RegProp[0]);=0D + FwCfgDataSize =3D 8;=0D + FwCfgSelectorAddress =3D FwCfgDataAddress + FwCfgDataSize;=0D +=0D + mFwCfgSelectorAddress =3D FwCfgSelectorAddress;=0D + mFwCfgDataAddress =3D FwCfgDataAddress;=0D +=0D + PcdStatus =3D PcdSet64S (=0D + PcdFwCfgSelectorAddress,=0D + FwCfgSelectorAddress=0D + );=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + PcdStatus =3D PcdSet64S (=0D + PcdFwCfgDataAddress,=0D + FwCfgDataAddress=0D + );=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + break;=0D + } else {=0D + DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT QemuCfg node\n",=0D + __FUNCTION__));=0D + break;=0D + }=0D + }=0D + }=0D + return RETURN_SUCCESS;=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPeiLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/Qem= uFwCfgPeiLib.inf new file mode 100644 index 0000000000..e6df7d9120 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.inf @@ -0,0 +1,44 @@ +## @file=0D +# initialized fw_cfg library.=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D QemuFwCfgSecLib=0D + FILE_GUID =3D cdf9a9d5-7422-4dcb-b41d-607151ad320b= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D QemuFwCfgLib|PEIM=0D +=0D + CONSTRUCTOR =3D QemuFwCfgInitialize=0D +=0D +=0D +[Sources]=0D + QemuFwCfgLibInternal.h=0D + QemuFwCfgPeiLib.c=0D + QemuFwCfgPei.c=0D +=0D +[Packages]=0D + EmbeddedPkg/EmbeddedPkg.dec=0D + MdePkg/MdePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + BaseMemoryLib=0D + DebugLib=0D + IoLib=0D + MemoryAllocationLib=0D + FdtLib=0D + PcdLib=0D +=0D +[Pcd]=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgSelectorAddress=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgDataAddress=0D --=20 2.31.1