]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
[mirror_edk2.git] / OvmfPkg / Library / QemuFwCfgLib / QemuFwCfgDxe.c
index ac05f4c347f38986ad474373dfa19bef3512b0ca..f8eb03bc3a9a4d7188f5aa110086b0651c831f04 100644 (file)
@@ -4,6 +4,7 @@
 \r
   Copyright (C) 2013, Red Hat, Inc.\r
   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, Advanced Micro Devices. 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
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 **/\r
 \r
+#include <Uefi.h>\r
+\r
+#include <Protocol/IoMmu.h>\r
+\r
+#include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/QemuFwCfgLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
 \r
 #include "QemuFwCfgLibInternal.h"\r
 \r
 STATIC BOOLEAN mQemuFwCfgSupported = FALSE;\r
 STATIC BOOLEAN mQemuFwCfgDmaSupported;\r
 \r
+STATIC EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;\r
+/**\r
+\r
+ Returns a boolean indicating whether SEV is enabled\r
+\r
+ @retval    TRUE    SEV is enabled\r
+ @retval    FALSE   SEV is disabled\r
+**/\r
+BOOLEAN\r
+InternalQemuFwCfgSevIsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  return MemEncryptSevIsEnabled ();\r
+}\r
 \r
 /**\r
   Returns a boolean indicating if the firmware configuration interface\r
@@ -79,6 +102,24 @@ QemuFwCfgInitialize (
     mQemuFwCfgDmaSupported = TRUE;\r
     DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));\r
   }\r
+\r
+  if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) {\r
+    EFI_STATUS   Status;\r
+\r
+    //\r
+    // IoMmuDxe driver must have installed the IOMMU protocol. If we are not\r
+    // able to locate the protocol then something must have gone wrong.\r
+    //\r
+    Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR,\r
+        "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",\r
+        gEfiCallerBaseName, __FUNCTION__));\r
+      ASSERT (FALSE);\r
+      CpuDeadLoop ();\r
+    }\r
+  }\r
+\r
   return RETURN_SUCCESS;\r
 }\r
 \r
@@ -114,3 +155,76 @@ InternalQemuFwCfgDmaIsAvailable (
 {\r
   return mQemuFwCfgDmaSupported;\r
 }\r
+\r
+/**\r
+ Allocate a bounce buffer for SEV DMA.\r
+\r
+  @param[in]     NumPage  Number of pages.\r
+  @param[out]    Buffer   Allocated DMA Buffer pointer\r
+\r
+**/\r
+VOID\r
+InternalQemuFwCfgSevDmaAllocateBuffer (\r
+  OUT    VOID     **Buffer,\r
+  IN     UINT32   NumPages\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  ASSERT (mIoMmuProtocol != NULL);\r
+\r
+  Status = mIoMmuProtocol->AllocateBuffer (\r
+                            mIoMmuProtocol,\r
+                            0,\r
+                            EfiBootServicesData,\r
+                            NumPages,\r
+                            Buffer,\r
+                            EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR,\r
+      "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, __FUNCTION__,\r
+      NumPages));\r
+    ASSERT (FALSE);\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  DEBUG ((DEBUG_VERBOSE,\r
+    "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, __FUNCTION__,\r
+    (UINT64)(UINTN)Buffer, NumPages));\r
+}\r
+\r
+/**\r
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer\r
+\r
+  @param[in]     NumPage  Number of pages.\r
+  @param[in]     Buffer   DMA Buffer pointer\r
+\r
+**/\r
+VOID\r
+InternalQemuFwCfgSevDmaFreeBuffer (\r
+  IN     VOID     *Buffer,\r
+  IN     UINT32   NumPages\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  ASSERT (mIoMmuProtocol != NULL);\r
+\r
+  Status = mIoMmuProtocol->FreeBuffer (\r
+                            mIoMmuProtocol,\r
+                            NumPages,\r
+                            Buffer\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR,\r
+      "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName,\r
+      __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));\r
+    ASSERT (FALSE);\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  DEBUG ((DEBUG_VERBOSE,\r
+    "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,__FUNCTION__,\r
+    (UINT64)(UINTN)Buffer, NumPages));\r
+}\r