# Virtio Support\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf\r
- QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf\r
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf\r
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf\r
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf\r
# Virtio Support\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf\r
- QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf\r
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf\r
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf\r
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf\r
+++ /dev/null
-/** @file\r
-\r
- Stateful and implicitly initialized fw_cfg library implementation.\r
-\r
- Copyright (C) 2013 - 2014, Red Hat, Inc.\r
- Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-**/\r
-\r
-#include <Uefi.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/QemuFwCfgLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-\r
-#include <Protocol/FdtClient.h>\r
-\r
-STATIC UINTN mFwCfgSelectorAddress;\r
-STATIC UINTN mFwCfgDataAddress;\r
-STATIC UINTN mFwCfgDmaAddress;\r
-\r
-/**\r
- Reads firmware configuration bytes into a buffer\r
-\r
- @param[in] Size Size in bytes to read\r
- @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI READ_BYTES_FUNCTION) (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- );\r
-\r
-/**\r
- Writes bytes from a buffer to firmware configuration\r
-\r
- @param[in] Size Size in bytes to write\r
- @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI WRITE_BYTES_FUNCTION) (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- );\r
-\r
-/**\r
- Skips bytes in firmware configuration\r
-\r
- @param[in] Size Size in bytes to skip\r
-\r
-**/\r
-typedef\r
-VOID (EFIAPI SKIP_BYTES_FUNCTION) (\r
- IN UINTN Size\r
- );\r
-\r
-//\r
-// Forward declaration of the two implementations we have.\r
-//\r
-STATIC READ_BYTES_FUNCTION MmioReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION MmioWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION MmioSkipBytes;\r
-STATIC READ_BYTES_FUNCTION DmaReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION DmaWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION DmaSkipBytes;\r
-\r
-//\r
-// These correspond to the implementation we detect at runtime.\r
-//\r
-STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;\r
-STATIC WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;\r
-STATIC SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;\r
-\r
-\r
-/**\r
- Returns a boolean indicating if the firmware configuration interface\r
- is available or not.\r
-\r
- This function may change fw_cfg state.\r
-\r
- @retval TRUE The interface is available\r
- @retval FALSE The interface is not available\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-QemuFwCfgIsAvailable (\r
- VOID\r
- )\r
-{\r
- return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);\r
-}\r
-\r
-\r
-RETURN_STATUS\r
-EFIAPI\r
-QemuFwCfgInitialize (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- FDT_CLIENT_PROTOCOL *FdtClient;\r
- CONST UINT64 *Reg;\r
- UINT32 RegSize;\r
- UINTN AddressCells, SizeCells;\r
- UINT64 FwCfgSelectorAddress;\r
- UINT64 FwCfgSelectorSize;\r
- UINT64 FwCfgDataAddress;\r
- UINT64 FwCfgDataSize;\r
- UINT64 FwCfgDmaAddress;\r
- UINT64 FwCfgDmaSize;\r
-\r
- Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
- (VOID **)&FdtClient);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = FdtClient->FindCompatibleNodeReg (FdtClient, "qemu,fw-cfg-mmio",\r
- (CONST VOID **)&Reg, &AddressCells, &SizeCells,\r
- &RegSize);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_WARN,\r
- "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",\r
- __FUNCTION__, Status));\r
- return EFI_SUCCESS;\r
- }\r
-\r
- ASSERT (AddressCells == 2);\r
- ASSERT (SizeCells == 2);\r
- ASSERT (RegSize == 2 * sizeof (UINT64));\r
-\r
- FwCfgDataAddress = SwapBytes64 (Reg[0]);\r
- FwCfgDataSize = 8;\r
- FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;\r
- FwCfgSelectorSize = 2;\r
-\r
- //\r
- // The following ASSERT()s express\r
- //\r
- // Address + Size - 1 <= MAX_UINTN\r
- //\r
- // for both registers, that is, that the last byte in each MMIO range is\r
- // expressible as a MAX_UINTN. The form below is mathematically\r
- // equivalent, and it also prevents any unsigned overflow before the\r
- // comparison.\r
- //\r
- ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);\r
- ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);\r
-\r
- mFwCfgSelectorAddress = FwCfgSelectorAddress;\r
- mFwCfgDataAddress = FwCfgDataAddress;\r
-\r
- DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress,\r
- FwCfgDataAddress));\r
-\r
- if (SwapBytes64 (Reg[1]) >= 0x18) {\r
- FwCfgDmaAddress = FwCfgDataAddress + 0x10;\r
- FwCfgDmaSize = 0x08;\r
-\r
- //\r
- // See explanation above.\r
- //\r
- ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);\r
-\r
- DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));\r
- } else {\r
- FwCfgDmaAddress = 0;\r
- }\r
-\r
- if (QemuFwCfgIsAvailable ()) {\r
- UINT32 Signature;\r
-\r
- QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
- Signature = QemuFwCfgRead32 ();\r
- if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {\r
- //\r
- // For DMA support, we require the DTB to advertise the register, and the\r
- // feature bitmap (which we read without DMA) to confirm the feature.\r
- //\r
- if (FwCfgDmaAddress != 0) {\r
- UINT32 Features;\r
-\r
- QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
- Features = QemuFwCfgRead32 ();\r
- if ((Features & FW_CFG_F_DMA) != 0) {\r
- mFwCfgDmaAddress = FwCfgDmaAddress;\r
- InternalQemuFwCfgReadBytes = DmaReadBytes;\r
- InternalQemuFwCfgWriteBytes = DmaWriteBytes;\r
- InternalQemuFwCfgSkipBytes = DmaSkipBytes;\r
- }\r
- }\r
- } else {\r
- mFwCfgSelectorAddress = 0;\r
- mFwCfgDataAddress = 0;\r
- }\r
- }\r
- return RETURN_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Selects a firmware configuration item for reading.\r
-\r
- Following this call, any data read from this item will start from the\r
- beginning of the configuration item's data.\r
-\r
- @param[in] QemuFwCfgItem Firmware Configuration item to read\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgSelectItem (\r
- IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem\r
- )\r
-{\r
- if (QemuFwCfgIsAvailable ()) {\r
- MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));\r
- }\r
-}\r
-\r
-\r
-/**\r
- Slow READ_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioReadBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- )\r
-{\r
- UINTN Left;\r
- UINT8 *Ptr;\r
- UINT8 *End;\r
-\r
-#ifdef MDE_CPU_AARCH64\r
- Left = Size & 7;\r
-#else\r
- Left = Size & 3;\r
-#endif\r
-\r
- Size -= Left;\r
- Ptr = Buffer;\r
- End = Ptr + Size;\r
-\r
-#ifdef MDE_CPU_AARCH64\r
- while (Ptr < End) {\r
- *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);\r
- Ptr += 8;\r
- }\r
- if (Left & 4) {\r
- *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
- Ptr += 4;\r
- }\r
-#else\r
- while (Ptr < End) {\r
- *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
- Ptr += 4;\r
- }\r
-#endif\r
-\r
- if (Left & 2) {\r
- *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);\r
- Ptr += 2;\r
- }\r
- if (Left & 1) {\r
- *Ptr = MmioRead8 (mFwCfgDataAddress);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Transfer an array of bytes, or skip a number of bytes, using the DMA\r
- interface.\r
-\r
- @param[in] Size Size in bytes to transfer or skip.\r
-\r
- @param[in,out] Buffer Buffer to read data into or write data from. Ignored,\r
- and may be NULL, if Size is zero, or Control is\r
- FW_CFG_DMA_CTL_SKIP.\r
-\r
- @param[in] Control One of the following:\r
- FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.\r
- FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.\r
- FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.\r
-**/\r
-STATIC\r
-VOID\r
-DmaTransferBytes (\r
- IN UINTN Size,\r
- IN OUT VOID *Buffer OPTIONAL,\r
- IN UINT32 Control\r
- )\r
-{\r
- volatile FW_CFG_DMA_ACCESS Access;\r
- UINT32 Status;\r
-\r
- ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||\r
- Control == FW_CFG_DMA_CTL_SKIP);\r
-\r
- if (Size == 0) {\r
- return;\r
- }\r
-\r
- ASSERT (Size <= MAX_UINT32);\r
-\r
- Access.Control = SwapBytes32 (Control);\r
- Access.Length = SwapBytes32 ((UINT32)Size);\r
- Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);\r
-\r
- //\r
- // We shouldn't start the transfer before setting up Access.\r
- //\r
- MemoryFence ();\r
-\r
- //\r
- // This will fire off the transfer.\r
- //\r
-#ifdef MDE_CPU_AARCH64\r
- MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));\r
-#else\r
- MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));\r
-#endif\r
-\r
- //\r
- // We shouldn't look at Access.Control before starting the transfer.\r
- //\r
- MemoryFence ();\r
-\r
- do {\r
- Status = SwapBytes32 (Access.Control);\r
- ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
- } while (Status != 0);\r
-\r
- //\r
- // The caller will want to access the transferred data.\r
- //\r
- MemoryFence ();\r
-}\r
-\r
-\r
-/**\r
- Fast READ_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaReadBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- )\r
-{\r
- DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_READ);\r
-}\r
-\r
-\r
-/**\r
- Reads firmware configuration bytes into a buffer\r
-\r
- If called multiple times, then the data read will continue at the offset of\r
- the firmware configuration item where the previous read ended.\r
-\r
- @param[in] Size Size in bytes to read\r
- @param[in] Buffer Buffer to store data into\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgReadBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer\r
- )\r
-{\r
- if (QemuFwCfgIsAvailable ()) {\r
- InternalQemuFwCfgReadBytes (Size, Buffer);\r
- } else {\r
- ZeroMem (Buffer, Size);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Slow WRITE_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioWriteBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- )\r
-{\r
- UINTN Idx;\r
-\r
- for (Idx = 0; Idx < Size; ++Idx) {\r
- MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Fast WRITE_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaWriteBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer OPTIONAL\r
- )\r
-{\r
- DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_WRITE);\r
-}\r
-\r
-\r
-/**\r
- Write firmware configuration bytes from a buffer\r
-\r
- If called multiple times, then the data written will continue at the offset\r
- of the firmware configuration item where the previous write ended.\r
-\r
- @param[in] Size Size in bytes to write\r
- @param[in] Buffer Buffer to read data from\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgWriteBytes (\r
- IN UINTN Size,\r
- IN VOID *Buffer\r
- )\r
-{\r
- if (QemuFwCfgIsAvailable ()) {\r
- InternalQemuFwCfgWriteBytes (Size, Buffer);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Slow SKIP_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-MmioSkipBytes (\r
- IN UINTN Size\r
- )\r
-{\r
- UINTN ChunkSize;\r
- UINT8 SkipBuffer[256];\r
-\r
- //\r
- // Emulate the skip by reading data in chunks, and throwing it away. The\r
- // implementation below doesn't affect the static data footprint for client\r
- // modules. Large skips are not expected, therefore this fallback is not\r
- // performance critical. The size of SkipBuffer is thought not to exert a\r
- // large pressure on the stack.\r
- //\r
- while (Size > 0) {\r
- ChunkSize = MIN (Size, sizeof SkipBuffer);\r
- MmioReadBytes (ChunkSize, SkipBuffer);\r
- Size -= ChunkSize;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Fast SKIP_BYTES_FUNCTION.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-DmaSkipBytes (\r
- IN UINTN Size\r
- )\r
-{\r
- DmaTransferBytes (Size, NULL, FW_CFG_DMA_CTL_SKIP);\r
-}\r
-\r
-\r
-/**\r
- Skip bytes in the firmware configuration item.\r
-\r
- Increase the offset of the firmware configuration item without transferring\r
- bytes between the item and a caller-provided buffer. Subsequent read, write\r
- or skip operations will commence at the increased offset.\r
-\r
- @param[in] Size Number of bytes to skip.\r
-**/\r
-VOID\r
-EFIAPI\r
-QemuFwCfgSkipBytes (\r
- IN UINTN Size\r
- )\r
-{\r
- if (QemuFwCfgIsAvailable ()) {\r
- InternalQemuFwCfgSkipBytes (Size);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Reads a UINT8 firmware configuration value\r
-\r
- @return Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT8\r
-EFIAPI\r
-QemuFwCfgRead8 (\r
- VOID\r
- )\r
-{\r
- UINT8 Result;\r
-\r
- QemuFwCfgReadBytes (sizeof Result, &Result);\r
- return Result;\r
-}\r
-\r
-\r
-/**\r
- Reads a UINT16 firmware configuration value\r
-\r
- @return Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT16\r
-EFIAPI\r
-QemuFwCfgRead16 (\r
- VOID\r
- )\r
-{\r
- UINT16 Result;\r
-\r
- QemuFwCfgReadBytes (sizeof Result, &Result);\r
- return Result;\r
-}\r
-\r
-\r
-/**\r
- Reads a UINT32 firmware configuration value\r
-\r
- @return Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-QemuFwCfgRead32 (\r
- VOID\r
- )\r
-{\r
- UINT32 Result;\r
-\r
- QemuFwCfgReadBytes (sizeof Result, &Result);\r
- return Result;\r
-}\r
-\r
-\r
-/**\r
- Reads a UINT64 firmware configuration value\r
-\r
- @return Value of Firmware Configuration item read\r
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-QemuFwCfgRead64 (\r
- VOID\r
- )\r
-{\r
- UINT64 Result;\r
-\r
- QemuFwCfgReadBytes (sizeof Result, &Result);\r
- return Result;\r
-}\r
-\r
-\r
-/**\r
- Find the configuration item corresponding to the firmware configuration file.\r
-\r
- @param[in] Name Name of file to look up.\r
- @param[out] Item Configuration item corresponding to the file, to be passed\r
- to QemuFwCfgSelectItem ().\r
- @param[out] Size Number of bytes in the file.\r
-\r
- @retval RETURN_SUCCESS If file is found.\r
- @retval RETURN_NOT_FOUND If file is not found.\r
- @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.\r
-\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-QemuFwCfgFindFile (\r
- IN CONST CHAR8 *Name,\r
- OUT FIRMWARE_CONFIG_ITEM *Item,\r
- OUT UINTN *Size\r
- )\r
-{\r
- UINT32 Count;\r
- UINT32 Idx;\r
-\r
- if (!QemuFwCfgIsAvailable ()) {\r
- return RETURN_UNSUPPORTED;\r
- }\r
-\r
- QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
- Count = SwapBytes32 (QemuFwCfgRead32 ());\r
-\r
- for (Idx = 0; Idx < Count; ++Idx) {\r
- UINT32 FileSize;\r
- UINT16 FileSelect;\r
- CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];\r
-\r
- FileSize = QemuFwCfgRead32 ();\r
- FileSelect = QemuFwCfgRead16 ();\r
- QemuFwCfgRead16 (); // skip the field called "reserved"\r
- InternalQemuFwCfgReadBytes (sizeof (FName), FName);\r
-\r
- if (AsciiStrCmp (Name, FName) == 0) {\r
- *Item = (FIRMWARE_CONFIG_ITEM) SwapBytes16 (FileSelect);\r
- *Size = SwapBytes32 (FileSize);\r
- return RETURN_SUCCESS;\r
- }\r
- }\r
-\r
- return RETURN_NOT_FOUND;\r
-}\r
+++ /dev/null
-## @file\r
-#\r
-# Stateful, implicitly initialized fw_cfg library.\r
-#\r
-# Copyright (C) 2013 - 2014, Red Hat, Inc.\r
-# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-#\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = QemuFwCfgLib\r
- FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF\r
- MODULE_TYPE = BASE\r
- VERSION_STRING = 1.0\r
- LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER UEFI_DRIVER\r
-\r
- CONSTRUCTOR = QemuFwCfgInitialize\r
-\r
-#\r
-# The following information is for reference only and not required by the build\r
-# tools.\r
-#\r
-# VALID_ARCHITECTURES = ARM AARCH64\r
-#\r
-\r
-[Sources]\r
- QemuFwCfgLib.c\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- OvmfPkg/OvmfPkg.dec\r
- EmbeddedPkg/EmbeddedPkg.dec\r
- ArmVirtPkg/ArmVirtPkg.dec\r
-\r
-[LibraryClasses]\r
- BaseLib\r
- BaseMemoryLib\r
- DebugLib\r
- IoLib\r
- UefiBootServicesTableLib\r
-\r
-[Protocols]\r
- gFdtClientProtocolGuid ## CONSUMES\r
-\r
-[Depex]\r
- gFdtClientProtocolGuid\r
--- /dev/null
+/** @file\r
+\r
+ Stateful and implicitly initialized fw_cfg library implementation.\r
+\r
+ Copyright (C) 2013 - 2014, Red Hat, Inc.\r
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
+\r
+STATIC UINTN mFwCfgSelectorAddress;\r
+STATIC UINTN mFwCfgDataAddress;\r
+STATIC UINTN mFwCfgDmaAddress;\r
+\r
+/**\r
+ Reads firmware configuration bytes into a buffer\r
+\r
+ @param[in] Size Size in bytes to read\r
+ @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI READ_BYTES_FUNCTION) (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ );\r
+\r
+/**\r
+ Writes bytes from a buffer to firmware configuration\r
+\r
+ @param[in] Size Size in bytes to write\r
+ @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI WRITE_BYTES_FUNCTION) (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ );\r
+\r
+/**\r
+ Skips bytes in firmware configuration\r
+\r
+ @param[in] Size Size in bytes to skip\r
+\r
+**/\r
+typedef\r
+VOID (EFIAPI SKIP_BYTES_FUNCTION) (\r
+ IN UINTN Size\r
+ );\r
+\r
+//\r
+// Forward declaration of the two implementations we have.\r
+//\r
+STATIC READ_BYTES_FUNCTION MmioReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION MmioWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION MmioSkipBytes;\r
+STATIC READ_BYTES_FUNCTION DmaReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION DmaWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION DmaSkipBytes;\r
+\r
+//\r
+// These correspond to the implementation we detect at runtime.\r
+//\r
+STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;\r
+STATIC WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;\r
+STATIC SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;\r
+\r
+\r
+/**\r
+ Returns a boolean indicating if the firmware configuration interface\r
+ is available or not.\r
+\r
+ This function may change fw_cfg state.\r
+\r
+ @retval TRUE The interface is available\r
+ @retval FALSE The interface is not available\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QemuFwCfgIsAvailable (\r
+ VOID\r
+ )\r
+{\r
+ return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);\r
+}\r
+\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+QemuFwCfgInitialize (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FDT_CLIENT_PROTOCOL *FdtClient;\r
+ CONST UINT64 *Reg;\r
+ UINT32 RegSize;\r
+ UINTN AddressCells, SizeCells;\r
+ UINT64 FwCfgSelectorAddress;\r
+ UINT64 FwCfgSelectorSize;\r
+ UINT64 FwCfgDataAddress;\r
+ UINT64 FwCfgDataSize;\r
+ UINT64 FwCfgDmaAddress;\r
+ UINT64 FwCfgDmaSize;\r
+\r
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
+ (VOID **)&FdtClient);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = FdtClient->FindCompatibleNodeReg (FdtClient, "qemu,fw-cfg-mmio",\r
+ (CONST VOID **)&Reg, &AddressCells, &SizeCells,\r
+ &RegSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN,\r
+ "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",\r
+ __FUNCTION__, Status));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT (AddressCells == 2);\r
+ ASSERT (SizeCells == 2);\r
+ ASSERT (RegSize == 2 * sizeof (UINT64));\r
+\r
+ FwCfgDataAddress = SwapBytes64 (Reg[0]);\r
+ FwCfgDataSize = 8;\r
+ FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;\r
+ FwCfgSelectorSize = 2;\r
+\r
+ //\r
+ // The following ASSERT()s express\r
+ //\r
+ // Address + Size - 1 <= MAX_UINTN\r
+ //\r
+ // for both registers, that is, that the last byte in each MMIO range is\r
+ // expressible as a MAX_UINTN. The form below is mathematically\r
+ // equivalent, and it also prevents any unsigned overflow before the\r
+ // comparison.\r
+ //\r
+ ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);\r
+ ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);\r
+\r
+ mFwCfgSelectorAddress = FwCfgSelectorAddress;\r
+ mFwCfgDataAddress = FwCfgDataAddress;\r
+\r
+ DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress,\r
+ FwCfgDataAddress));\r
+\r
+ if (SwapBytes64 (Reg[1]) >= 0x18) {\r
+ FwCfgDmaAddress = FwCfgDataAddress + 0x10;\r
+ FwCfgDmaSize = 0x08;\r
+\r
+ //\r
+ // See explanation above.\r
+ //\r
+ ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);\r
+\r
+ DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));\r
+ } else {\r
+ FwCfgDmaAddress = 0;\r
+ }\r
+\r
+ if (QemuFwCfgIsAvailable ()) {\r
+ UINT32 Signature;\r
+\r
+ QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
+ Signature = QemuFwCfgRead32 ();\r
+ if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {\r
+ //\r
+ // For DMA support, we require the DTB to advertise the register, and the\r
+ // feature bitmap (which we read without DMA) to confirm the feature.\r
+ //\r
+ if (FwCfgDmaAddress != 0) {\r
+ UINT32 Features;\r
+\r
+ QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);\r
+ Features = QemuFwCfgRead32 ();\r
+ if ((Features & FW_CFG_F_DMA) != 0) {\r
+ mFwCfgDmaAddress = FwCfgDmaAddress;\r
+ InternalQemuFwCfgReadBytes = DmaReadBytes;\r
+ InternalQemuFwCfgWriteBytes = DmaWriteBytes;\r
+ InternalQemuFwCfgSkipBytes = DmaSkipBytes;\r
+ }\r
+ }\r
+ } else {\r
+ mFwCfgSelectorAddress = 0;\r
+ mFwCfgDataAddress = 0;\r
+ }\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Selects a firmware configuration item for reading.\r
+\r
+ Following this call, any data read from this item will start from the\r
+ beginning of the configuration item's data.\r
+\r
+ @param[in] QemuFwCfgItem Firmware Configuration item to read\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgSelectItem (\r
+ IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem\r
+ )\r
+{\r
+ if (QemuFwCfgIsAvailable ()) {\r
+ MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Slow READ_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioReadBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ UINTN Left;\r
+ UINT8 *Ptr;\r
+ UINT8 *End;\r
+\r
+#ifdef MDE_CPU_AARCH64\r
+ Left = Size & 7;\r
+#else\r
+ Left = Size & 3;\r
+#endif\r
+\r
+ Size -= Left;\r
+ Ptr = Buffer;\r
+ End = Ptr + Size;\r
+\r
+#ifdef MDE_CPU_AARCH64\r
+ while (Ptr < End) {\r
+ *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);\r
+ Ptr += 8;\r
+ }\r
+ if (Left & 4) {\r
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
+ Ptr += 4;\r
+ }\r
+#else\r
+ while (Ptr < End) {\r
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);\r
+ Ptr += 4;\r
+ }\r
+#endif\r
+\r
+ if (Left & 2) {\r
+ *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);\r
+ Ptr += 2;\r
+ }\r
+ if (Left & 1) {\r
+ *Ptr = MmioRead8 (mFwCfgDataAddress);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Transfer an array of bytes, or skip a number of bytes, using the DMA\r
+ interface.\r
+\r
+ @param[in] Size Size in bytes to transfer or skip.\r
+\r
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,\r
+ and may be NULL, if Size is zero, or Control is\r
+ FW_CFG_DMA_CTL_SKIP.\r
+\r
+ @param[in] Control One of the following:\r
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.\r
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.\r
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.\r
+**/\r
+STATIC\r
+VOID\r
+DmaTransferBytes (\r
+ IN UINTN Size,\r
+ IN OUT VOID *Buffer OPTIONAL,\r
+ IN UINT32 Control\r
+ )\r
+{\r
+ volatile FW_CFG_DMA_ACCESS Access;\r
+ UINT32 Status;\r
+\r
+ ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||\r
+ Control == FW_CFG_DMA_CTL_SKIP);\r
+\r
+ if (Size == 0) {\r
+ return;\r
+ }\r
+\r
+ ASSERT (Size <= MAX_UINT32);\r
+\r
+ Access.Control = SwapBytes32 (Control);\r
+ Access.Length = SwapBytes32 ((UINT32)Size);\r
+ Access.Address = SwapBytes64 ((UINT64)(UINTN)Buffer);\r
+\r
+ //\r
+ // We shouldn't start the transfer before setting up Access.\r
+ //\r
+ MemoryFence ();\r
+\r
+ //\r
+ // This will fire off the transfer.\r
+ //\r
+#ifdef MDE_CPU_AARCH64\r
+ MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));\r
+#else\r
+ MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));\r
+#endif\r
+\r
+ //\r
+ // We shouldn't look at Access.Control before starting the transfer.\r
+ //\r
+ MemoryFence ();\r
+\r
+ do {\r
+ Status = SwapBytes32 (Access.Control);\r
+ ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);\r
+ } while (Status != 0);\r
+\r
+ //\r
+ // The caller will want to access the transferred data.\r
+ //\r
+ MemoryFence ();\r
+}\r
+\r
+\r
+/**\r
+ Fast READ_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaReadBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_READ);\r
+}\r
+\r
+\r
+/**\r
+ Reads firmware configuration bytes into a buffer\r
+\r
+ If called multiple times, then the data read will continue at the offset of\r
+ the firmware configuration item where the previous read ended.\r
+\r
+ @param[in] Size Size in bytes to read\r
+ @param[in] Buffer Buffer to store data into\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgReadBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ if (QemuFwCfgIsAvailable ()) {\r
+ InternalQemuFwCfgReadBytes (Size, Buffer);\r
+ } else {\r
+ ZeroMem (Buffer, Size);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Slow WRITE_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioWriteBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ UINTN Idx;\r
+\r
+ for (Idx = 0; Idx < Size; ++Idx) {\r
+ MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Fast WRITE_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaWriteBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+{\r
+ DmaTransferBytes (Size, Buffer, FW_CFG_DMA_CTL_WRITE);\r
+}\r
+\r
+\r
+/**\r
+ Write firmware configuration bytes from a buffer\r
+\r
+ If called multiple times, then the data written will continue at the offset\r
+ of the firmware configuration item where the previous write ended.\r
+\r
+ @param[in] Size Size in bytes to write\r
+ @param[in] Buffer Buffer to read data from\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgWriteBytes (\r
+ IN UINTN Size,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ if (QemuFwCfgIsAvailable ()) {\r
+ InternalQemuFwCfgWriteBytes (Size, Buffer);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Slow SKIP_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+MmioSkipBytes (\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN ChunkSize;\r
+ UINT8 SkipBuffer[256];\r
+\r
+ //\r
+ // Emulate the skip by reading data in chunks, and throwing it away. The\r
+ // implementation below doesn't affect the static data footprint for client\r
+ // modules. Large skips are not expected, therefore this fallback is not\r
+ // performance critical. The size of SkipBuffer is thought not to exert a\r
+ // large pressure on the stack.\r
+ //\r
+ while (Size > 0) {\r
+ ChunkSize = MIN (Size, sizeof SkipBuffer);\r
+ MmioReadBytes (ChunkSize, SkipBuffer);\r
+ Size -= ChunkSize;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Fast SKIP_BYTES_FUNCTION.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+DmaSkipBytes (\r
+ IN UINTN Size\r
+ )\r
+{\r
+ DmaTransferBytes (Size, NULL, FW_CFG_DMA_CTL_SKIP);\r
+}\r
+\r
+\r
+/**\r
+ Skip bytes in the firmware configuration item.\r
+\r
+ Increase the offset of the firmware configuration item without transferring\r
+ bytes between the item and a caller-provided buffer. Subsequent read, write\r
+ or skip operations will commence at the increased offset.\r
+\r
+ @param[in] Size Number of bytes to skip.\r
+**/\r
+VOID\r
+EFIAPI\r
+QemuFwCfgSkipBytes (\r
+ IN UINTN Size\r
+ )\r
+{\r
+ if (QemuFwCfgIsAvailable ()) {\r
+ InternalQemuFwCfgSkipBytes (Size);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Reads a UINT8 firmware configuration value\r
+\r
+ @return Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+QemuFwCfgRead8 (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 Result;\r
+\r
+ QemuFwCfgReadBytes (sizeof Result, &Result);\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Reads a UINT16 firmware configuration value\r
+\r
+ @return Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+QemuFwCfgRead16 (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 Result;\r
+\r
+ QemuFwCfgReadBytes (sizeof Result, &Result);\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Reads a UINT32 firmware configuration value\r
+\r
+ @return Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+QemuFwCfgRead32 (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 Result;\r
+\r
+ QemuFwCfgReadBytes (sizeof Result, &Result);\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Reads a UINT64 firmware configuration value\r
+\r
+ @return Value of Firmware Configuration item read\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+QemuFwCfgRead64 (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ QemuFwCfgReadBytes (sizeof Result, &Result);\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Find the configuration item corresponding to the firmware configuration file.\r
+\r
+ @param[in] Name Name of file to look up.\r
+ @param[out] Item Configuration item corresponding to the file, to be passed\r
+ to QemuFwCfgSelectItem ().\r
+ @param[out] Size Number of bytes in the file.\r
+\r
+ @retval RETURN_SUCCESS If file is found.\r
+ @retval RETURN_NOT_FOUND If file is not found.\r
+ @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+QemuFwCfgFindFile (\r
+ IN CONST CHAR8 *Name,\r
+ OUT FIRMWARE_CONFIG_ITEM *Item,\r
+ OUT UINTN *Size\r
+ )\r
+{\r
+ UINT32 Count;\r
+ UINT32 Idx;\r
+\r
+ if (!QemuFwCfgIsAvailable ()) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
+ Count = SwapBytes32 (QemuFwCfgRead32 ());\r
+\r
+ for (Idx = 0; Idx < Count; ++Idx) {\r
+ UINT32 FileSize;\r
+ UINT16 FileSelect;\r
+ CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];\r
+\r
+ FileSize = QemuFwCfgRead32 ();\r
+ FileSelect = QemuFwCfgRead16 ();\r
+ QemuFwCfgRead16 (); // skip the field called "reserved"\r
+ InternalQemuFwCfgReadBytes (sizeof (FName), FName);\r
+\r
+ if (AsciiStrCmp (Name, FName) == 0) {\r
+ *Item = (FIRMWARE_CONFIG_ITEM) SwapBytes16 (FileSelect);\r
+ *Size = SwapBytes32 (FileSize);\r
+ return RETURN_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return RETURN_NOT_FOUND;\r
+}\r
--- /dev/null
+## @file\r
+#\r
+# Stateful, implicitly initialized fw_cfg library.\r
+#\r
+# Copyright (C) 2013 - 2014, Red Hat, Inc.\r
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = QemuFwCfgLib\r
+ FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER UEFI_DRIVER\r
+\r
+ CONSTRUCTOR = QemuFwCfgInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+# VALID_ARCHITECTURES = ARM AARCH64\r
+#\r
+\r
+[Sources]\r
+ QemuFwCfgLibMmio.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ IoLib\r
+ UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+ gFdtClientProtocolGuid ## CONSUMES\r
+\r
+[Depex]\r
+ gFdtClientProtocolGuid\r