SecurityPkg: Tpm2DeviceLib: Enable CapCRBIdleBypass support

Directly transition from CMD completion to CMD Ready state if device
supports IdleByPass

Cc: Long Qin <qin.long@intel.com>
Cc: Yao Jiewen <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
Reviewed-by: Long Qin <qin.long@intel.com>
This commit is contained in:
Zhang, Chao B 2018-03-23 14:04:01 +08:00
parent 714eedc5b9
commit 631976706d
7 changed files with 146 additions and 14 deletions

View File

@ -31,6 +31,18 @@ Tpm2GetPtpInterface (
IN VOID *Register IN VOID *Register
); );
/**
Return PTP CRB interface IdleByPass state.
@param[in] Register Pointer to PTP register.
@return PTP CRB interface IdleByPass state.
**/
UINT8
Tpm2GetIdleByPass (
IN VOID *Register
);
/** /**
This service enables the sending of commands to the TPM2. This service enables the sending of commands to the TPM2.
@ -140,6 +152,7 @@ Tpm2DeviceLibConstructor (
) )
{ {
TPM2_PTP_INTERFACE_TYPE PtpInterface; TPM2_PTP_INTERFACE_TYPE PtpInterface;
UINT8 IdleByPass;
// //
// Cache current active TpmInterfaceType only when needed // Cache current active TpmInterfaceType only when needed
@ -148,5 +161,11 @@ Tpm2DeviceLibConstructor (
PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress)); PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface); PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
} }
if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdCRBIdleByPass, IdleByPass);
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }

View File

@ -55,3 +55,4 @@
[Pcd] [Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass ## PRODUCES

View File

@ -34,6 +34,18 @@ Tpm2GetPtpInterface (
IN VOID *Register IN VOID *Register
); );
/**
Return PTP CRB interface IdleByPass state.
@param[in] Register Pointer to PTP register.
@return PTP CRB interface IdleByPass state.
**/
UINT8
Tpm2GetIdleByPass (
IN VOID *Register
);
/** /**
Dump PTP register information. Dump PTP register information.
@ -97,6 +109,7 @@ Tpm2InstanceLibDTpmConstructor (
{ {
EFI_STATUS Status; EFI_STATUS Status;
TPM2_PTP_INTERFACE_TYPE PtpInterface; TPM2_PTP_INTERFACE_TYPE PtpInterface;
UINT8 IdleByPass;
Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device); Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device);
if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) { if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {
@ -111,6 +124,12 @@ Tpm2InstanceLibDTpmConstructor (
PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress)); PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface); PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
} }
if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdCRBIdleByPass, IdleByPass);
}
DumpPtpInfo ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress)); DumpPtpInfo ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
} }
return EFI_SUCCESS; return EFI_SUCCESS;

View File

@ -51,3 +51,4 @@
[Pcd] [Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass ## PRODUCES

View File

@ -174,10 +174,30 @@ PtpCrbTpmCommand (
} }
DEBUG ((EFI_D_VERBOSE, "\n")); DEBUG ((EFI_D_VERBOSE, "\n"));
); );
TpmOutSize = 0; TpmOutSize = 0;
// //
// STEP 0: // STEP 0:
// if CapCRbIdelByPass == 0, enforce Idle state before sending command
//
if (PcdGet8(PcdCRBIdleByPass) == 0 && (MmioRead32((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0){
Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus,
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
0,
PTP_TIMEOUT_C
);
if (EFI_ERROR (Status)) {
//
// Try to goIdle to recover TPM
//
Status = EFI_DEVICE_ERROR;
goto GoIdle_Exit;
}
}
//
// STEP 1:
// Ready is any time the TPM is ready to receive a command, following a write // Ready is any time the TPM is ready to receive a command, following a write
// of 1 by software to Request.cmdReady, as indicated by the Status field // of 1 by software to Request.cmdReady, as indicated by the Status field
// being cleared to 0. // being cleared to 0.
@ -191,7 +211,7 @@ PtpCrbTpmCommand (
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
goto Exit; goto GoIdle_Exit;
} }
Status = PtpCrbWaitRegisterBits ( Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus, &CrbReg->CrbControlStatus,
@ -201,11 +221,11 @@ PtpCrbTpmCommand (
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
goto Exit; goto GoIdle_Exit;
} }
// //
// STEP 1: // STEP 2:
// Command Reception occurs following a Ready state between the write of the // Command Reception occurs following a Ready state between the write of the
// first byte of a command to the Command Buffer and the receipt of a write // first byte of a command to the Command Buffer and the receipt of a write
// of 1 to Start. // of 1 to Start.
@ -221,7 +241,7 @@ PtpCrbTpmCommand (
MmioWrite32 ((UINTN)&CrbReg->CrbControlResponseSize, sizeof(CrbReg->CrbDataBuffer)); MmioWrite32 ((UINTN)&CrbReg->CrbControlResponseSize, sizeof(CrbReg->CrbDataBuffer));
// //
// STEP 2: // STEP 3:
// Command Execution occurs after receipt of a 1 to Start and the TPM // Command Execution occurs after receipt of a 1 to Start and the TPM
// clearing Start to 0. // clearing Start to 0.
// //
@ -251,12 +271,12 @@ PtpCrbTpmCommand (
// Still in Command Execution state. Try to goIdle, the behavior is agnostic. // Still in Command Execution state. Try to goIdle, the behavior is agnostic.
// //
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
goto Exit; goto GoIdle_Exit;
} }
} }
// //
// STEP 3: // STEP 4:
// Command Completion occurs after completion of a command (indicated by the // Command Completion occurs after completion of a command (indicated by the
// TPM clearing TPM_CRB_CTRL_Start_x to 0) and before a write of a 1 by the // TPM clearing TPM_CRB_CTRL_Start_x to 0) and before a write of a 1 by the
// software to Request.goIdle. // software to Request.goIdle.
@ -283,14 +303,17 @@ PtpCrbTpmCommand (
if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) { if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {
DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND)); DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));
Status = EFI_UNSUPPORTED; Status = EFI_UNSUPPORTED;
goto Exit; goto GoIdle_Exit;
} }
CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32)); CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
TpmOutSize = SwapBytes32 (Data32); TpmOutSize = SwapBytes32 (Data32);
if (*SizeOut < TpmOutSize) { if (*SizeOut < TpmOutSize) {
//
// Command completed, but buffer is not enough
//
Status = EFI_BUFFER_TOO_SMALL; Status = EFI_BUFFER_TOO_SMALL;
goto Exit; goto GoReady_Exit;
} }
*SizeOut = TpmOutSize; *SizeOut = TpmOutSize;
// //
@ -299,7 +322,7 @@ PtpCrbTpmCommand (
for (Index = sizeof (TPM2_RESPONSE_HEADER); Index < TpmOutSize; Index++) { for (Index = sizeof (TPM2_RESPONSE_HEADER); Index < TpmOutSize; Index++) {
BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]); BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]);
} }
Exit:
DEBUG_CODE ( DEBUG_CODE (
DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Receive - ")); DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Receive - "));
for (Index = 0; Index < TpmOutSize; Index++) { for (Index = 0; Index < TpmOutSize; Index++) {
@ -308,11 +331,40 @@ Exit:
DEBUG ((EFI_D_VERBOSE, "\n")); DEBUG ((EFI_D_VERBOSE, "\n"));
); );
GoReady_Exit:
// //
// STEP 4: // Goto Ready State if command is completed succesfully and TPM support IdleBypass
// Idle is any time TPM_CRB_CTRL_STS_x.Status.goIdle is 1. // If not supported. flow down to GoIdle
//
if (PcdGet8(PcdCRBIdleByPass) == 1) {
MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);
return Status;
}
//
// Do not wait for state transition for TIMEOUT_C
// This function will try to wait 2 TIMEOUT_C at the beginning in next call.
//
GoIdle_Exit:
//
// Return to Idle state by setting TPM_CRB_CTRL_STS_x.Status.goIdle to 1.
// //
MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE); MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);
//
// Only enforce Idle state transition if execution fails when CRBIndleBypass==1
// Leave regular Idle delay at the beginning of next command execution
//
if (PcdGet8(PcdCRBIdleByPass) == 1){
Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus,
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
0,
PTP_TIMEOUT_C
);
}
return Status; return Status;
} }
@ -394,6 +446,28 @@ Tpm2GetPtpInterface (
return Tpm2PtpInterfaceTis; return Tpm2PtpInterfaceTis;
} }
/**
Return PTP CRB interface IdleByPass state.
@param[in] Register Pointer to PTP register.
@return PTP CRB interface IdleByPass state.
**/
UINT8
Tpm2GetIdleByPass (
IN VOID *Register
)
{
PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;
//
// Check interface id
//
InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
return (UINT8)(InterfaceId.Bits.CapCRBIdleBypass);
}
/** /**
Dump PTP register information. Dump PTP register information.

View File

@ -474,5 +474,15 @@
# @Prompt current active TPM interface type. # @Prompt current active TPM interface type.
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType|0xFF|UINT8|0x0001001E gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType|0xFF|UINT8|0x0001001E
## This PCD records IdleByass status supported by current active TPM interface.
# Accodingt to TCG PTP spec 1.3, TPM with CRB interface can skip idle state and
# diretcly move to CmdReady state. <BR>
# 0x00 - Do not support IdleByPass.<BR>
# 0x01 - Support IdleByPass.<BR>
# 0xFF - IdleByPass State is not synced with TPM hardware.<BR>
#
# @Prompt IdleByass status supported by current active TPM interface.
gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass|0xFF|UINT8|0x0001001F
[UserExtensions.TianoCore."ExtraFiles"] [UserExtensions.TianoCore."ExtraFiles"]
SecurityPkgExtra.uni SecurityPkgExtra.uni

View File

@ -255,3 +255,11 @@
"0x01 - FIFO interface as defined in PTP for TPM 2.0 is active.<BR>\n" "0x01 - FIFO interface as defined in PTP for TPM 2.0 is active.<BR>\n"
"0x02 - CRB interface is active.<BR>\n" "0x02 - CRB interface is active.<BR>\n"
"0xFF - Contains no current active TPM interface type<BR>" "0xFF - Contains no current active TPM interface type<BR>"
#string STR_gEfiSecurityPkgTokenSpaceGuid_PcdCRBIdleByPass_PROMPT #language en-US "IdleByass status supported by current active TPM interface."
#string STR_gEfiSecurityPkgTokenSpaceGuid_PcdCRBIdleByPass_HELP #language en-US "This PCD records IdleByass status supported by current active TPM interface.\n"
"Accodingt to TCG PTP spec 1.3, TPM with CRB interface can skip idle state and diretcly move to CmdReady state. <BR>"
"0x01 - Do not support IdleByPass.<BR>\n"
"0x02 - Support IdleByPass.<BR>\n"
"0xFF - IdleByPass State is not synced with TPM hardware.<BR>"