Revision: 16567
          http://sourceforge.net/p/edk2/code/16567
Author:   lersek
Date:     2015-01-02 12:04:15 +0000 (Fri, 02 Jan 2015)
Log Message:
-----------
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 <[email protected]>

Modified Paths:
--------------
    trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc

Added Paths:
-----------
    trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/
    
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
    
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf

Modified: 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
===================================================================
--- trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc    
2015-01-02 12:04:05 UTC (rev 16566)
+++ trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc    
2015-01-02 12:04:15 UTC (rev 16567)
@@ -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

Added: 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
===================================================================
--- 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
                          (rev 0)
+++ 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
  2015-01-02 12:04:15 UTC (rev 16567)
@@ -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;
+}

Added: 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
===================================================================
--- 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
                                (rev 0)
+++ 
trunk/edk2/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
        2015-01-02 12:04:15 UTC (rev 16567)
@@ -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


------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to