mirror of https://github.com/acidanthera/audk.git
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:
parent
714eedc5b9
commit
631976706d
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,3 +55,4 @@
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
|
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
|
||||||
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
|
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
|
||||||
|
gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass ## PRODUCES
|
|
@ -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;
|
||||||
|
|
|
@ -51,3 +51,4 @@
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
|
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
|
||||||
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
|
gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## PRODUCES
|
||||||
|
gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass ## PRODUCES
|
|
@ -178,6 +178,26 @@ PtpCrbTpmCommand (
|
||||||
|
|
||||||
//
|
//
|
||||||
// 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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>"
|
Loading…
Reference in New Issue