alder_lake_bios/Insyde/InsydeModulePkg/Universal/Security/Tcg/TrEEConfigPei/TrEEConfigPeim.c

464 lines
13 KiB
C

/** @file
TrEE configuration module.
;******************************************************************************
;* Copyright (c) 2013 - 2019, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include <PiPei.h>
#include <Guid/TpmInstance.h>
#include <Guid/TcmInstance.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/Tpm12DeviceLib.h>
#include <Library/Tpm12CommandLib.h>
#include <Library/KernelConfigLib.h>
#include <Library/TcmDeviceLib.h>
#include <Ppi/MasterBootMode.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/TpmInitialized.h>
#include <IndustryStandard/Tpm12.h>
#include <KernelSetupConfig.h>
#include <TpmPolicy.h>
#define TPM_INSTANCE_ID_LIST { \
{TPM_DEVICE_INTERFACE_NONE, TPM_DEVICE_NULL}, \
{TPM_DEVICE_INTERFACE_TPM12, TPM_DEVICE_1_2}, \
{TPM_DEVICE_INTERFACE_TPM20_DTPM, TPM_DEVICE_2_0}, \
{TPM_DEVICE_INTERFACE_TCM, TPM_DEVICE_TCM}, \
}
typedef struct {
GUID TpmInstanceGuid;
UINT8 TpmDevice;
} TPM_INSTANCE_ID;
TPM_INSTANCE_ID mTpmInstanceId[] = TPM_INSTANCE_ID_LIST;
CONST EFI_PEI_PPI_DESCRIPTOR gTpmSelectedPpi = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiTpmDeviceSelectedGuid,
NULL
};
EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gPeiTpmInitializationDonePpiGuid,
NULL
};
/**
Callback for TrEE configuration driver.
@param FileHandle Handle of the file being invoked.
@param NotifyDescriptor Describes the list of possible PEI Services.
@retval EFI_SUCCES Convert variable to PCD successfully.
@retval Others Fail to convert variable to PCD.
**/
EFI_STATUS
EFIAPI
BootModePpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
/**
Install TpmSelectedPpi at memory discovered to notify other drivers.
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param[in] NotifyDescriptor Address of the notification descriptor data structure.
@param[in] Ppi Address of the PPI that was installed.
@retval EFI_SUCCESS Operation completed successfully.
@retval Others Operation failed.
**/
EFI_STATUS
EFIAPI
MemoryDiscoveredPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
);
EFI_PEI_NOTIFY_DESCRIPTOR mBootModeNotifyList[] = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiMasterBootModePpiGuid,
BootModePpiNotifyCallback
};
EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList =
{
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiPeiMemoryDiscoveredPpiGuid,
MemoryDiscoveredPpiNotifyCallback
};
/**
Install TpmSelectedPpi to notify other drivers.
@retval EFI_SUCCESS Operation completed successfully.
@retval Others Operation failed.
**/
STATIC
EFI_STATUS
TpmSelectionDone (
)
{
EFI_STATUS Status;
//
// Selection done
//
Status = PeiServicesInstallPpi (&gTpmSelectedPpi);
ASSERT_EFI_ERROR (Status);
//
// Even if no TPM is selected or detected, we still need intall TpmInitializationDonePpi.
// Because TcgPei or TrEEPei will not run, but we still need a way to notify other driver.
// Other driver can know TPM initialization state by TpmInitializedPpi.
// Also, install TpmInitializationDonePpi if TPM has been hidden.
//
if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
PcdGetBool (PcdTpmHide)) {
Status = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
ASSERT_EFI_ERROR (Status);
//
// Remove Type 43(TPM Device) from SMBIOS table
//
Status = PcdSetBoolS (PcdActiveSmbiosType043, FALSE);
ASSERT_EFI_ERROR (Status);
}
return Status;
}
/**
Install TpmSelectedPpi at memory discovered to notify other drivers.
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param[in] NotifyDescriptor Address of the notification descriptor data structure.
@param[in] Ppi Address of the PPI that was installed.
@retval EFI_SUCCESS Operation completed successfully.
@retval Others Operation failed.
**/
EFI_STATUS
EFIAPI
MemoryDiscoveredPpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
return TpmSelectionDone ();
}
/**
Send TPM_ContinueSelfTest command to TPM.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_TIMEOUT The register can't run into the expected status in time.
@retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.
@retval EFI_DEVICE_ERROR Unexpected device behavior.
**/
EFI_STATUS
TpmContinueSelfTest (
VOID
)
{
EFI_STATUS Status;
UINT32 TpmRecvSize;
UINT32 TpmSendSize;
TPM_RQU_COMMAND_HDR SendBuffer;
UINT8 RecvBuffer[20];
//
// send Tpm command TPM_ORD_ContinueSelfTest
//
TpmRecvSize = 20;
TpmSendSize = sizeof (TPM_RQU_COMMAND_HDR);
SendBuffer.tag = SwapBytes16 (TPM_TAG_RQU_COMMAND);
SendBuffer.paramSize = SwapBytes32 (TpmSendSize);
SendBuffer.ordinal = SwapBytes32 (TPM_ORD_ContinueSelfTest);
Status = Tpm12SubmitCommand (TpmSendSize, (UINT8 *)&SendBuffer, &TpmRecvSize, RecvBuffer);
return Status;
}
/**
This routine return if TCM present.
@retval TRUE dTPM present
@retval FALSE dTPM not present
**/
BOOLEAN
IsTcmPresent (
VOID
)
{
return !EFI_ERROR (TisPcRequestUseTcm ());
}
/**
This routine return if dTPM (1.2 or 2.0) present.
@retval TRUE dTPM present
@retval FALSE dTPM not present
**/
BOOLEAN
IsDtpmPresent (
VOID
)
{
UINT8 RegRead;
RegRead = MmioRead8 ((UINTN)PcdGet64 (PcdTpmBaseAddress));
if (RegRead == 0xFF) {
DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm not present\n"));
return FALSE;
} else {
DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm present\n"));
return TRUE;
}
}
/**
This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
@param SetupTpmDevice TpmDevice configuration in setup driver
@param ByPassTpmInit If TRUE, tries TpmSelfTest to identify TPM.
If FALSE, tries TpmStartup to identify TPM.
@return TpmDevice configuration
**/
UINT8
DetectTpmDevice (
IN UINT8 SetupTpmDevice,
IN BOOLEAN ByPassTpmInit
)
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
UINT32 TpmPolicy;
Status = PeiServicesGetBootMode (&BootMode);
ASSERT_EFI_ERROR (Status);
//
// In S3, we rely on normal boot Detection
//
if (BootMode == BOOT_ON_S3_RESUME) {
DEBUG ((EFI_D_ERROR, "DetectTpmDevice: S3 mode\n"));
DEBUG ((EFI_D_ERROR, "TpmDevice from DeviceDetection: %x\n", SetupTpmDevice));
if (PcdGetBool (PcdTpmHide)) {
//
// Activate the TPM when TPM is hidden, in order to prevent the time-out of
// following command executions.
// For CRB-interface of TPM, returned error is acceptable.
//
Tpm12RequestUseTpm ();
}
return SetupTpmDevice;
}
DEBUG ((EFI_D_ERROR, "DetectTpmDevice:\n"));
if (!IsDtpmPresent ()) {
//
// dTPM not available
//
return TPM_DEVICE_NULL;
}
if ((PcdGet32 (PcdPeiTpmPolicy) & SKIP_PEI_TPM_AUTO_DETECTION) != 0) {
DEBUG ((EFI_D_INFO, "PeiTpmPolicy: Skip TPM auto detection\n"));
return TPM_DEVICE_NULL;
}
if (IsTcmPresent ()) {
//
// TCM detected
//
DEBUG ((EFI_D_ERROR, "TCM detected.\n"));
return TPM_DEVICE_TCM;
}
//
// Check if it is TPM1.2 or TPM2.0 by tring TPM1.2 command at first
//
Status = Tpm12RequestUseTpm ();
if (EFI_ERROR (Status)) {
return TPM_DEVICE_2_0;
}
if (ByPassTpmInit) {
Status = TpmContinueSelfTest ();
TpmPolicy = PcdGet32 (PcdPeiTpmPolicy) | SKIP_TPM_SELF_TEST;
} else {
Status = Tpm12Startup (TPM_ST_CLEAR);
TpmPolicy = PcdGet32 (PcdPeiTpmPolicy) | SKIP_TPM_STARTUP;
}
if (EFI_ERROR (Status)) {
return TPM_DEVICE_2_0;
}
Status = PcdSet32S (PcdPeiTpmPolicy, TpmPolicy);
ASSERT_EFI_ERROR (Status);
return TPM_DEVICE_1_2;
}
/**
Callback for TrEE configuration driver.
@param FileHandle Handle of the file being invoked.
@param NotifyDescriptor Describes the list of possible PEI Services.
@retval EFI_SUCCES Convert variable to PCD successfully.
@retval Others Fail to convert variable to PCD.
**/
EFI_STATUS
EFIAPI
BootModePpiNotifyCallback (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
EFI_STATUS Status;
KERNEL_CONFIGURATION KernelConfiguration;
UINTN Size;
UINTN Index;
UINT8 TpmDevice;
BOOLEAN ByPassTpmInit;
if (!CompareGuid (NotifyDescriptor->Guid, &gEfiPeiMasterBootModePpiGuid)) {
return EFI_UNSUPPORTED;
}
Status = GetKernelConfiguration (&KernelConfiguration);
if (EFI_ERROR (Status) ||
KernelConfiguration.TpmDevice > TPM_DEVICE_MAX) {
//
// Variable not ready or incorrect, set default value
//
if (PcdGetBool (PcdH2OTpm2Supported)) {
KernelConfiguration.TpmDevice = TPM_DEVICE_2_0;
} else {
KernelConfiguration.TpmDevice = TPM_DEVICE_1_2;
}
KernelConfiguration.TpmHide = 0;
}
Status = PcdSetBoolS (PcdTpmHide, KernelConfiguration.TpmHide);
ASSERT_EFI_ERROR (Status);
Status = PcdSet8S (PcdTrEEProtocolVersion, KernelConfiguration.TrEEVersion);
ASSERT_EFI_ERROR (Status);
//
// Although we have setup variable info, we still need detect TPM device manually.
//
DEBUG ((EFI_D_ERROR, "KernelConfiguration.TpmDevice from Setup: %x\n", KernelConfiguration.TpmDevice));
if (PcdGetBool (PcdTpmAutoDetection)) {
ByPassTpmInit = ((PcdGet32 (PcdPeiTpmPolicy) & SKIP_TPM_STARTUP) == 0) ? FALSE : TRUE;
TpmDevice = DetectTpmDevice (KernelConfiguration.TpmDevice, ByPassTpmInit);
DEBUG ((EFI_D_ERROR, "TpmDevice final: %x\n", TpmDevice));
if (TpmDevice != TPM_DEVICE_NULL) {
KernelConfiguration.TpmDevice = TpmDevice;
}
} else {
TpmDevice = KernelConfiguration.TpmDevice;
}
//
// Check whether the selected TPM is changed.
// Don't hide TPM if TPM is changed
//
switch (TpmDevice) {
case TPM_DEVICE_2_0:
if (KernelConfiguration.TpmDeviceOk == 1) {
Status = PcdSetBoolS (PcdTpmHide, FALSE);
ASSERT_EFI_ERROR (Status);
}
break;
case TPM_DEVICE_1_2:
case TPM_DEVICE_TCM:
if (KernelConfiguration.Tpm2DeviceOk == 1) {
Status = PcdSetBoolS (PcdTpmHide, FALSE);
ASSERT_EFI_ERROR (Status);
}
break;
}
//
// Convert variable to PCD.
//
for (Index = 0; Index < sizeof (mTpmInstanceId) / sizeof (mTpmInstanceId[0]); Index++) {
if (TpmDevice == mTpmInstanceId[Index].TpmDevice) {
Size = sizeof (mTpmInstanceId[Index].TpmInstanceGuid);
Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid);
ASSERT_EFI_ERROR (Status);
break;
}
}
if ((PcdGet32 (PcdPeiTpmPolicy) & TPM2_STARTUP_IN_MP) == 0) {
Status = TpmSelectionDone ();
} else {
//
// Postpone TpmSelectedPpi installation to memory discovered
//
Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList);
}
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
The entry point for TrEE configuration driver.
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
@retval EFI_SUCCES Successfully registers BootMode service to be invoked
@retval Others Fail to register a callback
**/
EFI_STATUS
EFIAPI
TrEEConfigPeimEntryPoint (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
Status = PeiServicesNotifyPpi (mBootModeNotifyList);
ASSERT_EFI_ERROR (Status);
return Status;
}