diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 0212be4a33..e72a2dbc97 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -80,6 +80,7 @@
Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
Tpm2HelpLib|SecurityPkg/Library/Tpm2HelpLib/Tpm2HelpLib.inf
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+ Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf
!else
diff --git a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc
index d664775718..04541f5d91 100644
--- a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc
+++ b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc
@@ -10,6 +10,7 @@
!endif
Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+ Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf
Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
!else
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf
diff --git a/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h
new file mode 100644
index 0000000000..4299b4af43
--- /dev/null
+++ b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h
@@ -0,0 +1,41 @@
+/** @file
+ Returns the platform specific Physical Presence configuration.
+
+ Copyright (c) 2020, 9elements GmbH. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__
+#define __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__
+
+#include
+
+typedef enum {
+ Tcg2PhysicalPresenceTpmVersionUnknown,
+ Tcg2PhysicalPresenceTpmVersion12,
+ Tcg2PhysicalPresenceTpmVersion20
+} TCG2_PHYSICAL_PRESENCE_TPM_VERSION;
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS PpiAddress;
+ TCG2_PHYSICAL_PRESENCE_TPM_VERSION TpmVersion;
+ BOOLEAN PpiInMmio;
+} TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG;
+
+/**
+ Reads the platform specific Physical Presence configuration.
+
+ @param[out] Config The config structure to fill in.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A required pointer argument was NULL.
+ @retval EFI_PROTOCOL_ERROR Invalid config entry size.
+**/
+EFI_STATUS
+EFIAPI
+TpmPpiPlatformReadConfig (
+ OUT TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG *Config
+ );
+
+#endif
diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c
index 4038020251..36f4b4e8d6 100644
--- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c
+++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c
@@ -27,8 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include
#include
#include
-#include
#include
+#include
#include
#include
#include
@@ -40,42 +40,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
EFI_HII_HANDLE mTcg2PpStringPackHandle;
+#define TCG2_PHYSICAL_PRESENCE_USER_CONFIRM_TIMEOUT_100NS (3ULL * 60ULL * 10000000ULL)
+
#define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ)
STATIC volatile QEMU_TPM_PPI *mPpi;
-/**
- Reads QEMU PPI config from fw_cfg.
-
- @param[out] The Config structure to read to.
-
- @retval EFI_SUCCESS Operation completed successfully.
- @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size.
-**/
-STATIC
-EFI_STATUS
-QemuTpmReadConfig (
- OUT QEMU_FWCFG_TPM_CONFIG *Config
- )
-{
- EFI_STATUS Status;
- FIRMWARE_CONFIG_ITEM FwCfgItem;
- UINTN FwCfgSize;
-
- Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (FwCfgSize != sizeof (*Config)) {
- return EFI_PROTOCOL_ERROR;
- }
-
- QemuFwCfgSelectItem (FwCfgItem);
- QemuFwCfgReadBytes (sizeof (*Config), Config);
- return EFI_SUCCESS;
-}
-
/**
Initializes QEMU PPI memory region.
@@ -88,29 +58,34 @@ QemuTpmInitPPI (
VOID
)
{
- EFI_STATUS Status;
- QEMU_FWCFG_TPM_CONFIG Config;
- EFI_PHYSICAL_ADDRESS PpiAddress64;
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
- UINTN Idx;
+ EFI_STATUS Status;
+ TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG Config;
+ EFI_PHYSICAL_ADDRESS PpiAddress64;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
+ UINTN Idx;
if (mPpi != NULL) {
return EFI_SUCCESS;
}
- Status = QemuTpmReadConfig (&Config);
+ Status = TpmPpiPlatformReadConfig (&Config);
if (EFI_ERROR (Status)) {
return Status;
}
- mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress;
- if (mPpi == NULL) {
+ if ((Config.PpiAddress == 0) || (Config.PpiAddress > MAX_UINTN)) {
return EFI_PROTOCOL_ERROR;
}
+ PpiAddress64 = Config.PpiAddress;
+ mPpi = (QEMU_TPM_PPI *)(UINTN)PpiAddress64;
DEBUG ((DEBUG_INFO, "[TPM2PP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion));
- PpiAddress64 = (UINTN)mPpi;
+ if (PpiAddress64 > MAX_UINT64 - sizeof (*mPpi) + 1) {
+ DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi address overflows\n"));
+ goto InvalidPpiAddress;
+ }
+
if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) !=
((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK))
{
@@ -124,19 +99,29 @@ QemuTpmInitPPI (
goto InvalidPpiAddress;
}
- if (!EFI_ERROR (Status) &&
- ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) &&
- (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)))
- {
- DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n"));
- goto InvalidPpiAddress;
+ if (Config.PpiInMmio) {
+ if (!EFI_ERROR (Status) &&
+ ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) &&
+ (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)))
+ {
+ DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n"));
+ goto InvalidPpiAddress;
+ }
+ } else {
+ if (!EFI_ERROR (Status) &&
+ ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) &&
+ (Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory)))
+ {
+ DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n"));
+ goto InvalidPpiAddress;
+ }
}
for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) {
mPpi->Func[Idx] = 0;
}
- if (Config.TpmVersion == QEMU_TPM_VERSION_2) {
+ if (Config.TpmVersion == Tcg2PhysicalPresenceTpmVersion20) {
mPpi->Func[TCG2_PHYSICAL_PRESENCE_NO_ACTION] = TPM_PPI_FLAGS;
mPpi->Func[TCG2_PHYSICAL_PRESENCE_CLEAR] = TPM_PPI_FLAGS;
mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR] = TPM_PPI_FLAGS;
@@ -365,31 +350,51 @@ Tcg2ReadUserKey (
EFI_STATUS Status;
EFI_INPUT_KEY Key;
UINT16 InputKey;
+ EFI_EVENT TimeoutEvent;
+ EFI_EVENT WaitList[2];
+ UINTN WaitIndex;
- InputKey = 0;
- do {
- Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
- if (!EFI_ERROR (Status)) {
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- if (Key.ScanCode == SCAN_ESC) {
- InputKey = Key.ScanCode;
- }
-
- if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
- InputKey = Key.ScanCode;
- }
-
- if ((Key.ScanCode == SCAN_F12) && CautionKey) {
- InputKey = Key.ScanCode;
- }
- }
- } while (InputKey == 0);
-
- if (InputKey != SCAN_ESC) {
- return TRUE;
+ Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &TimeoutEvent);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
}
- return FALSE;
+ Status = gBS->SetTimer (
+ TimeoutEvent,
+ TimerRelative,
+ TCG2_PHYSICAL_PRESENCE_USER_CONFIRM_TIMEOUT_100NS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (TimeoutEvent);
+ return FALSE;
+ }
+
+ WaitList[0] = gST->ConIn->WaitForKey;
+ WaitList[1] = TimeoutEvent;
+ InputKey = 0;
+
+ while (InputKey == 0) {
+ Status = gBS->WaitForEvent (ARRAY_SIZE (WaitList), WaitList, &WaitIndex);
+ if (EFI_ERROR (Status) || (WaitIndex == 1)) {
+ break;
+ }
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if ((Key.ScanCode == SCAN_ESC) ||
+ ((Key.ScanCode == SCAN_F10) && !CautionKey) ||
+ ((Key.ScanCode == SCAN_F12) && CautionKey))
+ {
+ InputKey = Key.ScanCode;
+ }
+ }
+
+ gBS->CloseEvent (TimeoutEvent);
+
+ return (BOOLEAN)((InputKey != 0) && (InputKey != SCAN_ESC));
}
/**
diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
index 7cfc0804b2..904eafe295 100644
--- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
@@ -57,12 +57,12 @@
HobLib
MemoryAllocationLib
PrintLib
- QemuFwCfgLib
Tpm2CommandLib
UefiBootManagerLib
UefiBootServicesTableLib
UefiLib
UefiRuntimeServicesTableLib
+ Tcg2PhysicalPresencePlatformLib
[Protocols]
gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c
new file mode 100644
index 0000000000..abf30a7247
--- /dev/null
+++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c
@@ -0,0 +1,76 @@
+/** @file
+ Returns the platform specific configuration for the QEMU PPI.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable.
+ This external input must be validated carefully to avoid security issue.
+
+Copyright (C) 2018, Red Hat, Inc.
+Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include
+
+#include
+
+#include
+#include
+
+/**
+ Reads QEMU PPI config from fw_cfg.
+
+ @param[out] Config The config structure to fill in.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A required pointer argument was NULL.
+ @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size.
+**/
+EFI_STATUS
+EFIAPI
+TpmPpiPlatformReadConfig (
+ OUT TCG2_PHYSICAL_PRESENCE_PLATFORM_CONFIG *Config
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ QEMU_FWCFG_TPM_CONFIG QemuConfig;
+
+ if (Config == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (FwCfgSize != sizeof (QemuConfig)) {
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (sizeof (QemuConfig), &QemuConfig);
+
+ Config->PpiAddress = QemuConfig.PpiAddress;
+ Config->PpiInMmio = TRUE;
+
+ switch (QemuConfig.TpmVersion) {
+ case QEMU_TPM_VERSION_1_2:
+ Config->TpmVersion = Tcg2PhysicalPresenceTpmVersion12;
+ break;
+
+ case QEMU_TPM_VERSION_2:
+ Config->TpmVersion = Tcg2PhysicalPresenceTpmVersion20;
+ break;
+
+ default:
+ Config->TpmVersion = Tcg2PhysicalPresenceTpmVersionUnknown;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf
new file mode 100644
index 0000000000..0ea0c08d4c
--- /dev/null
+++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Returns the platform specific configuration for the QEMU PPI.
+#
+# Caution: This module requires additional review when modified.
+# This driver will have external input - variable.
+# This external input must be validated carefully to avoid security issue.
+#
+# Copyright (C) 2018, Red Hat, Inc.
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Tcg2PhysicalPresencePlatformLibQemu
+ FILE_GUID = 9336E7F0-6CA1-4E6D-A0E9-DFE5F077AA02
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ DxeTcg2PhysicalPresencePlatformLib.c
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ QemuFwCfgLib
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index ce5d5dda4f..39731bdcb3 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -83,6 +83,10 @@
#
QemuFwCfgLib|Include/Library/QemuFwCfgLib.h
+ ## @libraryclass Reads platform-specific TPM Physical Presence configuration.
+ #
+ Tcg2PhysicalPresencePlatformLib|Include/Library/Tcg2PhysicalPresencePlatformLib.h
+
## @libraryclass S3 support for QEMU fw_cfg
#
QemuFwCfgS3Lib|Include/Library/QemuFwCfgS3Lib.h