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
);
/**
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.
@ -140,6 +152,7 @@ Tpm2DeviceLibConstructor (
)
{
TPM2_PTP_INTERFACE_TYPE PtpInterface;
UINT8 IdleByPass;
//
// Cache current active TpmInterfaceType only when needed
@ -148,5 +161,11 @@ Tpm2DeviceLibConstructor (
PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
}
if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdCRBIdleByPass, IdleByPass);
}
return EFI_SUCCESS;
}

View File

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

View File

@ -34,6 +34,18 @@ Tpm2GetPtpInterface (
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.
@ -97,6 +109,7 @@ Tpm2InstanceLibDTpmConstructor (
{
EFI_STATUS Status;
TPM2_PTP_INTERFACE_TYPE PtpInterface;
UINT8 IdleByPass;
Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device);
if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {
@ -111,6 +124,12 @@ Tpm2InstanceLibDTpmConstructor (
PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
}
if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
PcdSet8S(PcdCRBIdleByPass, IdleByPass);
}
DumpPtpInfo ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
}
return EFI_SUCCESS;

View File

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

View File

@ -174,10 +174,30 @@ PtpCrbTpmCommand (
}
DEBUG ((EFI_D_VERBOSE, "\n"));
);
TpmOutSize = 0;
TpmOutSize = 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
// of 1 by software to Request.cmdReady, as indicated by the Status field
// being cleared to 0.
@ -191,7 +211,7 @@ PtpCrbTpmCommand (
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto Exit;
goto GoIdle_Exit;
}
Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus,
@ -201,11 +221,11 @@ PtpCrbTpmCommand (
);
if (EFI_ERROR (Status)) {
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
// first byte of a command to the Command Buffer and the receipt of a write
// of 1 to Start.
@ -221,7 +241,7 @@ PtpCrbTpmCommand (
MmioWrite32 ((UINTN)&CrbReg->CrbControlResponseSize, sizeof(CrbReg->CrbDataBuffer));
//
// STEP 2:
// STEP 3:
// Command Execution occurs after receipt of a 1 to Start and the TPM
// clearing Start to 0.
//
@ -251,12 +271,12 @@ PtpCrbTpmCommand (
// Still in Command Execution state. Try to goIdle, the behavior is agnostic.
//
Status = EFI_DEVICE_ERROR;
goto Exit;
goto GoIdle_Exit;
}
}
//
// STEP 3:
// STEP 4:
// 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
// software to Request.goIdle.
@ -283,14 +303,17 @@ PtpCrbTpmCommand (
if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {
DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));
Status = EFI_UNSUPPORTED;
goto Exit;
goto GoIdle_Exit;
}
CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
TpmOutSize = SwapBytes32 (Data32);
if (*SizeOut < TpmOutSize) {
//
// Command completed, but buffer is not enough
//
Status = EFI_BUFFER_TOO_SMALL;
goto Exit;
goto GoReady_Exit;
}
*SizeOut = TpmOutSize;
//
@ -299,7 +322,7 @@ PtpCrbTpmCommand (
for (Index = sizeof (TPM2_RESPONSE_HEADER); Index < TpmOutSize; Index++) {
BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]);
}
Exit:
DEBUG_CODE (
DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Receive - "));
for (Index = 0; Index < TpmOutSize; Index++) {
@ -308,11 +331,40 @@ Exit:
DEBUG ((EFI_D_VERBOSE, "\n"));
);
GoReady_Exit:
//
// STEP 4:
// Idle is any time TPM_CRB_CTRL_STS_x.Status.goIdle is 1.
// Goto Ready State if command is completed succesfully and TPM support IdleBypass
// 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);
//
// 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;
}
@ -394,6 +446,28 @@ Tpm2GetPtpInterface (
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.

View File

@ -474,5 +474,15 @@
# @Prompt current active TPM interface type.
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"]
SecurityPkgExtra.uni

View File

@ -254,4 +254,12 @@
"0x00 - FIFO interface as defined in TIS 1.3 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"
"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>"