summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/PlatformPei/MemTypeInfo.c
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2020-03-10 23:27:39 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2020-03-12 21:14:46 +0000
commitd42fdd6f8384bb4681d93e4a25d8f57db1e63adb (patch)
treebebabc8a88045ea38c041a5bd1de07f92baa2401 /OvmfPkg/PlatformPei/MemTypeInfo.c
parent89465fe9e0ccd03168f822289ec8878676d5df8b (diff)
downloadedk2-d42fdd6f8384bb4681d93e4a25d8f57db1e63adb.tar.gz
edk2-d42fdd6f8384bb4681d93e4a25d8f57db1e63adb.tar.bz2
edk2-d42fdd6f8384bb4681d93e4a25d8f57db1e63adb.zip
OvmfPkg: improve SMM comms security with adaptive MemoryTypeInformation
* In the Intel whitepaper: --v-- A Tour Beyond BIOS -- Secure SMM Communication https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Security-White-Papers https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Secure_SMM_Communication.pdf --^-- bullet#3 in section "Assumption and Recommendation", and bullet#4 in "Call for action", recommend enabling the (adaptive) Memory Type Information feature. * In the Intel whitepaper: --v-- A Tour Beyond BIOS -- Memory Map and Practices in UEFI BIOS https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-white-papers https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Memory_Map_And_Practices_in_UEFI_BIOS_V2.pdf --^-- figure#6 describes the Memory Type Information feature in detail; namely as a feedback loop between the Platform PEIM, the DXE IPL PEIM, the DXE Core, and BDS. Implement the missing PlatformPei functionality in OvmfPkg, for fulfilling the Secure SMM Communication recommendation. In the longer term, OVMF should install the WSMT ACPI table, and this patch contributes to that. Notes: - the step in figure#6 where the UEFI variable is copied into the HOB is covered by the DXE IPL PEIM, in the DxeLoadCore() function, - "PcdResetOnMemoryTypeInformationChange" must be reverted to the DEC default TRUE value, because both whitepapers indicate that BDS needs to reset the system if the Memory Type Information changes. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=386 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200310222739.26717-6-lersek@redhat.com> Acked-by: Leif Lindholm <leif@nuviainc.com>
Diffstat (limited to 'OvmfPkg/PlatformPei/MemTypeInfo.c')
-rw-r--r--OvmfPkg/PlatformPei/MemTypeInfo.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/OvmfPkg/PlatformPei/MemTypeInfo.c b/OvmfPkg/PlatformPei/MemTypeInfo.c
new file mode 100644
index 0000000000..c709236a45
--- /dev/null
+++ b/OvmfPkg/PlatformPei/MemTypeInfo.c
@@ -0,0 +1,147 @@
+/** @file
+ Produce a default memory type information HOB unless we can determine, from
+ the existence of the "MemoryTypeInformation" variable, that the DXE IPL PEIM
+ will produce the HOB.
+
+ Copyright (C) 2017-2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/MemoryTypeInformation.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Uefi/UefiMultiPhase.h>
+
+#include "Platform.h"
+
+STATIC EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiACPIMemoryNVS, 0x004 },
+ { EfiACPIReclaimMemory, 0x008 },
+ { EfiReservedMemoryType, 0x004 },
+ { EfiRuntimeServicesData, 0x024 },
+ { EfiRuntimeServicesCode, 0x030 },
+ { EfiBootServicesCode, 0x180 },
+ { EfiBootServicesData, 0xF00 },
+ { EfiMaxMemoryType, 0x000 }
+};
+
+STATIC
+VOID
+BuildMemTypeInfoHob (
+ VOID
+ )
+{
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof mDefaultMemoryTypeInformation
+ );
+ DEBUG ((DEBUG_INFO, "%a: default memory type information HOB built\n",
+ __FUNCTION__));
+}
+
+/**
+ Notification function called when EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes
+ available.
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor Address of the notification descriptor data
+ structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @return Status of the notification. The status code returned from this
+ function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+OnReadOnlyVariable2Available (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2;
+ UINTN DataSize;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));
+
+ //
+ // Check if the "MemoryTypeInformation" variable exists, in the
+ // gEfiMemoryTypeInformationGuid namespace.
+ //
+ ReadOnlyVariable2 = Ppi;
+ DataSize = 0;
+ Status = ReadOnlyVariable2->GetVariable (
+ ReadOnlyVariable2,
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ NULL,
+ &DataSize,
+ NULL
+ );
+ switch (Status) {
+ case EFI_BUFFER_TOO_SMALL:
+ //
+ // The variable exists; the DXE IPL PEIM will build the HOB from it.
+ //
+ break;
+ case EFI_NOT_FOUND:
+ //
+ // The variable does not exist; install the default memory type information
+ // HOB.
+ //
+ BuildMemTypeInfoHob ();
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: unexpected: GetVariable(): %r\n", __FUNCTION__,
+ Status));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mReadOnlyVariable2Notify = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), // Flags
+ &gEfiPeiReadOnlyVariable2PpiGuid, // Guid
+ OnReadOnlyVariable2Available // Notify
+};
+
+VOID
+MemTypeInfoInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // EFI_PEI_READ_ONLY_VARIABLE2_PPI will never be available; install
+ // the default memory type information HOB right away.
+ //
+ BuildMemTypeInfoHob ();
+ return;
+ }
+
+ Status = PeiServicesNotifyPpi (&mReadOnlyVariable2Notify);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: failed to set up R/O Variable 2 callback: %r\n",
+ __FUNCTION__, Status));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+}