]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
Renamed ArmPlatformPkg/ArmVirtualizationPkg into ArmVirtPkg
[mirror_edk2.git] / ArmVirtPkg / Library / QemuFwCfgLib / QemuFwCfgLib.c
diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
new file mode 100644 (file)
index 0000000..c62eee3
--- /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 = (FIRMWARE_CONFIG_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