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.web08.3548.1668157958634470557 for ; Fri, 11 Nov 2022 01:12:39 -0800 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 _____8AxbdoFEm5jfBMGAA--.19105S3; Fri, 11 Nov 2022 17:12:37 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxFlcAEm5jXc0QAA--.27651S6; Fri, 11 Nov 2022 17:12:36 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: Bibo Mao , Chao Li , Leif Lindholm , Liming Gao , Michael D Kinney Subject: [edk2-platforms][PATCH V5 04/15] Platform/Loongson: Add QemuFwCfgLib. Date: Fri, 11 Nov 2022 17:12:19 +0800 Message-Id: <2b938c55024c6e6207196ca6a70e27744742070b.1668157715.git.lixianglai@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxFlcAEm5jXc0QAA--.27651S6 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWfXr4UKryDGFWrKw18XF4DXFb_yoW8tFy5uo W8XF97Aw15tw4rW34I9Fn3W3y8Jayjgr4rXF4FyF4UtFn8tF4Y9FW3ta4UGFnYyw1Fy34k A395X3yfZFZayrs5n29KB7ZKAUJUUUUx529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUkv1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIE14v26F4UJVW0owA2z4x0Y4vEx4A2jsIEc7 CjxVAFwI0_Cr1j6rxdM2kKe7AKxVWUAVWUtwAS0I0E0xvYzxvE52x082IY62kv0487Mc80 4VCY07AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VCjz48v1sIEY2 0_WwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lc7CjxVAaw2AFwI0_JF0_ Jw1l42xK82IYc2Ij64vIr41l42xK82IY6x8ErcxFaVAv8VWrMxC20s026xCaFVCjc4AY6r 1j6r4UMxCIbckI1I0E14v26r126r1DMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xv wVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY6xIIjx v20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20E Y4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2jsIEc7CjxV AFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0zR9iSdUUUUU= Content-Transfer-Encoding: quoted-printable QemuFwCfgLib for PEI phase.=0D This library obtains the QemuFWCfg base address by=0D directly parsing the fdt, and reads and writes the data=0D in the QemuFWCfg by operating on the QemuFWCfg base address.=0D =0D REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054=0D =0D Cc: Bibo Mao =0D Cc: Chao Li =0D Cc: Leif Lindholm =0D Cc: Liming Gao =0D Cc: Michael D Kinney =0D Signed-off-by: xianglai li =0D ---=0D .../Include/Library/QemuFwCfgLib.h | 174 +++++++=0D .../QemuFwCfgLib/QemuFwCfgLibInternal.h | 63 +++=0D .../Library/QemuFwCfgLib/QemuFwCfgPei.c | 117 +++++=0D .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.c | 463 ++++++++++++++++++=0D .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf | 46 ++=0D 5 files changed, 863 insertions(+)=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu= FwCfgLib.h=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgLibInternal.h=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPei.c=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPeiLib.c=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib= /QemuFwCfgPeiLib.inf=0D =0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLi= b.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h=0D new file mode 100644=0D index 0000000000..11da4d0b8a=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/QemuFwCfgLib.h=0D @@ -0,0 +1,174 @@=0D +/** @file=0D + QEMU/KVM Firmware Configuration access=0D +=0D + Copyright (c) 2022 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 +BOOLEAN=0D +EFIAPI=0D +QemuFwCfgIsAvailable (=0D + VOID=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 +VOID=0D +EFIAPI=0D +QemuFwCfgSelectItem (=0D + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem=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 OPTIONAL=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 +VOID=0D +EFIAPI=0D +QemuFwCfgWriteBytes (=0D + IN UINTN Size,=0D + IN VOID *Buffer=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 + Reads a UINT8 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +**/=0D +UINT8=0D +EFIAPI=0D +QemuFwCfgRead8 (=0D + VOID=0D + );=0D +=0D +/**=0D + Reads a UINT16 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +**/=0D +UINT16=0D +EFIAPI=0D +QemuFwCfgRead16 (=0D + VOID=0D + );=0D +=0D +/**=0D + Reads a UINT32 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +**/=0D +UINT32=0D +EFIAPI=0D +QemuFwCfgRead32 (=0D + VOID=0D + );=0D +=0D +/**=0D + Reads a UINT64 firmware configuration value=0D +=0D + @retval Value of Firmware Configuration item read=0D +**/=0D +UINT64=0D +EFIAPI=0D +QemuFwCfgRead64 (=0D + VOID=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 +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 // QEMU_FW_CFG_LIB_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/= QemuFwCfgLibInternal.h=0D new file mode 100644=0D index 0000000000..229c080961=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgLibI= nternal.h=0D @@ -0,0 +1,63 @@=0D +/** @file=0D + fw_cfg library implementation.=0D +=0D + Copyright (c) 2022 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 + 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 // QEMU_FW_CFG_LIB_INTERNAL_H_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFw= CfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCf= gPei.c=0D new file mode 100644=0D index 0000000000..b170c953f3=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPei.= c=0D @@ -0,0 +1,117 @@=0D +/** @file=0D + fw_cfg library implementation.=0D +=0D + Copyright (c) 2022 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 +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 + 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=0D new file mode 100644=0D index 0000000000..5593856b82=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.c=0D @@ -0,0 +1,463 @@=0D +/** @file=0D +=0D + Copyright (c) 2022 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 +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 +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 + 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 + 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 + Reads a UINT8 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=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 + Reads a UINT16 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=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 + Reads a UINT32 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=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 + Reads a UINT64 firmware configuration value=0D +=0D + @return Value of Firmware Configuration item read=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 + 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 +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=0D new file mode 100644=0D index 0000000000..8609d615e7=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiL= ib.inf=0D @@ -0,0 +1,46 @@=0D +## @file=0D +# initialized fw_cfg library.=0D +#=0D +# Copyright (c) 2022 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 + CONSTRUCTOR =3D QemuFwCfgInitialize=0D +=0D +#=0D +# VALID_ARCHITECTURES =3D LOONGARCH64=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 -- =0D 2.31.1=0D =0D