From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 2E6D194085F for ; Wed, 10 Jan 2024 01:27:17 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=XIyRn8zHSypBppPCHGqZE8Xc/1axh9HaUYJixpLMF5k=; c=relaxed/simple; d=groups.io; h=Subject:To:Cc:References:From:Message-ID:Date:User-Agent:MIME-Version:In-Reply-To:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type:Content-Language:Content-Transfer-Encoding; s=20140610; t=1704850035; v=1; b=W5CB64dC+NfkqiWBKHkD/2U1lTG7obnFkuspIfwmPxSI2YjDo1adfaxGMeXdIgFCzSx5voeR VpDlPn4pCdV6jXhWELR58mPsVrypHWEBsDuI24A6QJReR73/vskhbH0KPiHPXhd6EJsDy2Jerel o4aashVNtN9hw/LB4agx6R9Y= X-Received: by 127.0.0.2 with SMTP id eJnrYY7687511xNgD9DXzjow; Tue, 09 Jan 2024 17:27:15 -0800 X-Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2127.1704850034629765452 for ; Tue, 09 Jan 2024 17:27:15 -0800 X-Received: from loongson.cn (unknown [10.20.42.173]) by gateway (Coremail) with SMTP id _____8DxvOhv8p1l+a4DAA--.3068S3; Wed, 10 Jan 2024 09:27:11 +0800 (CST) X-Received: from [10.20.42.173] (unknown [10.20.42.173]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxbNxs8p1lNvAJAA--.26366S3; Wed, 10 Jan 2024 09:27:08 +0800 (CST) Subject: Re: [edk2-devel] [PATCH v6 31/36] OvmfPkg/LoongArchVirt: Add FdtQemuFwCfgLib To: Chao Li , devel@edk2.groups.io Cc: Ard Biesheuvel , Jiewen Yao , Jordan Justen , Gerd Hoffmann , Dongyan Qian , Xianglai Li References: <20240105094118.2279380-1-lichao@loongson.cn> <20240105094616.2281979-1-lichao@loongson.cn> From: "maobibo" Message-ID: <7dadc71b-c18b-c84a-f10a-90307e1f1b21@loongson.cn> Date: Wed, 10 Jan 2024 09:27:08 +0800 User-Agent: Mozilla/5.0 (X11; Linux loongarch64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: <20240105094616.2281979-1-lichao@loongson.cn> X-CM-TRANSID: AQAAf8BxbNxs8p1lNvAJAA--.26366S3 X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBj9fXoWfZry5tF4DGF48ZrW8uw1DCFX_yoW8ZF4xKo WfXrn2yw1Yywn8u340kr93Wr4UtayYgrs3XFWrAFsrtF1DtF4j9FW7JayUGFn5Ga18tr18 J3yrX3yxZFsavrs5l-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYI7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUGVWUXwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI 0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUtVWrXwAv7VC2z280 aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcVAKI48JMxk0xIA0c2IEe2 xFo4CEbIxvr21l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAq x4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r 43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF 7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxV W8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxU cHUqUUUUU Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,maobibo@loongson.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: OMyZ5Sxi2eKjPTuIvi2Shvrmx7686176AA= Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=W5CB64dC; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io On 2024/1/5 下午5:46, Chao Li wrote: > This library for PEI phase, and obtains the QemuFwCfg base address by > directly parsing the FDT, reads and writes the data in QemuFwCfg by > operating on the QemuFwCfg base address. > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584 > > Cc: Ard Biesheuvel > Cc: Jiewen Yao > Cc: Jordan Justen > Cc: Gerd Hoffmann > Cc: Bibo Mao > Cc: Dongyan Qian > Signed-off-by: Chao Li > Co-authored-by: Xianglai Li > Co-authored-by: Bibo Mao > --- > .../FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.c | 504 ++++++++++++++++++ > .../FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.inf | 42 ++ > .../FdtQemuFwCfgLib/QemuFwCfgLibInternal.h | 73 +++ > .../Library/FdtQemuFwCfgLib/QemuFwCfgPei.c | 117 ++++ > 4 files changed, 736 insertions(+) > create mode 100644 OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.c > create mode 100644 OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.inf > create mode 100644 OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgLibInternal.h > create mode 100644 OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgPei.c > > diff --git a/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.c b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.c > new file mode 100644 > index 0000000000..a1f114b327 > --- /dev/null > +++ b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.c > @@ -0,0 +1,504 @@ > +/** @file > + > + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Glossary: > + - FwCfg - firmWare Configure > + - CTL - Control > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "QemuFwCfgLibInternal.h" > + > +EFI_GUID mFwCfgSelectorAddressGuid = FW_CONFIG_SELECTOR_ADDRESS_HOB_GUID; > +EFI_GUID mFwCfgDataAddressGuid = FW_CONFIG_DATA_ADDRESS_HOB_GUID; > + > +STATIC UINTN mFwCfgSelectorAddress; > +STATIC UINTN mFwCfgDataAddress; > + > +/** > + To get firmware configure selector address. > + > + @param VOID > + > + @retval firmware configure selector address > +**/ > +UINTN > +EFIAPI > +QemuGetFwCfgSelectorAddress ( > + VOID > + ) > +{ > + UINTN FwCfgSelectorAddress; > + EFI_HOB_GUID_TYPE *GuidHob; > + VOID *DataInHob; > + > + FwCfgSelectorAddress = mFwCfgSelectorAddress; > + GuidHob = NULL; > + DataInHob = NULL; > + > + if (FwCfgSelectorAddress == 0) { > + GuidHob = GetFirstGuidHob (&mFwCfgSelectorAddressGuid); > + DataInHob = GET_GUID_HOB_DATA (GuidHob); > + FwCfgSelectorAddress = (UINT64)(*(UINTN *)DataInHob); > + } > + > + return FwCfgSelectorAddress; > +} > + > +/** > + To get firmware configure Data address. > + > + @param VOID > + > + @retval firmware configure data address > +**/ > +UINTN > +EFIAPI > +QemuGetFwCfgDataAddress ( > + VOID > + ) > +{ > + UINTN FwCfgDataAddress; > + EFI_HOB_GUID_TYPE *GuidHob; > + VOID *DataInHob; > + > + FwCfgDataAddress = mFwCfgDataAddress; > + GuidHob = NULL; > + DataInHob = NULL; > + > + if (FwCfgDataAddress == 0) { > + GuidHob = GetFirstGuidHob (&mFwCfgDataAddressGuid); > + DataInHob = GET_GUID_HOB_DATA (GuidHob); > + FwCfgDataAddress = (UINT64)(*(UINTN *)DataInHob); > + } > + > + return FwCfgDataAddress; > +} > + > +/** > + Selects a firmware configuration item for reading. > + > + Following this call, any data read from this item will start from > + the beginning of the configuration item's data. > + > + @param[in] QemuFwCfgItem - Firmware Configuration item to read > +**/ > +VOID > +EFIAPI > +QemuFwCfgSelectItem ( > + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem > + ) > +{ > + UINTN FwCfgSelectorAddress; > + > + FwCfgSelectorAddress = QemuGetFwCfgSelectorAddress (); > + MmioWrite16 (FwCfgSelectorAddress, SwapBytes16 ((UINT16)(UINTN)QemuFwCfgItem)); > +} > + > +/** > + Slow READ_BYTES_FUNCTION. > + > + @param[in] The size of the data to be read. > + @param[in] Buffer The buffer that stores the readout data. > +**/ > +VOID > +EFIAPI > +MmioReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + UINTN Left; > + UINT8 *Ptr; > + UINT8 *End; > + UINTN FwCfgDataAddress; > + > + Left = Size & 7; > + > + Size -= Left; > + Ptr = Buffer; > + End = Ptr + Size; > + > + FwCfgDataAddress = QemuGetFwCfgDataAddress (); > + while (Ptr < End) { > + *(UINT64 *)Ptr = MmioRead64 (FwCfgDataAddress); > + Ptr += 8; > + } > + > + if (Left & 4) { > + *(UINT32 *)Ptr = MmioRead32 (FwCfgDataAddress); > + Ptr += 4; > + } > + > + if (Left & 2) { > + *(UINT16 *)Ptr = MmioRead16 (FwCfgDataAddress); > + Ptr += 2; > + } > + > + if (Left & 1) { > + *Ptr = MmioRead8 (FwCfgDataAddress); > + } > +} > + > +/** > + Slow WRITE_BYTES_FUNCTION. > + > + @param[in] The size of the data to be write. > + @param[in] Buffer The buffer that stores the writein data. > +**/ > +VOID > +EFIAPI > +MmioWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + UINTN Idx; > + UINTN FwCfgDataAddress; > + > + FwCfgDataAddress = QemuGetFwCfgDataAddress (); > + for (Idx = 0; Idx < Size; ++Idx) { > + MmioWrite8 (FwCfgDataAddress, ((UINT8 *)Buffer)[Idx]); > + } > +} > + > +/** > + Reads firmware configuration bytes into a buffer > + > + @param[in] Size - Size in bytes to read > + @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0) > +**/ > +VOID > +EFIAPI > +InternalQemuFwCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer OPTIONAL > + ) > +{ > + if ((InternalQemuFwCfgDmaIsAvailable ()) && > + (Size <= MAX_UINT32)) > + { > + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ); > + return; > + } > + > + MmioReadBytes (Size, Buffer); > +} > + > +/** > + Reads firmware configuration bytes into a buffer > + > + If called multiple times, then the data read will > + continue at the offset of the firmware configuration > + item where the previous read ended. > + > + @param[in] Size - Size in bytes to read > + @param[in] Buffer - Buffer to store data into > +**/ > +VOID > +EFIAPI > +QemuFwCfgReadBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +{ > + if (InternalQemuFwCfgIsAvailable ()) { > + InternalQemuFwCfgReadBytes (Size, Buffer); > + } else { > + ZeroMem (Buffer, Size); > + } > +} > + > +/** > + Write firmware configuration bytes from a buffer > + > + If called multiple times, then the data written will > + continue at the offset of the firmware configuration > + item where the previous write ended. > + > + @param[in] Size - Size in bytes to write > + @param[in] Buffer - Buffer to read data from > +**/ > +VOID > +EFIAPI > +QemuFwCfgWriteBytes ( > + IN UINTN Size, > + IN VOID *Buffer > + ) > +{ > + if (InternalQemuFwCfgIsAvailable ()) { > + if ((InternalQemuFwCfgDmaIsAvailable ()) && > + (Size <= MAX_UINT32)) > + { > + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_WRITE); > + return; > + } > + > + MmioWriteBytes (Size, Buffer); > + } > +} > + > +/** > + Skip bytes in the firmware configuration item. > + > + Increase the offset of the firmware configuration item without transferring > + bytes between the item and a caller-provided buffer. Subsequent read, write > + or skip operations will commence at the increased offset. > + > + @param[in] Size Number of bytes to skip. > +**/ > +VOID > +EFIAPI > +QemuFwCfgSkipBytes ( > + IN UINTN Size > + ) > +{ > + UINTN ChunkSize; > + UINT8 SkipBuffer[256]; > + > + if (!InternalQemuFwCfgIsAvailable ()) { > + return; > + } > + > + if ((InternalQemuFwCfgDmaIsAvailable ()) && > + (Size <= MAX_UINT32)) > + { > + InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP); > + return; > + } > + > + // > + // Emulate the skip by reading data in chunks, and throwing it away. The > + // implementation below is suitable even for phases where RAM or dynamic > + // allocation is not available or appropriate. It also doesn't affect the > + // static data footprint for client modules. Large skips are not expected, > + // therefore this fallback is not performance critical. The size of > + // SkipBuffer is thought not to exert a large pressure on the stack in any > + // phase. > + // > + while (Size > 0) { > + ChunkSize = MIN (Size, sizeof SkipBuffer); > + MmioReadBytes (ChunkSize, SkipBuffer); > + Size -= ChunkSize; > + } > +} > + > +/** > + Reads a UINT8 firmware configuration value > + > + @return Value of Firmware Configuration item read > +**/ > +UINT8 > +EFIAPI > +QemuFwCfgRead8 ( > + VOID > + ) > +{ > + UINT8 Result; > + > + QemuFwCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +} > + > +/** > + Reads a UINT16 firmware configuration value > + > + @return Value of Firmware Configuration item read > +**/ > +UINT16 > +EFIAPI > +QemuFwCfgRead16 ( > + VOID > + ) > +{ > + UINT16 Result; > + > + QemuFwCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +} > + > +/** > + Reads a UINT32 firmware configuration value > + > + @return Value of Firmware Configuration item read > +**/ > +UINT32 > +EFIAPI > +QemuFwCfgRead32 ( > + VOID > + ) > +{ > + UINT32 Result; > + > + QemuFwCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +} > + > +/** > + Reads a UINT64 firmware configuration value > + > + @return Value of Firmware Configuration item read > +**/ > +UINT64 > +EFIAPI > +QemuFwCfgRead64 ( > + VOID > + ) > +{ > + UINT64 Result; > + > + QemuFwCfgReadBytes (sizeof (Result), &Result); > + > + return Result; > +} > + > +/** > + Find the configuration item corresponding to the firmware configuration file. > + > + @param[in] Name - Name of file to look up. > + @param[out] Item - Configuration item corresponding to the file, to be passed > + to QemuFwCfgSelectItem (). > + @param[out] Size - Number of bytes in the file. > + > + @return RETURN_SUCCESS If file is found. > + RETURN_NOT_FOUND If file is not found. > + RETURN_UNSUPPORTED If firmware configuration is unavailable. > +**/ > +RETURN_STATUS > +EFIAPI > +QemuFwCfgFindFile ( > + IN CONST CHAR8 *Name, > + OUT FIRMWARE_CONFIG_ITEM *Item, > + OUT UINTN *Size > + ) > +{ > + UINT32 Count; > + UINT32 Idx; > + > + if (!InternalQemuFwCfgIsAvailable ()) { > + return RETURN_UNSUPPORTED; > + } > + > + QemuFwCfgSelectItem (QemuFwCfgItemFileDir); > + Count = SwapBytes32 (QemuFwCfgRead32 ()); > + > + for (Idx = 0; Idx < Count; ++Idx) { > + UINT32 FileSize; > + UINT16 FileSelect; > + CHAR8 FileName[QEMU_FW_CFG_FNAME_SIZE]; > + > + FileSize = QemuFwCfgRead32 (); > + FileSelect = QemuFwCfgRead16 (); > + QemuFwCfgRead16 (); // skip the field called "reserved" > + InternalQemuFwCfgReadBytes (sizeof (FileName), FileName); > + > + if (AsciiStrCmp (Name, FileName) == 0) { > + *Item = SwapBytes16 (FileSelect); > + *Size = SwapBytes32 (FileSize); > + return RETURN_SUCCESS; > + } > + } > + > + return RETURN_NOT_FOUND; > +} > + > +/** > + firmware config initialize. > + > + @param VOID > + > + @return RETURN_SUCCESS Initialization succeeded. > +**/ > +RETURN_STATUS > +EFIAPI > +FdtQemuFwCfgInitialize ( > + VOID > + ) > +{ > + VOID *DeviceTreeBase; > + INT32 Node; > + INT32 Prev; > + CONST CHAR8 *Type; > + INT32 Len; > + CONST UINT64 *RegProp; > + UINT64 FwCfgSelectorAddress; > + UINT64 FwCfgDataAddress; > + UINT64 FwCfgDataSize; > + > + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); > + ASSERT (DeviceTreeBase != NULL); > + // > + // Make sure we have a valid device tree blob > + // > + ASSERT (fdt_check_header (DeviceTreeBase) == 0); > + > + for (Prev = 0; ; Prev = Node) { > + Node = fdt_next_node (DeviceTreeBase, Prev, NULL); > + if (Node < 0) { > + break; > + } > + > + // > + // Check for memory node > + // > + Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); > + if ((Type) && > + (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0)) > + { > + // > + // Get the 'reg' property of this node. For now, we will assume > + // two 8 byte quantities for base and size, respectively. > + // > + RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); > + if ((RegProp != 0) && > + (Len == (2 * sizeof (UINT64)))) > + { > + FwCfgDataAddress = SwapBytes64 (RegProp[0]); > + FwCfgDataSize = 8; > + FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; > + > + mFwCfgSelectorAddress = FwCfgSelectorAddress; > + mFwCfgDataAddress = FwCfgDataAddress; > + > + BuildGuidDataHob ( > + &mFwCfgSelectorAddressGuid, > + (VOID *)&FwCfgSelectorAddress, > + sizeof (UINT64) > + ); > + > + BuildGuidDataHob ( > + &mFwCfgDataAddressGuid, > + (VOID *)&FwCfgDataAddress, > + sizeof (UINT64) > + ); > + break; > + } else { > + DEBUG (( > + DEBUG_ERROR, > + "%a: Failed to parse FDT QemuCfg node\n", > + __func__ > + )); > + break; > + } > + } > + } > + > + return RETURN_SUCCESS; > +} > diff --git a/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.inf b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.inf > new file mode 100644 > index 0000000000..930933ce7d > --- /dev/null > +++ b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/FdtQemuFwCfgPeiLib.inf > @@ -0,0 +1,42 @@ > +## @file > +# initialized fw_cfg library. > +# > +# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 1.29 > + BASE_NAME = FdtQemuFwCfgPeiLib > + FILE_GUID = cdf9a9d5-7422-4dcb-b41d-607151ad320b > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = FtdQemuFwCfgLib|PEIM > + CONSTRUCTOR = FdtQemuFwCfgInitialize > + > +# > +# VALID_ARCHITECTURES = LOONGARCH64 > +# > + > +[Sources] > + FdtQemuFwCfgPeiLib.c > + QemuFwCfgPei.c > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + FdtLib > + HobLib > + IoLib > + MemoryAllocationLib > + > +[Pcd] > + gUefiOvmfPkgTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress > diff --git a/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgLibInternal.h > new file mode 100644 > index 0000000000..983d1f4849 > --- /dev/null > +++ b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgLibInternal.h > @@ -0,0 +1,73 @@ > +/** @file > + fw_cfg library implementation. > + > + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Glossary: > + - FwCfg - firmWare Configure > +**/ > + > +#ifndef QEMU_FW_CFG_LIB_INTERNAL_H_ > +#define QEMU_FW_CFG_LIB_INTERNAL_H_ > + > +#define FW_CONFIG_SELECTOR_ADDRESS_HOB_GUID \ > + { \ > + 0x3cc47b04, 0x0d3e, 0xaa64, { 0x06, 0xa6, 0x4b, 0xdc, 0x9a, 0x2c, 0x61, 0x19 } \ > + } > + > +#define FW_CONFIG_DATA_ADDRESS_HOB_GUID \ > + { \ > + 0xef854788, 0x10f3, 0x8e7a, { 0x3e, 0xd0, 0x4d, 0x16, 0xc1, 0x79, 0x55, 0x2f } \ > + } > + > +/** > + Returns a boolean indicating if the firmware configuration interface is > + available for library-internal purposes. > + > + This function never changes fw_cfg state. > + > + @retval TRUE The interface is available internally. > + @retval FALSE The interface is not available internally. > +**/ > +BOOLEAN > +InternalQemuFwCfgIsAvailable ( > + VOID > + ); > + > +/** > + Returns a boolean indicating whether QEMU provides the DMA-like access method > + for fw_cfg. > + > + @retval TRUE The DMA-like access method is available. > + @retval FALSE The DMA-like access method is unavailable. > +**/ > +BOOLEAN > +InternalQemuFwCfgDmaIsAvailable ( > + VOID > + ); > + > +/** > + Transfer an array of bytes, or skip a number of bytes, using the DMA > + interface. > + > + @param[in] Size Size in bytes to transfer or skip. > + > + @param[in,out] Buffer Buffer to read data into or write data from. Ignored, > + and may be NULL, if Size is zero, or Control is > + FW_CFG_DMA_CTL_SKIP. > + > + @param[in] Control One of the following: > + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. > + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. > + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. > +**/ > +VOID > +InternalQemuFwCfgDmaBytes ( > + IN UINT32 Size, > + IN OUT VOID *Buffer OPTIONAL, > + IN UINT32 Control > + ); > + > +#endif // QEMU_FW_CFG_LIB_INTERNAL_H_ > diff --git a/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgPei.c > new file mode 100644 > index 0000000000..74e778aac7 > --- /dev/null > +++ b/OvmfPkg/LoongArchVirt/Library/FdtQemuFwCfgLib/QemuFwCfgPei.c > @@ -0,0 +1,117 @@ > +/** @file > + fw_cfg library implementation. > + > + Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Glossary: > + - FwCfg - firmWare Configure > +**/ > + > +#include > +#include > +#include > + > +#include "QemuFwCfgLibInternal.h" > + > +/** > + Returns a boolean indicating if the firmware configuration interface > + is available or not. > + > + This function may change fw_cfg state. > + > + @retval TRUE The interface is available > + @retval FALSE The interface is not available > +**/ > +BOOLEAN > +EFIAPI > +QemuFwCfgIsAvailable ( > + VOID > + ) > +{ > + UINT32 Signature; > + UINT32 Revision; > + > + QemuFwCfgSelectItem (QemuFwCfgItemSignature); > + Signature = QemuFwCfgRead32 (); > + DEBUG ((DEBUG_INFO, "FW CFG Signature: 0x%x\n", Signature)); > + QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); > + Revision = QemuFwCfgRead32 (); > + DEBUG ((DEBUG_INFO, "FW CFG Revision: 0x%x\n", Revision)); > + if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || > + (Revision < 1)) > + { > + DEBUG ((DEBUG_INFO, "QemuFwCfg interface not supported.\n")); > + return FALSE; > + } > + > + DEBUG ((DEBUG_INFO, "QemuFwCfg interface is supported.\n")); > + return TRUE; > +} > + > +/** > + Returns a boolean indicating if the firmware configuration interface is > + available for library-internal purposes. > + > + This function never changes fw_cfg state. > + > + @retval TRUE The interface is available internally. > + @retval FALSE The interface is not available internally. > +**/ > +BOOLEAN > +InternalQemuFwCfgIsAvailable ( > + VOID > + ) > +{ > + // > + // We always return TRUE, because the consumer of this library ought to have > + // called QemuFwCfgIsAvailable before making other calls which would hit this > + // path. > + // > + return TRUE; > +} > + > +/** > + Returns a boolean indicating whether QEMU provides the DMA-like access method > + for fw_cfg. > + > + @retval TRUE The DMA-like access method is available. > + @retval FALSE The DMA-like access method is unavailable. > +**/ > +BOOLEAN > +InternalQemuFwCfgDmaIsAvailable ( > + VOID > + ) > +{ > + return FALSE; > +} > + > +/** > + Transfer an array of bytes, or skip a number of bytes, using the DMA > + interface. > + > + @param[in] Size Size in bytes to transfer or skip. > + > + @param[in, out] Buffer Buffer to read data into or write data from. Ignored, > + and may be NULL, if Size is zero, or Control is > + FW_CFG_DMA_CTL_SKIP. > + > + @param[in] Control One of the following: > + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. > + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. > + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. > +**/ > +VOID > +InternalQemuFwCfgDmaBytes ( > + IN UINT32 Size, > + IN OUT VOID *Buffer OPTIONAL, > + IN UINT32 Control > + ) > +{ > + // > + // We should never reach here > + // > + ASSERT (FALSE); > + CpuDeadLoop (); > +} > Reviewed-by: Bibo Mao -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113502): https://edk2.groups.io/g/devel/message/113502 Mute This Topic: https://groups.io/mt/103540132/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-