After reviewing OvmfPkg's use of its own QemuFwCfgLib instances, it is clear that its only pre-DXE fw_cfg dependency concerns S3 support (the QemuFwCfgS3Enabled() call in "PlatformPei/Platform.c").
For ARM guests, S3 is in the distant future, but we can see several shorter term applications for fw_cfg that all reside in DXE: - controlling boot order (to be implemented in PlatformBdsLib for Intel BDS), - loading and linking ACPI tables, - installing SMBIOS tables. Therefore it makes sense to add a simple MMIO-based fw_cfg client library to ArmVirtualizationPkg that for the moment is only available to DXE_DRIVER modules. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf | 52 +++++++++++ ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 1 + 3 files changed, 379 insertions(+) diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf new file mode 100644 index 0000000..21ab2bf --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf @@ -0,0 +1,52 @@ +## @file +# +# Stateful, implicitly initialized fw_cfg library. +# +# Copyright (C) 2013 - 2014, Red Hat, Inc. +# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = QemuFwCfgLib + FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER + + CONSTRUCTOR = QemuFwCfgInitialize + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + QemuFwCfgLib.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + IoLib + PcdLib + +[Pcd] + gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress + gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c new file mode 100644 index 0000000..fbc0dfb --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c @@ -0,0 +1,326 @@ +/** @file + + Stateful and implicitly initialized fw_cfg library implementation. + + Copyright (C) 2013 - 2014, Red Hat, Inc. + Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR> + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/QemuFwCfgLib.h> + +STATIC UINTN mFwCfgSelectorAddress; +STATIC UINTN mFwCfgDataAddress; + + +/** + 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 +EFIAPI +InternalQemuFwCfgIsAvailable ( + VOID + ) +{ + return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0); +} + + +/** + 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 + ) +{ + return InternalQemuFwCfgIsAvailable (); +} + + +RETURN_STATUS +EFIAPI +QemuFwCfgInitialize ( + VOID + ) +{ + mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress); + mFwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress); + + if (InternalQemuFwCfgIsAvailable ()) { + UINT32 Signature; + + QemuFwCfgSelectItem (QemuFwCfgItemSignature); + Signature = QemuFwCfgRead32 (); + if (Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) { + mFwCfgSelectorAddress = 0; + mFwCfgDataAddress = 0; + } + } + return RETURN_SUCCESS; +} + + +/** + 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 + ) +{ + if (InternalQemuFwCfgIsAvailable ()) { + MmioWrite16 (mFwCfgSelectorAddress, (UINT16)QemuFwCfgItem); + } +} + + +/** + 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) + +**/ +STATIC +VOID +EFIAPI +InternalQemuFwCfgReadBytes ( + IN UINTN Size, + IN VOID *Buffer OPTIONAL + ) +{ + UINTN Idx; + + for (Idx = 0; Idx < Size; ++Idx) { + ((UINT8 *)Buffer)[Idx] = MmioRead8 (mFwCfgDataAddress); + } +} + + +/** + 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 ()) { + UINTN Idx; + + for (Idx = 0; Idx < Size; ++Idx) { + MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]); + } + } +} + + +/** + 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. + + @retval RETURN_SUCCESS If file is found. + @retval RETURN_NOT_FOUND If file is not found. + @retval 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 FName[QEMU_FW_CFG_FNAME_SIZE]; + + FileSize = QemuFwCfgRead32 (); + FileSelect = QemuFwCfgRead16 (); + QemuFwCfgRead16 (); // skip the field called "reserved" + InternalQemuFwCfgReadBytes (sizeof (FName), FName); + + if (AsciiStrCmp (Name, FName) == 0) { + *Item = SwapBytes16 (FileSelect); + *Size = SwapBytes32 (FileSize); + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + + +/** + Determine if S3 support is explicitly enabled. + + @retval TRUE if S3 support is explicitly enabled. + FALSE otherwise. This includes unavailability of the firmware + configuration interface. +**/ +BOOLEAN +EFIAPI +QemuFwCfgS3Enabled ( + VOID + ) +{ + return FALSE; +} diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc index 1f3ddea..60f7d7f 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc @@ -42,6 +42,7 @@ # Virtio Support VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf + QemuFwCfgLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf ArmPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf ArmPlatformSysConfigLib|ArmPlatformPkg/Library/ArmPlatformSysConfigLibNull/ArmPlatformSysConfigLibNull.inf -- 1.8.3.1