]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtualizationPkg: introduce QemuFwCfgLib instance for DXE drivers
authorLaszlo Ersek <lersek@redhat.com>
Fri, 2 Jan 2015 12:04:15 +0000 (12:04 +0000)
committerlersek <lersek@Edk2>
Fri, 2 Jan 2015 12:04:15 +0000 (12:04 +0000)
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

ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc
ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c [new file with mode: 0644]
ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf [new file with mode: 0644]

index d23832fc013024be5dd65e43ab92bd4dfcad120e..c18b7a0609cfde442b2a1db337fbc8e41791b511 100644 (file)
@@ -42,6 +42,7 @@
   # Virtio Support\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
   VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf\r
+  QemuFwCfgLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
 \r
   ArmPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf\r
   ArmPlatformSysConfigLib|ArmPlatformPkg/Library/ArmPlatformSysConfigLibNull/ArmPlatformSysConfigLibNull.inf\r
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
new file mode 100644 (file)
index 0000000..e9e96d7
--- /dev/null
@@ -0,0 +1,358 @@
+/** @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
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+\r
+STATIC UINTN mFwCfgSelectorAddress;\r
+STATIC UINTN mFwCfgDataAddress;\r
+\r
+\r
+/**\r
+  Returns a boolean indicating if the firmware configuration interface is\r
+  available for library-internal purposes.\r
+\r
+  This function never changes fw_cfg state.\r
+\r
+  @retval TRUE   The interface is available internally.\r
+  @retval FALSE  The interface is not available internally.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalQemuFwCfgIsAvailable (\r
+  VOID\r
+  )\r
+{\r
+  return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);\r
+}\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 InternalQemuFwCfgIsAvailable ();\r
+}\r
+\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+QemuFwCfgInitialize (\r
+  VOID\r
+  )\r
+{\r
+  mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);\r
+  mFwCfgDataAddress     = (UINTN)PcdGet64 (PcdFwCfgDataAddress);\r
+\r
+  if (InternalQemuFwCfgIsAvailable ()) {\r
+    UINT32 Signature;\r
+\r
+    QemuFwCfgSelectItem (QemuFwCfgItemSignature);\r
+    Signature = QemuFwCfgRead32 ();\r
+    if (Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) {\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 (InternalQemuFwCfgIsAvailable ()) {\r
+    MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));\r
+  }\r
+}\r
+\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
+STATIC\r
+VOID\r
+EFIAPI\r
+InternalQemuFwCfgReadBytes (\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
+  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 (InternalQemuFwCfgIsAvailable ()) {\r
+    InternalQemuFwCfgReadBytes (Size, Buffer);\r
+  } else {\r
+    ZeroMem (Buffer, Size);\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 (InternalQemuFwCfgIsAvailable ()) {\r
+    UINTN Idx;\r
+\r
+    for (Idx = 0; Idx < Size; ++Idx) {\r
+      MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);\r
+    }\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 (!InternalQemuFwCfgIsAvailable ()) {\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 = SwapBytes16 (FileSelect);\r
+      *Size = SwapBytes32 (FileSize);\r
+      return RETURN_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return RETURN_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Determine if S3 support is explicitly enabled.\r
+\r
+  @retval TRUE   if S3 support is explicitly enabled.\r
+          FALSE  otherwise. This includes unavailability of the firmware\r
+                 configuration interface.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+QemuFwCfgS3Enabled (\r
+  VOID\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
new file mode 100644 (file)
index 0000000..21ab2bf
--- /dev/null
@@ -0,0 +1,52 @@
+## @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
+#  This program and the accompanying materials are licensed and made available\r
+#  under the terms and conditions of the BSD License which accompanies this\r
+#  distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR\r
+#  IMPLIED.\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\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
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  IoLib\r
+  PcdLib\r
+\r
+[Pcd]\r
+  gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress\r
+  gArmVirtualizationTokenSpaceGuid.PcdFwCfgDataAddress\r