\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/MemEncryptSevLib.h>\r
#include <Library/PcdLib.h>\r
\r
#include "QemuFlash.h"\r
\r
DEBUG ((DEBUG_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));\r
\r
+ if (MemEncryptSevEsIsEnabled ()) {\r
+ //\r
+ // When SEV-ES is enabled, the check below can result in an infinite\r
+ // loop with respect to a nested page fault. When the memslot is mapped\r
+ // read-only, the nested page table entry is read-only. The check below\r
+ // will cause a nested page fault that cannot be emulated, causing\r
+ // the instruction to retried over and over. For SEV-ES, acknowledge that\r
+ // the FD appears as ROM and not as FLASH, but report FLASH anyway because\r
+ // FLASH behavior can be simulated using VMGEXIT.\r
+ //\r
+ DEBUG ((DEBUG_INFO,\r
+ "QEMU Flash: SEV-ES enabled, assuming FD behaves as FLASH\n"));\r
+ return TRUE;\r
+ }\r
+\r
OriginalUint8 = *Ptr;\r
*Ptr = CLEAR_STATUS_CMD;\r
ProbeUint8 = *Ptr;\r
//\r
Ptr = QemuFlashPtr (Lba, Offset);\r
for (Loop = 0; Loop < *NumBytes; Loop++) {\r
- *Ptr = WRITE_BYTE_CMD;\r
- *Ptr = Buffer[Loop];\r
+ QemuFlashPtrWrite (Ptr, WRITE_BYTE_CMD);\r
+ QemuFlashPtrWrite (Ptr, Buffer[Loop]);\r
+\r
Ptr++;\r
}\r
\r
// Restore flash to read mode\r
//\r
if (*NumBytes > 0) {\r
- *(Ptr - 1) = READ_ARRAY_CMD;\r
+ QemuFlashPtrWrite (Ptr - 1, READ_ARRAY_CMD);\r
}\r
\r
return EFI_SUCCESS;\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
// 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
+\r
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+ Ghcb = Msr.Ghcb;\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);\r
+ Ghcb->SharedBuffer[0] = Value;\r
+ Ghcb->SaveArea.SwScratch = (UINT64) (UINTN) Ghcb->SharedBuffer;\r
+ VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, (UINT64) (UINTN) Ptr, 1);\r
+ VmgDone (Ghcb);\r
+ } else {\r
+ *Ptr = Value;\r
+ }\r
+}\r