summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2015-01-02 12:04:15 +0000
committerlersek <lersek@Edk2>2015-01-02 12:04:15 +0000
commit6e2543b01d0cbd16b3fbcc6f12f6938d8c12bcc8 (patch)
tree015b36479f53e7ef98ab54de7989282959473a16
parentad652d46941c6a1e0f828cb084fb6829c3abb68d (diff)
downloadedk2-6e2543b01d0cbd16b3fbcc6f12f6938d8c12bcc8.tar.gz
edk2-6e2543b01d0cbd16b3fbcc6f12f6938d8c12bcc8.tar.bz2
edk2-6e2543b01d0cbd16b3fbcc6f12f6938d8c12bcc8.zip
ArmVirtualizationPkg: introduce QemuFwCfgLib instance for DXE drivers
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), - supporting -kernel / -initrd / -append boot on QEMU (to be implemented in PlatformBdsLib for Intel BDS, similarly), - 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. Because MMIO accesses are costly on KVM/ARM, InternalQemuFwCfgReadBytes() accesses the fw_cfg data register in full words. This speeds up transfers almost linearly. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16567 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc1
-rw-r--r--ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c358
-rw-r--r--ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf52
3 files changed, 411 insertions, 0 deletions
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
index d23832fc01..c18b7a0609 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
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
new file mode 100644
index 0000000000..e9e96d7a8d
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
@@ -0,0 +1,358 @@
+/** @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, SwapBytes16 ((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 Left;
+ UINT8 *Ptr;
+ UINT8 *End;
+
+#ifdef MDE_CPU_AARCH64
+ Left = Size & 7;
+#else
+ Left = Size & 3;
+#endif
+
+ Size -= Left;
+ Ptr = Buffer;
+ End = Ptr + Size;
+
+#ifdef MDE_CPU_AARCH64
+ while (Ptr < End) {
+ *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);
+ Ptr += 8;
+ }
+ if (Left & 4) {
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ Ptr += 4;
+ }
+#else
+ while (Ptr < End) {
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ Ptr += 4;
+ }
+#endif
+
+ if (Left & 2) {
+ *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);
+ Ptr += 2;
+ }
+ if (Left & 1) {
+ *Ptr = 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/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
new file mode 100644
index 0000000000..21ab2bf186
--- /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