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 D7E0294125A for ; Mon, 11 Mar 2024 09:39:32 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=4J0UiUZ/HQwfXC4DJ7gHtbVPaGOwPLHmtbbWrzFDQcU=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240206; t=1710149971; v=1; b=YHrkxRUd/NFvVsFWMNcS0wJ41aT3IOZGzX8YjSHuQD7GKnE0xYLf3HOUf4NaVLWArqyKHUD4 uicjInoIPQm11ssz3kUPO7xSi/u1XFWTO+ahJm3TtwX+dosPk8CgFpaSZoQmuJ86GGLPSyJhkg2 H+jU8CQxk80hjldUZm3H2Fm/8owqlQFhjvOUW05KGYnA7muBUQ2fibgfgAur2chEnHjC6vq/u/Z VxVHMhW0GU5pBvQpSXKUM68KyReNpMJSI+MtHumFJbQl+baj8jYEniSy9oAz4BwH749WYm228hm VdLub70shXUTSG6WF8PvnzPH++vQ8y8Mh1zTU637lxxqQ== X-Received: by 127.0.0.2 with SMTP id szE6YY7687511xl4tbvjcM9G; Mon, 11 Mar 2024 02:39:31 -0700 X-Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.58774.1710149970354770466 for ; Mon, 11 Mar 2024 02:39:31 -0700 X-Received: from loongson.cn (unknown [10.2.9.245]) by gateway (Coremail) with SMTP id _____8Dx6uhO0e5lABsXAA--.36847S3; Mon, 11 Mar 2024 17:39:26 +0800 (CST) X-Received: from code-server.gen (unknown [10.2.9.245]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxXRNM0e5lHSVWAA--.30475S2; Mon, 11 Mar 2024 17:39:24 +0800 (CST) From: "Chao Li" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Jiewen Yao , Jordan Justen , Gerd Hoffmann , Bibo Mao , Dongyan Qian , Xianglai Li Subject: [edk2-devel] [PATCH v1 21/26] OvmfPkg/LoongArchVirt: Add FdtQemuFwCfgLib Date: Mon, 11 Mar 2024 02:39:31 -0700 Message-Id: <20240311093924.1254576-1-lichao@loongson.cn> In-Reply-To: <20240311093631.1251466-1-lichao@loongson.cn> References: <20240311093631.1251466-1-lichao@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxXRNM0e5lHSVWAA--.30475S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQANCGXuwOYA3wAfsp X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== 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,lichao@loongson.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: yf6EJHje2FUbBZbtF858fsq4x7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=YHrkxRUd; 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 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 Reviewed-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 (); +} -- 2.27.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#116604): https://edk2.groups.io/g/devel/message/116604 Mute This Topic: https://groups.io/mt/104859897/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-