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.web09.3659.1668159402206485626 for ; Fri, 11 Nov 2022 01:36:43 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lichao@loongson.cn) Received: from loongson.cn (unknown [10.40.24.149]) by gateway (Coremail) with SMTP id _____8BxLtuoF25jnhUGAA--.19136S3; Fri, 11 Nov 2022 17:36:40 +0800 (CST) Received: from lichao-PC (unknown [10.40.24.149]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Cxb+KnF25jx9EQAA--.46285S2; Fri, 11 Nov 2022 17:36:39 +0800 (CST) Date: Fri, 11 Nov 2022 17:36:39 +0800 From: "Chao Li" To: xianglai li Cc: "=?utf-8?Q?devel=40edk2.groups.io?=" , Bibo Mao , Leif Lindholm , Liming Gao , Michael D Kinney Message-ID: <93476F0F-6845-45AE-B609-B3BCC63CAB30@getmailspring.com> In-Reply-To: <2b938c55024c6e6207196ca6a70e27744742070b.1668157715.git.lixianglai@loongson.cn> References: <2b938c55024c6e6207196ca6a70e27744742070b.1668157715.git.lixianglai@loongson.cn> Subject: Re: [edk2-platforms][PATCH V5 04/15] Platform/Loongson: Add QemuFwCfgLib. X-Mailer: Mailspring MIME-Version: 1.0 X-CM-TRANSID: AQAAf8Cxb+KnF25jx9EQAA--.46285S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQAHCGNs6eQZ0AAVsQ X-Coremail-Antispam: 1Uk129KBjvAXoWfXr4UKryDGFWrKw18XF4DXFb_yoW8tFWxGo W8ZF97Aw15tw4rW34I9Fn3W3y8Jayjgr4rXF4FyF4UtFn8tF4Y9FW3ta4UGFnYyw1Fy34k A395X3yfZFZayrs5n29KB7ZKAUJUUUUP529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ec02F40Eb7x2x7xS6r1j6r4UMc02F40EFcxC0VAKzVAqx4xG6I80ewAqx4xG64kEw2xG 04xIwI0_Xr0_WrUv73VFW2AGmfu7bjvjm3AaLaJ3UjIYCTnIWjp_UUUOf7kC6x804xWl14 x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWU XVWUAwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84ACjcxK6xIIjxv20xvE14 v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4j6F4UM28EF7xvwVC2z280aVAF wI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVWxJr0_GcWln4kS14v26r1q6r43M2 AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx1l5I8CrVAYj202 j2C_Jr0_Gr1l5I8CrVACY4xI64kE6c02F40Ex7xfMc02F40Ew4AK048IF2xKxVW5JVWrJw Av7VC0I7IYx2IY67AKxVWUtVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JMx8GjcxK6IxK0xIIj40E5I8CrwCY1x0262kKe7AKxV WUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E 14v26r106r1rMI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F 4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jf6p9U UUUU= Content-Type: multipart/alternative; boundary="636e17a7_455d779_1e57b" --636e17a7_455d779_1e57b Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Reviewed-by: Chao Li Thanks, Chao -------- On 11=E6=9C=88 11 2022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li wrote: > Qemu=46wCfgLib for PEI phase. > > This library obtains the Qemu=46WCfg base address by > directly parsing the fdt, and reads and writes the data > in the Qemu=46WCfg by operating on the Qemu=46WCfg base address. > > > RE=46: https://bugzilla.tianocore.org/show=5Fbug.cgi=3Fid=3D4054 > > > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > --- > .../Include/Library/Qemu=46wCfgLib.h =7C 174 +++++++ > .../Qemu=46wCfgLib/Qemu=46wCfgLibInternal.h =7C 63 +++ > .../Library/Qemu=46wCfgLib/Qemu=46wCfgPei.c =7C 117 +++++ > .../Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.c =7C 463 ++++++++++++++++= ++ > .../Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.inf =7C 46 ++ > 5 files changed, 863 insertions(+) > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Q= emu=46wCfgLib.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wC= fgLib/Qemu=46wCfgLibInternal.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wC= fgLib/Qemu=46wCfgPei.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wC= fgLib/Qemu=46wCfgPeiLib.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wC= fgLib/Qemu=46wCfgPeiLib.inf > > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu=46= wCfgLib.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu=46wCf= gLib.h > new file mode 100644 > index 0000000000..11da4d0b8a > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu=46wCfgLib= .h > =40=40 -0,0 +1,174 =40=40 > +/** =40file > + QEMU/KVM =46irmware Configuration access > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - =46W or =46w - =46irmware > + - Cfg - Configure > +**/ > + > +=23ifndef QEMU=5F=46W=5FC=46G=5FLIB=5F > +=23define QEMU=5F=46W=5FC=46G=5FLIB=5F > + > +=23include > + > +typedef enum =7B > + EfiAcpiAddressRangeMemory =3D 1, > + EfiAcpiAddressRangeReserved =3D 2, > + EfiAcpiAddressRangeACPI =3D 3, > + EfiAcpiAddressRangeNVS =3D 4 > +=7D E=46I=5FACPI=5FMEMORY=5FTYPE; > + > +typedef struct =7B > + UINT64 BaseAddr; > + UINT64 Length; > + UINT32 Type; > + UINT32 Reserved; > +=7D LOONGARCH=5FMEMMAP=5FENTRY; > + > +/** > + Returns a boolean indicating if the firmware configuration interface > + is available or not. > + > + This function may change fw=5Fcfg state. > + > + =40retval TRUE The interface is available > + =40retval =46ALSE The interface is not available > +**/ > +BOOLEAN > +E=46IAPI > +Qemu=46wCfgIsAvailable ( > + VOID > + ); > + > +/** > + Selects a firmware configuration item for reading. > + > + =46ollowing this call, any data read from this item will start from > + the beginning of the configuration item's data. > + > + =40param=5Bin=5D Qemu=46wCfgItem - =46irmware Configuration item to r= ead > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgSelectItem ( > + IN =46IRMWARE=5FCON=46IG=5FITEM Qemu=46wCfgItem > + ); > + > +/** > + 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. > + > + =40param=5Bin=5D Size - Size in bytes to read > + =40param=5Bin=5D Buffer - Buffer to store data into > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgReadBytes ( > + 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. > + > + =40param=5Bin=5D Size - Size in bytes to write > + =40param=5Bin=5D Buffer - Buffer to read data from > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ); > + > +/** > + Skip bytes in the firmware configuration item. > + > + Increase the offset of the firmware configuration item without transf= erring > + bytes between the item and a caller-provided buffer. Subsequent read,= write > + or skip operations will commence at the increased offset. > + > + =40param=5Bin=5D Size Number of bytes to skip. > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgSkipBytes ( > + IN UINTN Size > + ); > + > +/** > + Reads a UINT8 firmware configuration value > + > + =40retval Value of =46irmware Configuration item read > +**/ > +UINT8 > +E=46IAPI > +Qemu=46wCfgRead8 ( > + VOID > + ); > + > +/** > + Reads a UINT16 firmware configuration value > + > + =40retval Value of =46irmware Configuration item read > +**/ > +UINT16 > +E=46IAPI > +Qemu=46wCfgRead16 ( > + VOID > + ); > + > +/** > + Reads a UINT32 firmware configuration value > + > + =40retval Value of =46irmware Configuration item read > +**/ > +UINT32 > +E=46IAPI > +Qemu=46wCfgRead32 ( > + VOID > + ); > + > +/** > + Reads a UINT64 firmware configuration value > + > + =40retval Value of =46irmware Configuration item read > +**/ > +UINT64 > +E=46IAPI > +Qemu=46wCfgRead64 ( > + VOID > + ); > + > +/** > + =46ind the configuration item corresponding to the firmware configura= tion file. > + > + =40param=5Bin=5D Name - Name of file to look up. > + =40param=5Bout=5D Item - Configuration item corresponding to the file= , to be passed > + to Qemu=46wCfgSelectItem (). > + =40param=5Bout=5D Size - Number of bytes in the file. > + > + =40retval RETURN=5FSUCCESS If file is found. > + RETURN=5FNOT=5F=46OUND If file is not found. > + RETURN=5FUNSUPPORTED If firmware configuration is unavailable. > +**/ > +RETURN=5FSTATUS > +E=46IAPI > +Qemu=46wCfg=46ind=46ile ( > + IN CONST CHAR8 *Name, > + OUT =46IRMWARE=5FCON=46IG=5FITEM *Item, > + OUT UINTN *Size > + ); > + > +=23endif // QEMU=5F=46W=5FC=46G=5FLIB=5F > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/= Qemu=46wCfgLibInternal.h b/Platform/Loongson/LoongArchQemuPkg/Library/Qem= u=46wCfgLib/Qemu=46wCfgLibInternal.h > new file mode 100644 > index 0000000000..229c080961 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgLibInternal.h > =40=40 -0,0 +1,63 =40=40 > +/** =40file > + fw=5Fcfg library implementation. > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - =46wCfg - firmWare Configure > +**/ > + > +=23ifndef QEMU=5F=46W=5FC=46G=5FLIB=5FINTERNAL=5FH=5F > +=23define QEMU=5F=46W=5FC=46G=5FLIB=5FINTERNAL=5FH=5F > + > +/** > + Returns a boolean indicating if the firmware configuration interface = is > + available for library-internal purposes. > + > + This function never changes fw=5Fcfg state. > + > + =40retval TRUE The interface is available internally. > + =40retval =46ALSE The interface is not available internally. > +**/ > +BOOLEAN > +InternalQemu=46wCfgIsAvailable ( > + VOID > + ); > + > +/** > + Returns a boolean indicating whether QEMU provides the DMA-like acces= s method > + for fw=5Fcfg. > + > + =40retval TRUE The DMA-like access method is available. > + =40retval =46ALSE The DMA-like access method is unavailable. > +**/ > +BOOLEAN > +InternalQemu=46wCfgDmaIsAvailable ( > + VOID > + ); > + > +/** > + Transfer an array of bytes, or skip a number of bytes, using the DMA > + interface. > + > + =40param=5Bin=5D Size Size in bytes to transfer or skip. > + > + =40param=5Bin,out=5D Buffer Buffer to read data into or write data fr= om. Ignored, > + and may be NULL, if Size is zero, or Control is > + =46W=5FC=46G=5FDMA=5FCTL=5FSKIP. > + > + =40param=5Bin=5D Control One of the following: > + =46W=5FC=46G=5FDMA=5FCTL=5FWRITE - write to fw=5Fcfg from Buffer. > + =46W=5FC=46G=5FDMA=5FCTL=5FREAD - read from fw=5Fcfg into Buffer. > + =46W=5FC=46G=5FDMA=5FCTL=5FSKIP - skip bytes in fw=5Fcfg. > +**/ > +VOID > +InternalQemu=46wCfgDmaBytes ( > + IN UINT32 Size, > + IN OUT VOID *Buffer OPTIONAL, > + IN UINT32 Control > + ); > + > +=23endif // QEMU=5F=46W=5FC=46G=5FLIB=5FINTERNAL=5FH=5F > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/= Qemu=46wCfgPei.c b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfg= Lib/Qemu=46wCfgPei.c > new file mode 100644 > index 0000000000..b170c953f3 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgPei.c > =40=40 -0,0 +1,117 =40=40 > +/** =40file > + fw=5Fcfg library implementation. > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - =46wCfg - firmWare Configure > +**/ > + > +=23include > +=23include > +=23include > + > +=23include =22Qemu=46wCfgLibInternal.h=22 > + > +/** > + Returns a boolean indicating if the firmware configuration interface > + is available or not. > + > + This function may change fw=5Fcfg state. > + > + =40retval TRUE The interface is available > + =40retval =46ALSE The interface is not available > +**/ > +BOOLEAN > +E=46IAPI > +Qemu=46wCfgIsAvailable ( > + VOID > + ) > +=7B > + UINT32 Signature; > + UINT32 Revision; > + > + Qemu=46wCfgSelectItem (Qemu=46wCfgItemSignature); > + Signature =3D Qemu=46wCfgRead32 (); > + DEBUG ((DEBUG=5FIN=46O, =22=46W C=46G Signature: 0x%x=5Cn=22, Signatu= re)); > + Qemu=46wCfgSelectItem (Qemu=46wCfgItemInterfaceVersion); > + Revision =3D Qemu=46wCfgRead32 (); > + DEBUG ((DEBUG=5FIN=46O, =22=46W C=46G Revision: 0x%x=5Cn=22, Revision= )); > + if ((Signature =21=3D SIGNATURE=5F32 ('Q', 'E', 'M', 'U')) > + =7C=7C (Revision < 1)) > + =7B > + DEBUG ((DEBUG=5FIN=46O, =22Qemu=46wCfg interface not supported.=5Cn=22= )); > + return =46ALSE; > + =7D > + > + DEBUG ((DEBUG=5FIN=46O, =22Qemu=46wCfg interface is supported.=5Cn=22= )); > + return TRUE; > +=7D > + > +/** > + Returns a boolean indicating if the firmware configuration interface = is > + available for library-internal purposes. > + > + This function never changes fw=5Fcfg state. > + > + =40retval TRUE The interface is available internally. > + =40retval =46ALSE The interface is not available internally. > +**/ > +BOOLEAN > +InternalQemu=46wCfgIsAvailable ( > + VOID > + ) > +=7B > + // > + // We always return TRUE, because the consumer of this library ought = to have > + // called Qemu=46wCfgIsAvailable before making other calls which woul= d hit this > + // path. > + // > + return TRUE; > +=7D > + > +/** > + Returns a boolean indicating whether QEMU provides the DMA-like acces= s method > + for fw=5Fcfg. > + > + =40retval TRUE The DMA-like access method is available. > + =40retval =46ALSE The DMA-like access method is unavailable. > +**/ > +BOOLEAN > +InternalQemu=46wCfgDmaIsAvailable ( > + VOID > + ) > +=7B > + return =46ALSE; > +=7D > + > +/** > + Transfer an array of bytes, or skip a number of bytes, using the DMA > + interface. > + > + =40param=5Bin=5D Size Size in bytes to transfer or skip. > + > + =40param=5Bin, out=5D Buffer Buffer to read data into or write data f= rom. Ignored, > + and may be NULL, if Size is zero, or Control is > + =46W=5FC=46G=5FDMA=5FCTL=5FSKIP. > + > + =40param=5Bin=5D Control One of the following: > + =46W=5FC=46G=5FDMA=5FCTL=5FWRITE - write to fw=5Fcfg from Buffer. > + =46W=5FC=46G=5FDMA=5FCTL=5FREAD - read from fw=5Fcfg into Buffer. > + =46W=5FC=46G=5FDMA=5FCTL=5FSKIP - skip bytes in fw=5Fcfg. > +**/ > +VOID > +InternalQemu=46wCfgDmaBytes ( > + IN UINT32 Size, > + IN OUT VOID *Buffer OPTIONAL, > + IN UINT32 Control > + ) > +=7B > + // > + // We should never reach here > + // > + ASSERT (=46ALSE); > + CpuDeadLoop (); > +=7D > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/= Qemu=46wCfgPeiLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46w= CfgLib/Qemu=46wCfgPeiLib.c > new file mode 100644 > index 0000000000..5593856b82 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgPeiLib.c > =40=40 -0,0 +1,463 =40=40 > +/** =40file > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - =46wCfg - firmWare Configure > + - CTL - Control > +**/ > + > +=23include =22Uefi.h=22 > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include =22Qemu=46wCfgLibInternal.h=22 > + > +STATIC UINTN m=46wCfgSelectorAddress; > +STATIC UINTN m=46wCfgDataAddress; > +/** > + To get firmware configure selector address. > + > + =40param VOID > + > + =40retval firmware configure selector address > +**/ > +UINTN > +E=46IAPI > +QemuGet=46wCfgSelectorAddress ( > + VOID > + ) > +=7B > + UINTN =46wCfgSelectorAddress =3D m=46wCfgSelectorAddress; > + if (=46wCfgSelectorAddress =3D=3D 0) =7B > + =46wCfgSelectorAddress =3D (UINTN)PcdGet64 (Pcd=46wCfgSelectorAddress= ); > + =7D > + return =46wCfgSelectorAddress; > +=7D > +/** > + To get firmware configure Data address. > + > + =40param VOID > + > + =40retval firmware configure data address > +**/ > +UINTN > +E=46IAPI > +QemuGet=46wCfgDataAddress ( > + VOID > + ) > +=7B > + UINTN =46wCfgDataAddress =3D m=46wCfgDataAddress; > + if (=46wCfgDataAddress =3D=3D 0) =7B > + =46wCfgDataAddress =3D (UINTN)PcdGet64 (Pcd=46wCfgDataAddress); > + =7D > + return =46wCfgDataAddress; > +=7D > +/** > + Selects a firmware configuration item for reading. > + > + =46ollowing this call, any data read from this item will start from > + the beginning of the configuration item's data. > + > + =40param=5Bin=5D Qemu=46wCfgItem - =46irmware Configuration item to r= ead > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgSelectItem ( > + IN =46IRMWARE=5FCON=46IG=5FITEM Qemu=46wCfgItem > + ) > +=7B > + UINTN =46wCfgSelectorAddress; > + =46wCfgSelectorAddress =3D QemuGet=46wCfgSelectorAddress (); > + MmioWrite16 (=46wCfgSelectorAddress, SwapBytes16((UINT16) (UINTN)Qemu= =46wCfgItem)); > +=7D > + > +/** > + Slow READ=5FBYTES=5F=46UNCTION. > + > + =40param=5Bin=5D The size of the data to be read. > + =40param=5Bin=5D Buffer The buffer that stores the readout data. > +**/ > +VOID > +E=46IAPI > +MmioReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +=7B > + UINTN Left; > + UINT8 *Ptr; > + UINT8 *End; > + UINTN =46wCfgDataAddress; > + Left =3D Size & 7; > + > + Size -=3D Left; > + Ptr =3D Buffer; > + End =3D Ptr + Size; > + =46wCfgDataAddress =3D QemuGet=46wCfgDataAddress (); > + while (Ptr < End) =7B > + *(UINT64 *)Ptr =3D MmioRead64 (=46wCfgDataAddress); > + Ptr +=3D 8; > + =7D > + if (Left & 4) =7B > + *(UINT32 *)Ptr =3D MmioRead32 (=46wCfgDataAddress); > + Ptr +=3D 4; > + =7D > + if (Left & 2) =7B > + *(UINT16 *)Ptr =3D MmioRead16 (=46wCfgDataAddress); > + Ptr +=3D 2; > + =7D > + if (Left & 1) =7B > + *Ptr =3D MmioRead8 (=46wCfgDataAddress); > + =7D > +=7D > + > +/** > + Slow WRITE=5FBYTES=5F=46UNCTION. > + > + =40param=5Bin=5D The size of the data to be write. > + =40param=5Bin=5D Buffer The buffer that stores the writein data. > +**/ > +VOID > +E=46IAPI > +MmioWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +=7B > + UINTN Idx; > + UINTN =46wCfgDataAddress; > + =46wCfgDataAddress =3D QemuGet=46wCfgDataAddress (); > + for (Idx =3D 0; Idx < Size; ++Idx) =7B > + MmioWrite8 (=46wCfgDataAddress, ((UINT8 *)Buffer)=5BIdx=5D); > + =7D > +=7D > + > +/** > + Reads firmware configuration bytes into a buffer > + > + =40param=5Bin=5D Size - Size in bytes to read > + =40param=5Bin=5D Buffer - Buffer to store data into (OPTIONAL if Size= is 0) > +**/ > +VOID > +E=46IAPI > +InternalQemu=46wCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +=7B > + if ((InternalQemu=46wCfgDmaIsAvailable ()) > + && (Size <=3D MAX=5FUINT32)) > + =7B > + InternalQemu=46wCfgDmaBytes ((UINT32)Size, Buffer, =46W=5FC=46G=5FDMA= =5FCTL=5FREAD); > + return; > + =7D > + MmioReadBytes (Size, Buffer); > +=7D > + > +/** > + 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. > + > + =40param=5Bin=5D Size - Size in bytes to read > + =40param=5Bin=5D Buffer - Buffer to store data into > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +=7B > + if (InternalQemu=46wCfgIsAvailable ()) =7B > + InternalQemu=46wCfgReadBytes (Size, Buffer); > + =7D else =7B > + ZeroMem (Buffer, Size); > + =7D > +=7D > + > +/** > + 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. > + > + =40param=5Bin=5D Size - Size in bytes to write > + =40param=5Bin=5D Buffer - Buffer to read data from > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +=7B > + if (InternalQemu=46wCfgIsAvailable ()) =7B > + if ((InternalQemu=46wCfgDmaIsAvailable ()) > + && (Size <=3D MAX=5FUINT32)) > + =7B > + InternalQemu=46wCfgDmaBytes ((UINT32)Size, Buffer, =46W=5FC=46G=5FDMA= =5FCTL=5FWRITE); > + return; > + =7D > + MmioWriteBytes (Size, Buffer); > + =7D > +=7D > + > +/** > + Skip bytes in the firmware configuration item. > + > + Increase the offset of the firmware configuration item without transf= erring > + bytes between the item and a caller-provided buffer. Subsequent read,= write > + or skip operations will commence at the increased offset. > + > + =40param=5Bin=5D Size Number of bytes to skip. > +**/ > +VOID > +E=46IAPI > +Qemu=46wCfgSkipBytes ( > + IN UINTN Size > + ) > +=7B > + UINTN ChunkSize; > + UINT8 SkipBuffer=5B256=5D; > + > + if (=21InternalQemu=46wCfgIsAvailable ()) =7B > + return; > + =7D > + > + if ((InternalQemu=46wCfgDmaIsAvailable ()) > + && (Size <=3D MAX=5FUINT32)) > + =7B > + InternalQemu=46wCfgDmaBytes ((UINT32)Size, NULL, =46W=5FC=46G=5FDMA=5F= CTL=5FSKIP); > + return; > + =7D > + > + // > + // Emulate the skip by reading data in chunks, and throwing it away. = The > + // implementation below is suitable even for phases where RAM or dyna= mic > + // allocation is not available or appropriate. It also doesn't affect= the > + // static data footprint for client modules. Large skips are not expe= cted, > + // therefore this fallback is not performance critical. The size of > + // SkipBuffer is thought not to exert a large pressure on the stack i= n any > + // phase. > + // > + while (Size > 0) =7B > + ChunkSize =3D MIN (Size, sizeof SkipBuffer); > + MmioReadBytes (ChunkSize, SkipBuffer); > + Size -=3D ChunkSize; > + =7D > +=7D > + > +/** > + Reads a UINT8 firmware configuration value > + > + =40return Value of =46irmware Configuration item read > +**/ > +UINT8 > +E=46IAPI > +Qemu=46wCfgRead8 ( > + VOID > + ) > +=7B > + UINT8 Result; > + > + Qemu=46wCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +=7D > + > +/** > + Reads a UINT16 firmware configuration value > + > + =40return Value of =46irmware Configuration item read > +**/ > +UINT16 > +E=46IAPI > +Qemu=46wCfgRead16 ( > + VOID > + ) > +=7B > + UINT16 Result; > + > + Qemu=46wCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +=7D > + > +/** > + Reads a UINT32 firmware configuration value > + > + =40return Value of =46irmware Configuration item read > +**/ > +UINT32 > +E=46IAPI > +Qemu=46wCfgRead32 ( > + VOID > + ) > +=7B > + UINT32 Result; > + > + Qemu=46wCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +=7D > + > +/** > + Reads a UINT64 firmware configuration value > + > + =40return Value of =46irmware Configuration item read > +**/ > +UINT64 > +E=46IAPI > +Qemu=46wCfgRead64 ( > + VOID > + ) > +=7B > + UINT64 Result; > + > + Qemu=46wCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +=7D > + > +/** > + =46ind the configuration item corresponding to the firmware configura= tion file. > + > + =40param=5Bin=5D Name - Name of file to look up. > + =40param=5Bout=5D Item - Configuration item corresponding to the file= , to be passed > + to Qemu=46wCfgSelectItem (). > + =40param=5Bout=5D Size - Number of bytes in the file. > + > + =40return RETURN=5FSUCCESS If file is found. > + RETURN=5FNOT=5F=46OUND If file is not found. > + RETURN=5FUNSUPPORTED If firmware configuration is unavailable. > +**/ > +RETURN=5FSTATUS > +E=46IAPI > +Qemu=46wCfg=46ind=46ile ( > + IN CONST CHAR8 *Name, > + OUT =46IRMWARE=5FCON=46IG=5FITEM *Item, > + OUT UINTN *Size > + ) > +=7B > + UINT32 Count; > + UINT32 Idx; > + > + if (=21InternalQemu=46wCfgIsAvailable ()) =7B > + return RETURN=5FUNSUPPORTED; > + =7D > + > + Qemu=46wCfgSelectItem (Qemu=46wCfgItem=46ileDir); > + Count =3D SwapBytes32 (Qemu=46wCfgRead32 ()); > + > + for (Idx =3D 0; Idx < Count; ++Idx) =7B > + UINT32 =46ileSize; > + UINT16 =46ileSelect; > + CHAR8 =46ileName=5BQEMU=5F=46W=5FC=46G=5F=46NAME=5FSIZE=5D; > + > + =46ileSize =3D Qemu=46wCfgRead32 (); > + =46ileSelect =3D Qemu=46wCfgRead16 (); > + Qemu=46wCfgRead16 (); // skip the field called =22reserved=22 > + InternalQemu=46wCfgReadBytes (sizeof (=46ileName), =46ileName); > + > + if (AsciiStrCmp (Name, =46ileName) =3D=3D 0) =7B > + *Item =3D SwapBytes16 (=46ileSelect); > + *Size =3D SwapBytes32 (=46ileSize); > + return RETURN=5FSUCCESS; > + =7D > + =7D > + > + return RETURN=5FNOT=5F=46OUND; > +=7D > + > +/** > + firmware config initialize. > + > + =40param VOID > + > + =40return RETURN=5FSUCCESS Initialization succeeded. > +**/ > +RETURN=5FSTATUS > +E=46IAPI > +Qemu=46wCfgInitialize ( > + VOID > + ) > +=7B > + VOID *DeviceTreeBase; > + INT32 Node; > + INT32 Prev; > + CONST CHAR8 *Type; > + INT32 Len; > + CONST UINT64 *RegProp; > + UINT64 =46wCfgSelectorAddress; > + UINT64 =46wCfgDataAddress; > + UINT64 =46wCfgDataSize; > + RETURN=5FSTATUS PcdStatus; > + > + DeviceTreeBase =3D (VOID *) (UINTN)PcdGet64 (PcdDeviceTreeBase); > + ASSERT (DeviceTreeBase =21=3D NULL); > + // > + // Make sure we have a valid device tree blob > + // > + ASSERT (fdt=5Fcheck=5Fheader (DeviceTreeBase) =3D=3D 0); > + > + for (Prev =3D 0;; Prev =3D Node) =7B > + Node =3D fdt=5Fnext=5Fnode (DeviceTreeBase, Prev, NULL); > + if (Node < 0) =7B > + break; > + =7D > + > + // > + // Check for memory node > + // > + Type =3D fdt=5Fgetprop (DeviceTreeBase, Node, =22compatible=22, &Len)= ; > + if ((Type) > + && (AsciiStrnCmp (Type, =22qemu,fw-cfg-mmio=22, Len) =3D=3D 0)) > + =7B > + // > + // Get the 'reg' property of this node. =46or now, we will assume > + // two 8 byte quantities for base and size, respectively. > + // > + RegProp =3D fdt=5Fgetprop (DeviceTreeBase, Node, =22reg=22, &Len); > + if ((RegProp =21=3D 0) > + && (Len =3D=3D (2 * sizeof (UINT64)))) > + =7B > + =46wCfgDataAddress =3D SwapBytes64 (RegProp=5B0=5D); > + =46wCfgDataSize =3D 8; > + =46wCfgSelectorAddress =3D =46wCfgDataAddress + =46wCfgDataSize; > + > + m=46wCfgSelectorAddress =3D =46wCfgSelectorAddress; > + m=46wCfgDataAddress =3D =46wCfgDataAddress; > + > + PcdStatus =3D PcdSet64S ( > + Pcd=46wCfgSelectorAddress, > + =46wCfgSelectorAddress > + ); > + ASSERT=5FRETURN=5FERROR (PcdStatus); > + PcdStatus =3D PcdSet64S ( > + Pcd=46wCfgDataAddress, > + =46wCfgDataAddress > + ); > + ASSERT=5FRETURN=5FERROR (PcdStatus); > + break; > + =7D else =7B > + DEBUG ((DEBUG=5FERROR, =22%a: =46ailed to parse =46DT QemuCfg node=5C= n=22, > + =5F=5F=46UNCTION=5F=5F)); > + break; > + =7D > + =7D > + =7D > + return RETURN=5FSUCCESS; > +=7D > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/= Qemu=46wCfgPeiLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46= wCfgLib/Qemu=46wCfgPeiLib.inf > new file mode 100644 > index 0000000000..8609d615e7 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgPeiLib.inf > =40=40 -0,0 +1,46 =40=40 > +=23=23 =40file > +=23 initialized fw=5Fcfg library. > +=23 > +=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.
> +=23 > +=23 SPDX-License-Identifier: BSD-2-Clause-Patent > +=23 > +=23=23 > + > +=5BDefines=5D > + IN=46=5FVERSION =3D 0x00010005 > + BASE=5FNAME =3D Qemu=46wCfgSecLib > + =46ILE=5FGUID =3D cdf9a9d5-7422-4dcb-b41d-607151ad320b > + MODULE=5FTYPE =3D BASE > + VERSION=5FSTRING =3D 1.0 > + LIBRARY=5FCLASS =3D Qemu=46wCfgLib=7CPEIM > + CONSTRUCTOR =3D Qemu=46wCfgInitialize > + > +=23 > +=23 VALID=5FARCHITECTURES =3D LOONGARCH64 > +=23 > + > +=5BSources=5D > + Qemu=46wCfgLibInternal.h > + Qemu=46wCfgPeiLib.c > + Qemu=46wCfgPei.c > + > +=5BPackages=5D > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec > + > +=5BLibraryClasses=5D > + BaseLib > + BaseMemoryLib > + DebugLib > + IoLib > + MemoryAllocationLib > + =46dtLib > + PcdLib > + > +=5BPcd=5D > + gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase > + gLoongArchQemuPkgTokenSpaceGuid.Pcd=46wCfgSelectorAddress > + gLoongArchQemuPkgTokenSpaceGuid.Pcd=46wCfgDataAddress > -- > 2.31.1 --636e17a7_455d779_1e57b Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline
Reviewed-by: Chao Li  <lichao=40loongson.cn>


Thanks,
Chao
--------

On 11=E6=9C=88 11 2= 022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li <lixianglai=40loongson.cn= > wrote:
Qemu=46wCfgLib for PEI phase.
This library obtains the Qemu=46WCfg base address by

<= div>directly parsing the fdt, and reads and writes the data

in the Qemu=46WCfg by operating on the Qemu=46WCfg base address.


RE=46: https://bugzilla.tianocore.org/show=5Fbug.cgi=3Fid=3D= 4054



Cc: Bibo Mao <maobibo=40loongson.cn>
Cc: Chao Li <lichao=40loongson.cn>

Cc: Lei= f Lindholm <quic=5Fllindhol=40quicinc.com>

Cc: Liming= Gao <gaoliming=40byosoft.com.cn>

Cc: Michael D Kinne= y <michael.d.kinney=40intel.com>

Signed-off-by: xiang= lai li <lixianglai=40loongson.cn>

---

.= ../Include/Library/Qemu=46wCfgLib.h =7C 174 +++++++

.../Qem= u=46wCfgLib/Qemu=46wCfgLibInternal.h =7C 63 +++

.../Library= /Qemu=46wCfgLib/Qemu=46wCfgPei.c =7C 117 +++++

.../Library/= Qemu=46wCfgLib/Qemu=46wCfgPeiLib.c =7C 463 ++++++++++++++++++

.../Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.inf =7C 46 ++

5 files changed, 863 insertions(+)
create mode 100644 Pl= atform/Loongson/LoongArchQemuPkg/Include/Library/Qemu=46wCfgLib.h
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Qemu= =46wCfgLib/Qemu=46wCfgLibInternal.h

create mode 100644 Plat= form/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPei.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library= /Qemu=46wCfgLib/Qemu=46wCfgPeiLib.c

create mode 100644 Plat= form/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.i= nf



diff --git a/Platform/Loongson/LoongArchQemuPkg/= Include/Library/Qemu=46wCfgLib.h b/Platform/Loongson/LoongArchQemuPkg/Inc= lude/Library/Qemu=46wCfgLib.h

new file mode 100644
index 0000000000..11da4d0b8a

--- /dev/null

<= div>+++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/Qemu=46wCfgL= ib.h

=40=40 -0,0 +1,174 =40=40

+/** =40file
+ QEMU/KVM =46irmware Configuration access

+
+ Copyright (c) 2022 Loongson Technology Corporation Limited= . All rights reserved.<BR>

+

+ SPDX-Lic= ense-Identifier: BSD-2-Clause-Patent

+

+ =40p= ar Glossary:

+ - =46W or =46w - =46irmware

+ = - Cfg - Configure

+**/

+

+=23if= ndef QEMU=5F=46W=5FC=46G=5FLIB=5F

+=23define QEMU=5F=46W=5F= C=46G=5FLIB=5F

+

+=23include <IndustryStan= dard/Qemu=46wCfg.h>

+

+typedef enum =7B
+ EfiAcpiAddressRangeMemory =3D 1,

+ EfiAcpiAdd= ressRangeReserved =3D 2,

+ EfiAcpiAddressRangeACPI =3D 3,
+ EfiAcpiAddressRangeNVS =3D 4

+=7D E=46I=5FAC= PI=5FMEMORY=5FTYPE;

+

+typedef struct =7B
+ UINT64 BaseAddr;

+ UINT64 Length;

+ UINT32 Type;

+ UINT32 Reserved;

+=7D LOON= GARCH=5FMEMMAP=5FENTRY;

+

+/**

= + Returns a boolean indicating if the firmware configuration interface
+ is available or not.

+

+ This f= unction may change fw=5Fcfg state.

+

+ =40ret= val TRUE The interface is available

+ =40retval =46ALSE The= interface is not available

+**/

+BOOLEAN
+E=46IAPI

+Qemu=46wCfgIsAvailable (

+ VOID

+ );

+

+/**

<= div>+ Selects a firmware configuration item for reading.

+<= /div>
+ =46ollowing this call, any data read from this item will = start from

+ the beginning of the configuration item's data= .

+

+ =40param=5Bin=5D Qemu=46wCfgItem - =46i= rmware Configuration item to read

+**/

+VOID<= /div>
+E=46IAPI

+Qemu=46wCfgSelectItem (

<= div>+ IN =46IRMWARE=5FCON=46IG=5FITEM Qemu=46wCfgItem

+ );<= /div>
+

+/**

+ Reads firmware configu= ration bytes into a buffer

+

+ If called mult= iple times, then the data read will

+ continue at the offse= t of the firmware configuration

+ item where the previous r= ead ended.

+

+ =40param=5Bin=5D Size - Size i= n bytes to read

+ =40param=5Bin=5D Buffer - Buffer to store= data into

+**/

+VOID

+E=46IAPI=

+Qemu=46wCfgReadBytes (

+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL

+ );

+<= /div>
+/**

+ Writes firmware configuration bytes fr= om a buffer

+

+ If called multiple times, the= n the data written will

+ continue at the offset of the fir= mware configuration

+ item where the previous write ended.<= /div>
+

+ =40param=5Bin=5D Size - Size in bytes to = write

+ =40param=5Bin=5D Buffer - Buffer to read data from<= /div>
+**/

+VOID

+E=46IAPI

<= div>+Qemu=46wCfgWriteBytes (

+ IN UINTN Size,

+ IN VOID *Buffer

+ );

+

+/**<= /div>
+ Skip bytes in the firmware configuration item.

<= div>+

+ Increase the offset of the firmware configuration i= tem without transferring

+ bytes between the item and a cal= ler-provided buffer. Subsequent read, write

+ or skip opera= tions will commence at the increased offset.

+

+ =40param=5Bin=5D Size Number of bytes to skip.

+**/
+VOID

+E=46IAPI

+Qemu=46wCfgSkipBy= tes (

+ IN UINTN Size

+ );

+
+/**

+ Reads a UINT8 firmware configuration val= ue

+

+ =40retval Value of =46irmware Configur= ation item read

+**/

+UINT8

+E=46= IAPI

+Qemu=46wCfgRead8 (

+ VOID

+ );

+

+/**

+ Reads a UINT16 f= irmware configuration value

+

+ =40retval Val= ue of =46irmware Configuration item read

+**/

+UINT16

+E=46IAPI

+Qemu=46wCfgRead16 (
=
+ VOID

+ );

+

+/**
+ Reads a UINT32 firmware configuration value

+<= /div>
+ =40retval Value of =46irmware Configuration item read
+**/

+UINT32

+E=46IAPI

+Qemu=46wCfgRead32 (

+ VOID

+ );

=
+

+/**

+ Reads a UINT64 firmware configu= ration value

+

+ =40retval Value of =46irmwar= e Configuration item read

+**/

+UINT64
<= br>
+E=46IAPI

+Qemu=46wCfgRead64 (

+ VOID=

+ );

+

+/**

+ =46= ind the configuration item corresponding to the firmware configuration fi= le.

+

+ =40param=5Bin=5D Name - Name of file = to look up.

+ =40param=5Bout=5D Item - Configuration item c= orresponding to the file, to be passed

+ to Qemu=46wCfgSele= ctItem ().

+ =40param=5Bout=5D Size - Number of bytes in th= e file.

+

+ =40retval RETURN=5FSUCCESS If fil= e is found.

+ RETURN=5FNOT=5F=46OUND If file is not found.<= /div>
+ RETURN=5FUNSUPPORTED If firmware configuration is unavail= able.

+**/

+RETURN=5FSTATUS

+E=46= IAPI

+Qemu=46wCfg=46ind=46ile (

+ IN CONST CH= AR8 *Name,

+ OUT =46IRMWARE=5FCON=46IG=5FITEM *Item,
<= br>
+ OUT UINTN *Size

+ );

+

+=23endif // QEMU=5F=46W=5FC=46G=5FLIB=5F

diff --git a/Pl= atform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgLibInt= ernal.h b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgLibInternal.h

new file mode 100644

index = 0000000000..229c080961

--- /dev/null

+++ b/Pl= atform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgLibInt= ernal.h

=40=40 -0,0 +1,63 =40=40

+/** =40file=

+ fw=5Fcfg library implementation.

+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All = rights reserved.<BR>

+

+ SPDX-License-I= dentifier: BSD-2-Clause-Patent

+

+ =40par Glo= ssary:

+ - =46wCfg - firmWare Configure

+**/<= /div>
+

+=23ifndef QEMU=5F=46W=5FC=46G=5FLIB=5FINTE= RNAL=5FH=5F

+=23define QEMU=5F=46W=5FC=46G=5FLIB=5FINTERNAL= =5FH=5F

+

+/**

+ Returns a bool= ean indicating if the firmware configuration interface is

+= available for library-internal purposes.

+

+= This function never changes fw=5Fcfg state.

+

+ =40retval TRUE The interface is available internally.

+= =40retval =46ALSE The interface is not available internally.

+**/

+BOOLEAN

+InternalQemu=46wCfgIsAvaila= ble (

+ VOID

+ );

+

+/**

+ Returns a boolean indicating whether QEMU provide= s the DMA-like access method

+ for fw=5Fcfg.

= +

+ =40retval TRUE The DMA-like access method is available.=

+ =40retval =46ALSE The DMA-like access method is unavaila= ble.

+**/

+BOOLEAN

+InternalQem= u=46wCfgDmaIsAvailable (

+ VOID

+ );
+

+/**

+ Transfer an array of bytes, or= skip a number of bytes, using the DMA

+ interface.
+

+ =40param=5Bin=5D Size Size in bytes to transfer = or skip.

+

+ =40param=5Bin,out=5D Buffer Buff= er to read data into or write data from. Ignored,

+ and may= be NULL, if Size is zero, or Control is

+ =46W=5FC=46G=5FD= MA=5FCTL=5FSKIP.

+

+ =40param=5Bin=5D Control= One of the following:

+ =46W=5FC=46G=5FDMA=5FCTL=5FWRITE -= write to fw=5Fcfg from Buffer.

+ =46W=5FC=46G=5FDMA=5FCTL=5F= READ - read from fw=5Fcfg into Buffer.

+ =46W=5FC=46G=5FDMA= =5FCTL=5FSKIP - skip bytes in fw=5Fcfg.

+**/

= +VOID

+InternalQemu=46wCfgDmaBytes (

+ IN UIN= T32 Size,

+ IN OUT VOID *Buffer OPTIONAL,

+ I= N UINT32 Control

+ );

+

+=23end= if // QEMU=5F=46W=5FC=46G=5FLIB=5FINTERNAL=5FH=5F

diff --gi= t a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfg= Pei.c b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgPei.c

new file mode 100644

index 00000000= 00..b170c953f3

--- /dev/null

+++ b/Platform/L= oongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPei.c
=40=40 -0,0 +1,117 =40=40

+/** =40file

= + fw=5Fcfg library implementation.

+

+ Copyri= ght (c) 2022 Loongson Technology Corporation Limited. All rights reserved= .<BR>

+

+ SPDX-License-Identifier: BSD-= 2-Clause-Patent

+

+ =40par Glossary:
+ - =46wCfg - firmWare Configure

+**/

+=

+=23include <Library/BaseLib.h>

+=23in= clude <Library/DebugLib.h>

+=23include <Library/Qe= mu=46wCfgLib.h>

+

+=23include =22Qemu=46wC= fgLibInternal.h=22

+

+/**

+ Ret= urns a boolean indicating if the firmware configuration interface
+ is available or not.

+

+ This functi= on may change fw=5Fcfg state.

+

+ =40retval T= RUE The interface is available

+ =40retval =46ALSE The inte= rface is not available

+**/

+BOOLEAN
+E=46IAPI

+Qemu=46wCfgIsAvailable (

+ V= OID

+ )

+=7B

+ UINT32 Signature= ;

+ UINT32 Revision;

+

+ Qemu=46= wCfgSelectItem (Qemu=46wCfgItemSignature);

+ Signature =3D = Qemu=46wCfgRead32 ();

+ DEBUG ((DEBUG=5FIN=46O, =22=46W C=46= G Signature: 0x%x=5Cn=22, Signature));

+ Qemu=46wCfgSelectI= tem (Qemu=46wCfgItemInterfaceVersion);

+ Revision =3D Qemu=46= wCfgRead32 ();

+ DEBUG ((DEBUG=5FIN=46O, =22=46W C=46G Revi= sion: 0x%x=5Cn=22, Revision));

+ if ((Signature =21=3D SIGN= ATURE=5F32 ('Q', 'E', 'M', 'U'))

+ =7C=7C (Revision < 1)= )

+ =7B

+ DEBUG ((DEBUG=5FIN=46O, =22Qemu=46w= Cfg interface not supported.=5Cn=22));

+ return =46ALSE;
+ =7D

+

+ DEBUG ((DEBUG=5FIN=46O,= =22Qemu=46wCfg interface is supported.=5Cn=22));

+ return = TRUE;

+=7D

+

+/**

+ Returns a boolean indicating if the firmware configuration interface i= s

+ available for library-internal purposes.

= +

+ This function never changes fw=5Fcfg state.

+

+ =40retval TRUE The interface is available internally= .

+ =40retval =46ALSE The interface is not available intern= ally.

+**/

+BOOLEAN

+InternalQe= mu=46wCfgIsAvailable (

+ VOID

+ )

+=7B

+ //

+ // We always return TRUE, beca= use the consumer of this library ought to have

+ // called = Qemu=46wCfgIsAvailable before making other calls which would hit this
+ // path.

+ //

+ return TRUE;
+=7D

+

+/**

+ Return= s a boolean indicating whether QEMU provides the DMA-like access method
+ for fw=5Fcfg.

+

+ =40retval TR= UE The DMA-like access method is available.

+ =40retval =46= ALSE The DMA-like access method is unavailable.

+**/
<= br>
+BOOLEAN

+InternalQemu=46wCfgDmaIsAvailable (
=
+ VOID

+ )

+=7B

+ retu= rn =46ALSE;

+=7D

+

+/**
+ Transfer an array of bytes, or skip a number of bytes, using the= DMA

+ interface.

+

+ =40param=5B= in=5D Size Size in bytes to transfer or skip.

+

+ =40param=5Bin, out=5D Buffer Buffer to read data into or write data = from. Ignored,

+ and may be NULL, if Size is zero, or Contr= ol is

+ =46W=5FC=46G=5FDMA=5FCTL=5FSKIP.

+
+ =40param=5Bin=5D Control One of the following:

+ =46W=5FC=46G=5FDMA=5FCTL=5FWRITE - write to fw=5Fcfg from Buffer.
+ =46W=5FC=46G=5FDMA=5FCTL=5FREAD - read from fw=5Fcfg into Bu= ffer.

+ =46W=5FC=46G=5FDMA=5FCTL=5FSKIP - skip bytes in fw=5F= cfg.

+**/

+VOID

+InternalQemu=46= wCfgDmaBytes (

+ IN UINT32 Size,

+ IN OUT VOI= D *Buffer OPTIONAL,

+ IN UINT32 Control

+ )
+=7B

+ //

+ // We should never r= each here

+ //

+ ASSERT (=46ALSE);

<= div>+ CpuDeadLoop ();

+=7D

diff --git a/Platf= orm/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.c = b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPe= iLib.c

new file mode 100644

index 0000000000.= .5593856b82

--- /dev/null

+++ b/Platform/Loon= gson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46wCfgPeiLib.c
=40=40 -0,0 +1,463 =40=40

+/** =40file

= +

+ Copyright (c) 2022 Loongson Technology Corporation Limi= ted. All rights reserved.<BR>

+

+ SPDX-= License-Identifier: BSD-2-Clause-Patent

+

+ =40= par Glossary:

+ - =46wCfg - firmWare Configure

+ - CTL - Control

+**/

+

+=23= include =22Uefi.h=22

+=23include <Library/BaseLib.h><= /div>
+=23include <Library/BaseMemoryLib.h>

+= =23include <Library/DebugLib.h>

+=23include <Libra= ry/IoLib.h>

+=23include <Library/Qemu=46wCfgLib.h>=

+=23include <Library/MemoryAllocationLib.h>
+=23include <Library/UefiBootServicesTableLib.h>

+=23include <Library/PcdLib.h>

+=23include <libf= dt.h>

+=23include =22Qemu=46wCfgLibInternal.h=22
+

+STATIC UINTN m=46wCfgSelectorAddress;

+STATIC UINTN m=46wCfgDataAddress;

+/**

+ = To get firmware configure selector address.

+

+ =40param VOID

+

+ =40retval firmware confi= gure selector address

+**/

+UINTN

+E=46IAPI

+QemuGet=46wCfgSelectorAddress (

+ VOID

+ )

+=7B

+ UINTN =46wCf= gSelectorAddress =3D m=46wCfgSelectorAddress;

+ if (=46wCfg= SelectorAddress =3D=3D 0) =7B

+ =46wCfgSelectorAddress =3D = (UINTN)PcdGet64 (Pcd=46wCfgSelectorAddress);

+ =7D
+ return =46wCfgSelectorAddress;

+=7D

+= /**

+ To get firmware configure Data address.

+

+ =40param VOID

+

+ =40retva= l firmware configure data address

+**/

+UINTN=

+E=46IAPI

+QemuGet=46wCfgDataAddress (
=
+ VOID

+ )

+=7B

+ UINT= N =46wCfgDataAddress =3D m=46wCfgDataAddress;

+ if (=46wCfg= DataAddress =3D=3D 0) =7B

+ =46wCfgDataAddress =3D (UINTN)P= cdGet64 (Pcd=46wCfgDataAddress);

+ =7D

+ retu= rn =46wCfgDataAddress;

+=7D

+/**

+ Selects a firmware configuration item for reading.

+
+ =46ollowing this call, any data read from this item will st= art from

+ the beginning of the configuration item's data.<= /div>
+

+ =40param=5Bin=5D Qemu=46wCfgItem - =46irm= ware Configuration item to read

+**/

+VOID
+E=46IAPI

+Qemu=46wCfgSelectItem (

+ IN =46IRMWARE=5FCON=46IG=5FITEM Qemu=46wCfgItem

+ )
+=7B

+ UINTN =46wCfgSelectorAddress;

+ =46wCfgSelectorAddress =3D QemuGet=46wCfgSelectorAddress ();
+ MmioWrite16 (=46wCfgSelectorAddress, SwapBytes16((UINT16) (UINTN= )Qemu=46wCfgItem));

+=7D

+

+/**=

+ Slow READ=5FBYTES=5F=46UNCTION.

+
+ =40param=5Bin=5D The size of the data to be read.

+= =40param=5Bin=5D Buffer The buffer that stores the readout data.
+**/

+VOID

+E=46IAPI

+Mm= ioReadBytes (

+ IN UINTN Size,

+ IN VOID *Buf= fer OPTIONAL

+ )

+=7B

+ UINTN L= eft;

+ UINT8 *Ptr;

+ UINT8 *End;

+ UINTN =46wCfgDataAddress;

+ Left =3D Size & 7;
+

+ Size -=3D Left;

+ Ptr =3D Buffe= r;

+ End =3D Ptr + Size;

+ =46wCfgDataAddress= =3D QemuGet=46wCfgDataAddress ();

+ while (Ptr < End) =7B=

+ *(UINT64 *)Ptr =3D MmioRead64 (=46wCfgDataAddress);
+ Ptr +=3D 8;

+ =7D

+ if (Left &= ; 4) =7B

+ *(UINT32 *)Ptr =3D MmioRead32 (=46wCfgDataAddres= s);

+ Ptr +=3D 4;

+ =7D

+ if (L= eft & 2) =7B

+ *(UINT16 *)Ptr =3D MmioRead16 (=46wCfgDa= taAddress);

+ Ptr +=3D 2;

+ =7D

+ if (Left & 1) =7B

+ *Ptr =3D MmioRead8 (=46wCfgDataA= ddress);

+ =7D

+=7D

+

=
+/**

+ Slow WRITE=5FBYTES=5F=46UNCTION.

= +

+ =40param=5Bin=5D The size of the data to be write.
+ =40param=5Bin=5D Buffer The buffer that stores the writein da= ta.

+**/

+VOID

+E=46IAPI
<= br>
+MmioWriteBytes (

+ IN UINTN Size,

+ = IN VOID *Buffer OPTIONAL

+ )

+=7B

+ UINTN Idx;

+ UINTN =46wCfgDataAddress;

+= =46wCfgDataAddress =3D QemuGet=46wCfgDataAddress ();

+ for= (Idx =3D 0; Idx < Size; ++Idx) =7B

+ MmioWrite8 (=46wCf= gDataAddress, ((UINT8 *)Buffer)=5BIdx=5D);

+ =7D

<= div>+=7D

+

+/**

+ Reads firmwar= e configuration bytes into a buffer

+

+ =40pa= ram=5Bin=5D Size - Size in bytes to read

+ =40param=5Bin=5D= Buffer - Buffer to store data into (OPTIONAL if Size is 0)

+**/

+VOID

+E=46IAPI

+Internal= Qemu=46wCfgReadBytes (

+ IN UINTN Size,

+ IN = VOID *Buffer OPTIONAL

+ )

+=7B

= + if ((InternalQemu=46wCfgDmaIsAvailable ())

+ && (= Size <=3D MAX=5FUINT32))

+ =7B

+ InternalQ= emu=46wCfgDmaBytes ((UINT32)Size, Buffer, =46W=5FC=46G=5FDMA=5FCTL=5FREAD= );

+ return;

+ =7D

+ MmioReadBy= tes (Size, Buffer);

+=7D

+

+/**=

+ Reads firmware configuration bytes into a buffer
+

+ If called multiple times, then the data read wil= l

+ continue at the offset of the firmware configuration
+ item where the previous read ended.

+
+ =40param=5Bin=5D Size - Size in bytes to read

+ =40= param=5Bin=5D Buffer - Buffer to store data into

+**/
=
+VOID

+E=46IAPI

+Qemu=46wCfgReadByte= s (

+ IN UINTN Size,

+ IN VOID *Buffer
<= br>
+ )

+=7B

+ if (InternalQemu=46wCfgIsA= vailable ()) =7B

+ InternalQemu=46wCfgReadBytes (Size, Buff= er);

+ =7D else =7B

+ ZeroMem (Buffer, Size);=

+ =7D

+=7D

+

+/*= *

+ Write firmware configuration bytes from a buffer
<= br>
+

+ If called multiple times, then the data written= will

+ continue at the offset of the firmware configuratio= n

+ item where the previous write ended.

+
+ =40param=5Bin=5D Size - Size in bytes to write

+ =40param=5Bin=5D Buffer - Buffer to read data from

+**/=

+VOID

+E=46IAPI

+Qemu=46wCfgWr= iteBytes (

+ IN UINTN Size,

+ IN VOID *Buffer=

+ )

+=7B

+ if (InternalQemu=46= wCfgIsAvailable ()) =7B

+ if ((InternalQemu=46wCfgDmaIsAvai= lable ())

+ && (Size <=3D MAX=5FUINT32))
+ =7B

+ InternalQemu=46wCfgDmaBytes ((UINT32)Size, B= uffer, =46W=5FC=46G=5FDMA=5FCTL=5FWRITE);

+ return;
+ =7D

+ MmioWriteBytes (Size, Buffer);

+ =7D

+=7D

+

+/**

+ Skip bytes in the firmware configuration item.

+
<= br>
+ 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 c= ommence at the increased offset.

+

+ =40param= =5Bin=5D Size Number of bytes to skip.

+**/

+= VOID

+E=46IAPI

+Qemu=46wCfgSkipBytes (
<= br>
+ IN UINTN Size

+ )

+=7B

+ UINTN ChunkSize;
+ UINT8 SkipBuffer=5B256=5D;

=
+

+ if (=21InternalQemu=46wCfgIsAvailable ()) =7B
+ return;

+ =7D

+

+ i= f ((InternalQemu=46wCfgDmaIsAvailable ())

+ && (Siz= e <=3D MAX=5FUINT32))

+ =7B

+ InternalQemu= =46wCfgDmaBytes ((UINT32)Size, NULL, =46W=5FC=46G=5FDMA=5FCTL=5FSKIP);
+ return;

+ =7D

+

+= //

+ // Emulate the skip by reading data in chunks, and th= rowing it away. The

+ // implementation below is suitable e= ven for phases where RAM or dynamic

+ // allocation is not = available or appropriate. It also doesn't affect the

+ // s= tatic 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 pr= essure on the stack in any

+ // phase.

+ //
+ while (Size > 0) =7B

+ ChunkSize =3D MIN = (Size, sizeof SkipBuffer);

+ MmioReadBytes (ChunkSize, Skip= Buffer);

+ Size -=3D ChunkSize;

+ =7D
+=7D

+

+/**

+ Reads a UI= NT8 firmware configuration value

+

+ =40retur= n Value of =46irmware Configuration item read

+**/
+UINT8

+E=46IAPI

+Qemu=46wCfgRead8 (
+ VOID

+ )

+=7B

+ U= INT8 Result;

+

+ Qemu=46wCfgReadBytes (sizeof= (Result), &Result);

+

+ return Result;
+=7D

+

+/**

+ Read= s a UINT16 firmware configuration value

+

+ =40= return Value of =46irmware Configuration item read

+**/
+UINT16

+E=46IAPI

+Qemu=46wCfgRead= 16 (

+ VOID

+ )

+=7B

<= div>+ UINT16 Result;

+

+ Qemu=46wCfgReadBytes= (sizeof (Result), &Result);

+

+ return R= esult;

+=7D

+

+/**

+ Reads a UINT32 firmware configuration value

+

=
+ =40return Value of =46irmware Configuration item read

+**/

+UINT32

+E=46IAPI

+Qemu=46= wCfgRead32 (

+ VOID

+ )

+=7B
+ UINT32 Result;

+

+ Qemu=46wCfgR= eadBytes (sizeof (Result), &Result);

+

+ = return Result;

+=7D

+

+/**
+ Reads a UINT64 firmware configuration value

+
+ =40return Value of =46irmware Configuration item read
+**/

+UINT64

+E=46IAPI

+Qemu=46wCfgRead64 (

+ VOID

+ )

+=7B

+ UINT64 Result;

+

+ Qe= mu=46wCfgReadBytes (sizeof (Result), &Result);

+
<= br>
+ return Result;

+=7D

+

+/**

+ =46ind the configuration item corresponding to the = firmware configuration file.

+

+ =40param=5Bi= n=5D Name - Name of file to look up.

+ =40param=5Bout=5D It= em - Configuration item corresponding to the file, to be passed

=
+ to Qemu=46wCfgSelectItem ().

+ =40param=5Bout=5D Siz= e - Number of bytes in the file.

+

+ =40retur= n RETURN=5FSUCCESS If file is found.

+ RETURN=5FNOT=5F=46OU= ND If file is not found.

+ RETURN=5FUNSUPPORTED If firmware= configuration is unavailable.

+**/

+RETURN=5F= STATUS

+E=46IAPI

+Qemu=46wCfg=46ind=46ile (
+ IN CONST CHAR8 *Name,

+ OUT =46IRMWARE=5FCON= =46IG=5FITEM *Item,

+ OUT UINTN *Size

+ )
+=7B

+ UINT32 Count;

+ UINT32 Idx;=

+

+ if (=21InternalQemu=46wCfgIsAvailable ()= ) =7B

+ return RETURN=5FUNSUPPORTED;

+ =7D
+

+ Qemu=46wCfgSelectItem (Qemu=46wCfgItem=46il= eDir);

+ Count =3D SwapBytes32 (Qemu=46wCfgRead32 ());
+

+ for (Idx =3D 0; Idx < Count; ++Idx) =7B
+ UINT32 =46ileSize;

+ UINT16 =46ileSelect;
+ CHAR8 =46ileName=5BQEMU=5F=46W=5FC=46G=5F=46NAME=5FSIZE=5D;<= /div>
+

+ =46ileSize =3D Qemu=46wCfgRead32 ();
+ =46ileSelect =3D Qemu=46wCfgRead16 ();

+ Qemu=46= wCfgRead16 (); // skip the field called =22reserved=22

+ In= ternalQemu=46wCfgReadBytes (sizeof (=46ileName), =46ileName);

+

+ if (AsciiStrCmp (Name, =46ileName) =3D=3D 0) =7B
+ *Item =3D SwapBytes16 (=46ileSelect);

+ *Size = =3D SwapBytes32 (=46ileSize);

+ return RETURN=5FSUCCESS;
+ =7D

+ =7D

+

+ ret= urn RETURN=5FNOT=5F=46OUND;

+=7D

+

<= div>+/**

+ firmware config initialize.

+
+ =40param VOID

+

+ =40return RETUR= N=5FSUCCESS Initialization succeeded.

+**/

+R= ETURN=5FSTATUS

+E=46IAPI

+Qemu=46wCfgInitiali= ze (

+ VOID

+ )

+=7B

<= div>+ VOID *DeviceTreeBase;

+ INT32 Node;

+ I= NT32 Prev;

+ CONST CHAR8 *Type;

+ INT32 Len;<= /div>
+ CONST UINT64 *RegProp;

+ UINT64 =46wCfgSele= ctorAddress;

+ UINT64 =46wCfgDataAddress;

+ U= INT64 =46wCfgDataSize;

+ RETURN=5FSTATUS PcdStatus;
+

+ DeviceTreeBase =3D (VOID *) (UINTN)PcdGet64 (Pcd= DeviceTreeBase);

+ ASSERT (DeviceTreeBase =21=3D NULL);
+ //

+ // Make sure we have a valid device tree = blob

+ //

+ ASSERT (fdt=5Fcheck=5Fheader (Dev= iceTreeBase) =3D=3D 0);

+

+ for (Prev =3D 0;;= Prev =3D Node) =7B

+ Node =3D fdt=5Fnext=5Fnode (DeviceTre= eBase, Prev, NULL);

+ if (Node < 0) =7B

+ = break;

+ =7D

+

+ //

+ // Check for memory node

+ //

+ Type =3D= fdt=5Fgetprop (DeviceTreeBase, Node, =22compatible=22, &Len);
<= br>
+ if ((Type)

+ && (AsciiStrnCmp (Type, =22q= emu,fw-cfg-mmio=22, Len) =3D=3D 0))

+ =7B

+ /= /

+ // Get the 'reg' property of this node. =46or now, we w= ill assume

+ // two 8 byte quantities for base and size, re= spectively.

+ //

+ RegProp =3D fdt=5Fgetprop = (DeviceTreeBase, Node, =22reg=22, &Len);

+ if ((RegProp= =21=3D 0)

+ && (Len =3D=3D (2 * sizeof (UINT64))))=

+ =7B

+ =46wCfgDataAddress =3D SwapBytes64 (= RegProp=5B0=5D);

+ =46wCfgDataSize =3D 8;

+ =46= wCfgSelectorAddress =3D =46wCfgDataAddress + =46wCfgDataSize;

+

+ m=46wCfgSelectorAddress =3D =46wCfgSelectorAddress;<= /div>
+ m=46wCfgDataAddress =3D =46wCfgDataAddress;

+

+ PcdStatus =3D PcdSet64S (

+ Pcd=46wCfgSe= lectorAddress,

+ =46wCfgSelectorAddress

+ );<= /div>
+ ASSERT=5FRETURN=5FERROR (PcdStatus);

+ PcdS= tatus =3D PcdSet64S (

+ Pcd=46wCfgDataAddress,

+ =46wCfgDataAddress

+ );

+ ASSERT=5FRETURN= =5FERROR (PcdStatus);

+ break;

+ =7D else =7B=

+ DEBUG ((DEBUG=5FERROR, =22%a: =46ailed to parse =46DT Qe= muCfg node=5Cn=22,

+ =5F=5F=46UNCTION=5F=5F));

+ break;

+ =7D

+ =7D

+ =7D
+ return RETURN=5FSUCCESS;

+=7D

d= iff --git a/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qem= u=46wCfgPeiLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wC= fgLib/Qemu=46wCfgPeiLib.inf

new file mode 100644

<= div>index 0000000000..8609d615e7

--- /dev/null

+++ b/Platform/Loongson/LoongArchQemuPkg/Library/Qemu=46wCfgLib/Qemu=46= wCfgPeiLib.inf

=40=40 -0,0 +1,46 =40=40

+=23=23= =40file

+=23 initialized fw=5Fcfg library.

+= =23

+=23 Copyright (c) 2022 Loongson Technology Corporation= Limited. All rights reserved.<BR>

+=23

+=23 SPDX-License-Identifier: BSD-2-Clause-Patent

+=23
+=23=23

+

+=5BDefines=5D

=
+ IN=46=5FVERSION =3D 0x00010005

+ BASE=5FNAME =3D Qem= u=46wCfgSecLib

+ =46ILE=5FGUID =3D cdf9a9d5-7422-4dcb-b41d-= 607151ad320b

+ MODULE=5FTYPE =3D BASE

+ VERSI= ON=5FSTRING =3D 1.0

+ LIBRARY=5FCLASS =3D Qemu=46wCfgLib=7C= PEIM

+ CONSTRUCTOR =3D Qemu=46wCfgInitialize

= +

+=23

+=23 VALID=5FARCHITECTURES =3D LOONGAR= CH64

+=23

+

+=5BSources=5D
+ Qemu=46wCfgLibInternal.h

+ Qemu=46wCfgPeiLib.c<= /div>
+ Qemu=46wCfgPei.c

+

+=5BPackag= es=5D

+ EmbeddedPkg/EmbeddedPkg.dec

+ MdePkg/= MdePkg.dec

+ OvmfPkg/OvmfPkg.dec

+ Platform/L= oongson/LoongArchQemuPkg/Loongson.dec

+

+=5BL= ibraryClasses=5D

+ BaseLib

+ BaseMemoryLib
+ DebugLib

+ IoLib

+ MemoryAlloca= tionLib

+ =46dtLib

+ PcdLib

+
+=5BPcd=5D

+ gLoongArchQemuPkgTokenSpaceGuid.P= cdDeviceTreeBase

+ gLoongArchQemuPkgTokenSpaceGuid.Pcd=46wC= fgSelectorAddress

+ gLoongArchQemuPkgTokenSpaceGuid.Pcd=46w= CfgDataAddress

--

2.31.1
--636e17a7_455d779_1e57b--