#include <Library/DxeServicesTableLib.h>\r
#include <Library/MemEncryptSevLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Guid/ConfidentialComputingSevSnpBlob.h>\r
#include <Library/PcdLib.h>\r
+#include <Pi/PrePiDxeCis.h>\r
+#include <Protocol/SevMemoryAcceptance.h>\r
+#include <Protocol/MemoryAccept.h>\r
+#include <Uefi/UefiSpec.h>\r
+\r
+// Present, initialized, tested bits defined in MdeModulePkg/Core/Dxe/DxeMain.h\r
+#define EFI_MEMORY_INTERNAL_MASK 0x0700000000000000ULL\r
+\r
+STATIC CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION mSnpBootDxeTable = {\r
+ SIGNATURE_32 ('A', 'M', 'D', 'E'),\r
+ 1,\r
+ 0,\r
+ (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfSnpSecretsBase),\r
+ FixedPcdGet32 (PcdOvmfSnpSecretsSize),\r
+ (UINT64)(UINTN)FixedPcdGet32 (PcdOvmfCpuidBase),\r
+ FixedPcdGet32 (PcdOvmfCpuidSize),\r
+};\r
+\r
+STATIC EFI_HANDLE mAmdSevDxeHandle = NULL;\r
+\r
+STATIC BOOLEAN mAcceptAllMemoryAtEBS = TRUE;\r
+\r
+STATIC EFI_EVENT mAcceptAllMemoryEvent = NULL;\r
+\r
+#define IS_ALIGNED(x, y) ((((x) & ((y) - 1)) == 0))\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AmdSevMemoryAccept (\r
+ IN EDKII_MEMORY_ACCEPT_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS StartAddress,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ //\r
+ // The StartAddress must be page-aligned, and the Size must be a positive\r
+ // multiple of SIZE_4KB. Use an assert instead of returning an erros since\r
+ // this is an EDK2-internal protocol.\r
+ //\r
+ ASSERT (IS_ALIGNED (StartAddress, SIZE_4KB));\r
+ ASSERT (IS_ALIGNED (Size, SIZE_4KB));\r
+ ASSERT (Size != 0);\r
+\r
+ MemEncryptSevSnpPreValidateSystemRam (\r
+ StartAddress,\r
+ EFI_SIZE_TO_PAGES (Size)\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+AcceptAllMemory (\r
+ VOID\r
+ )\r
+{\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDescMap;\r
+ UINTN NumEntries;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO, "Accepting all memory\n"));\r
+\r
+ /*\r
+ * Get a copy of the memory space map to iterate over while\r
+ * changing the map.\r
+ */\r
+ Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < NumEntries; Index++) {\r
+ CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;\r
+\r
+ Desc = &AllDescMap[Index];\r
+ if (Desc->GcdMemoryType != EFI_GCD_MEMORY_TYPE_UNACCEPTED) {\r
+ continue;\r
+ }\r
+\r
+ Status = AmdSevMemoryAccept (\r
+ NULL,\r
+ Desc->BaseAddress,\r
+ Desc->Length\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ Status = gDS->RemoveMemorySpace (Desc->BaseAddress, Desc->Length);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeSystemMemory,\r
+ Desc->BaseAddress,\r
+ Desc->Length,\r
+ // Allocable system memory resource capabilities as masked\r
+ // in MdeModulePkg/Core/Dxe/Mem/Page.c:PromoteMemoryResource\r
+ Desc->Capabilities & ~(EFI_MEMORY_INTERNAL_MASK | EFI_MEMORY_RUNTIME)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (AllDescMap);\r
+ gBS->CloseEvent (mAcceptAllMemoryEvent);\r
+ return Status;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+ResolveUnacceptedMemory (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (!mAcceptAllMemoryAtEBS) {\r
+ return;\r
+ }\r
+\r
+ Status = AcceptAllMemory ();\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AllowUnacceptedMemory (\r
+ IN OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL *This\r
+ )\r
+{\r
+ mAcceptAllMemoryAtEBS = FALSE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL\r
+ mMemoryAcceptanceProtocol = { AllowUnacceptedMemory };\r
+\r
+STATIC EDKII_MEMORY_ACCEPT_PROTOCOL mMemoryAcceptProtocol = {\r
+ AmdSevMemoryAccept\r
+};\r
\r
EFI_STATUS\r
EFIAPI\r
}\r
}\r
\r
+ if (MemEncryptSevSnpIsEnabled ()) {\r
+ //\r
+ // Memory acceptance began being required in SEV-SNP, so install the\r
+ // memory accept protocol implementation for a SEV-SNP active guest.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mAmdSevDxeHandle,\r
+ &gEdkiiMemoryAcceptProtocolGuid,\r
+ &mMemoryAcceptProtocol,\r
+ &gOvmfSevMemoryAcceptanceProtocolGuid,\r
+ &mMemoryAcceptanceProtocol,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // SEV-SNP support does not automatically imply unaccepted memory support,\r
+ // so make ExitBootServices accept all unaccepted memory if support is\r
+ // not communicated.\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ ResolveUnacceptedMemory,\r
+ NULL,\r
+ &gEfiEventBeforeExitBootServicesGuid,\r
+ &mAcceptAllMemoryEvent\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "AllowUnacceptedMemory event creation for EventBeforeExitBootServices failed.\n"));\r
+ }\r
+\r
+ //\r
+ // If its SEV-SNP active guest then install the CONFIDENTIAL_COMPUTING_SEV_SNP_BLOB.\r
+ // It contains the location for both the Secrets and CPUID page.\r
+ //\r
+ return gBS->InstallConfigurationTable (\r
+ &gConfidentialComputingSevSnpBlobGuid,\r
+ &mSnpBootDxeTable\r
+ );\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r