Copyright (C) 2015, Red Hat, Inc.\r
Copyright (c) 2009 - 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,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Library/UefiRuntimeLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
+#include <Library/VmgExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
\r
#include "QemuFlash.h"\r
\r
+STATIC EFI_PHYSICAL_ADDRESS mSevEsFlashPhysBase;\r
+\r
VOID\r
QemuFlashConvertPointers (\r
VOID\r
)\r
{\r
- EfiConvertPointer (0x0, (VOID **) &mFlashBase);\r
+ if (MemEncryptSevEsIsEnabled ()) {\r
+ mSevEsFlashPhysBase = (UINTN)mFlashBase;\r
+ }\r
+\r
+ EfiConvertPointer (0x0, (VOID **)&mFlashBase);\r
}\r
\r
VOID\r
QemuFlashBeforeProbe (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINTN FdBlockSize,\r
- IN UINTN FdBlockCount\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINTN FdBlockSize,\r
+ IN UINTN FdBlockCount\r
)\r
{\r
//\r
// Do nothing\r
//\r
}\r
+\r
+/**\r
+ Write to QEMU Flash\r
+\r
+ @param[in] Ptr Pointer to the location to write.\r
+ @param[in] Value The value to write.\r
+\r
+**/\r
+VOID\r
+QemuFlashPtrWrite (\r
+ IN volatile UINT8 *Ptr,\r
+ IN UINT8 Value\r
+ )\r
+{\r
+ if (MemEncryptSevEsIsEnabled ()) {\r
+ MSR_SEV_ES_GHCB_REGISTER Msr;\r
+ GHCB *Ghcb;\r
+ EFI_PHYSICAL_ADDRESS PhysAddr;\r
+ BOOLEAN InterruptState;\r
+\r
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+ Ghcb = Msr.Ghcb;\r
+\r
+ //\r
+ // The MMIO write needs to be to the physical address of the flash pointer.\r
+ // Since this service is available as part of the EFI runtime services,\r
+ // account for a non-identity mapped VA after SetVirtualAddressMap().\r
+ //\r
+ if (mSevEsFlashPhysBase == 0) {\r
+ PhysAddr = (UINTN)Ptr;\r
+ } else {\r
+ PhysAddr = mSevEsFlashPhysBase + (Ptr - mFlashBase);\r
+ }\r
+\r
+ //\r
+ // Writing to flash is emulated by the hypervisor through the use of write\r
+ // protection. This won't work for an SEV-ES guest because the write won't\r
+ // be recognized as a true MMIO write, which would result in the required\r
+ // #VC exception. Instead, use the the VMGEXIT MMIO write support directly\r
+ // to perform the update.\r
+ //\r
+ VmgInit (Ghcb, &InterruptState);\r
+ Ghcb->SharedBuffer[0] = Value;\r
+ Ghcb->SaveArea.SwScratch = (UINT64)(UINTN)Ghcb->SharedBuffer;\r
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+ VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, PhysAddr, 1);\r
+ VmgDone (Ghcb, InterruptState);\r
+ } else {\r
+ *Ptr = Value;\r
+ }\r
+}\r